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