1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_DEBUG_DEBUG_SCOPES_H_ 6 #define V8_DEBUG_DEBUG_SCOPES_H_ 7 8 #include "src/debug/debug-frames.h" 9 #include "src/frames.h" 10 11 namespace v8 { 12 namespace internal { 13 14 class ParseInfo; 15 16 // Iterate over the actual scopes visible from a stack frame or from a closure. 17 // The iteration proceeds from the innermost visible nested scope outwards. 18 // All scopes are backed by an actual context except the local scope, 19 // which is inserted "artificially" in the context chain. 20 class ScopeIterator { 21 public: 22 enum ScopeType { 23 ScopeTypeGlobal = 0, 24 ScopeTypeLocal, 25 ScopeTypeWith, 26 ScopeTypeClosure, 27 ScopeTypeCatch, 28 ScopeTypeBlock, 29 ScopeTypeScript, 30 ScopeTypeEval, 31 ScopeTypeModule 32 }; 33 34 static const int kScopeDetailsTypeIndex = 0; 35 static const int kScopeDetailsObjectIndex = 1; 36 static const int kScopeDetailsNameIndex = 2; 37 static const int kScopeDetailsStartPositionIndex = 3; 38 static const int kScopeDetailsEndPositionIndex = 4; 39 static const int kScopeDetailsFunctionIndex = 5; 40 static const int kScopeDetailsSize = 6; 41 42 enum Option { DEFAULT, IGNORE_NESTED_SCOPES, COLLECT_NON_LOCALS }; 43 44 ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector, 45 Option options = DEFAULT); 46 47 ScopeIterator(Isolate* isolate, Handle<JSFunction> function); 48 ScopeIterator(Isolate* isolate, Handle<JSGeneratorObject> generator); 49 50 MUST_USE_RESULT MaybeHandle<JSObject> MaterializeScopeDetails(); 51 52 // More scopes? Done()53 bool Done() { 54 DCHECK(!failed_); 55 return context_.is_null(); 56 } 57 Failed()58 bool Failed() { return failed_; } 59 60 // Move to the next scope. 61 void Next(); 62 63 // Return the type of the current scope. 64 ScopeType Type(); 65 66 // Return the JavaScript object with the content of the current scope. 67 MaybeHandle<JSObject> ScopeObject(); 68 69 bool HasContext(); 70 71 // Set variable value and return true on success. 72 bool SetVariableValue(Handle<String> variable_name, Handle<Object> new_value); 73 74 Handle<ScopeInfo> CurrentScopeInfo(); 75 76 // Return the context for this scope. For the local context there might not 77 // be an actual context. 78 Handle<Context> CurrentContext(); 79 80 // Populate the set with collected non-local variable names. 81 Handle<StringSet> GetNonLocals(); 82 83 #ifdef DEBUG 84 // Debug print of the content of the current scope. 85 void DebugPrint(); 86 #endif 87 88 private: 89 struct ExtendedScopeInfo { ExtendedScopeInfoExtendedScopeInfo90 ExtendedScopeInfo(Handle<ScopeInfo> info, int start, int end) 91 : scope_info(info), start_position(start), end_position(end) {} ExtendedScopeInfoExtendedScopeInfo92 explicit ExtendedScopeInfo(Handle<ScopeInfo> info) 93 : scope_info(info), start_position(-1), end_position(-1) {} 94 Handle<ScopeInfo> scope_info; 95 int start_position; 96 int end_position; is_hiddenExtendedScopeInfo97 bool is_hidden() { return start_position == -1 && end_position == -1; } 98 }; 99 100 Isolate* isolate_; 101 FrameInspector* const frame_inspector_; 102 Handle<Context> context_; 103 List<ExtendedScopeInfo> nested_scope_chain_; 104 Handle<StringSet> non_locals_; 105 bool seen_script_scope_; 106 bool failed_; 107 GetFrame()108 inline JavaScriptFrame* GetFrame() { 109 return frame_inspector_->GetArgumentsFrame(); 110 } 111 GetFunction()112 inline Handle<JSFunction> GetFunction() { 113 return frame_inspector_->GetFunction(); 114 } 115 116 void RetrieveScopeChain(DeclarationScope* scope); 117 118 void CollectNonLocals(ParseInfo* info, DeclarationScope* scope); 119 120 void UnwrapEvaluationContext(); 121 122 MUST_USE_RESULT MaybeHandle<JSObject> MaterializeScriptScope(); 123 MUST_USE_RESULT MaybeHandle<JSObject> MaterializeLocalScope(); 124 MUST_USE_RESULT MaybeHandle<JSObject> MaterializeModuleScope(); 125 Handle<JSObject> MaterializeClosure(); 126 Handle<JSObject> MaterializeCatchScope(); 127 Handle<JSObject> MaterializeInnerScope(); 128 Handle<JSObject> WithContextExtension(); 129 130 bool SetLocalVariableValue(Handle<String> variable_name, 131 Handle<Object> new_value); 132 bool SetInnerScopeVariableValue(Handle<String> variable_name, 133 Handle<Object> new_value); 134 bool SetClosureVariableValue(Handle<String> variable_name, 135 Handle<Object> new_value); 136 bool SetScriptVariableValue(Handle<String> variable_name, 137 Handle<Object> new_value); 138 bool SetCatchVariableValue(Handle<String> variable_name, 139 Handle<Object> new_value); 140 141 // Helper functions. 142 bool SetParameterValue(Handle<ScopeInfo> scope_info, JavaScriptFrame* frame, 143 Handle<String> parameter_name, 144 Handle<Object> new_value); 145 bool SetStackVariableValue(Handle<ScopeInfo> scope_info, 146 Handle<String> variable_name, 147 Handle<Object> new_value); 148 bool SetContextVariableValue(Handle<ScopeInfo> scope_info, 149 Handle<Context> context, 150 Handle<String> variable_name, 151 Handle<Object> new_value); 152 153 void CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info, 154 Handle<Context> context, 155 Handle<JSObject> scope_object); 156 void CopyModuleVarsToScopeObject(Handle<ScopeInfo> scope_info, 157 Handle<Context> context, 158 Handle<JSObject> scope_object); 159 void CopyContextExtensionToScopeObject(Handle<Context> context, 160 Handle<JSObject> scope_object, 161 KeyCollectionMode mode); 162 163 // Get the chain of nested scopes within this scope for the source statement 164 // position. The scopes will be added to the list from the outermost scope to 165 // the innermost scope. Only nested block, catch or with scopes are tracked 166 // and will be returned, but no inner function scopes. 167 void GetNestedScopeChain(Isolate* isolate, Scope* scope, 168 int statement_position); 169 170 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); 171 }; 172 173 } // namespace internal 174 } // namespace v8 175 176 #endif // V8_DEBUG_DEBUG_SCOPES_H_ 177