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 <vector> 9 10 #include "src/debug/debug-frames.h" 11 12 namespace v8 { 13 namespace internal { 14 15 class JavaScriptFrame; 16 class ParseInfo; 17 18 // Iterate over the actual scopes visible from a stack frame or from a closure. 19 // The iteration proceeds from the innermost visible nested scope outwards. 20 // All scopes are backed by an actual context except the local scope, 21 // which is inserted "artificially" in the context chain. 22 class ScopeIterator { 23 public: 24 enum ScopeType { 25 ScopeTypeGlobal = 0, 26 ScopeTypeLocal, 27 ScopeTypeWith, 28 ScopeTypeClosure, 29 ScopeTypeCatch, 30 ScopeTypeBlock, 31 ScopeTypeScript, 32 ScopeTypeEval, 33 ScopeTypeModule 34 }; 35 36 static const int kScopeDetailsTypeIndex = 0; 37 static const int kScopeDetailsObjectIndex = 1; 38 static const int kScopeDetailsNameIndex = 2; 39 static const int kScopeDetailsStartPositionIndex = 3; 40 static const int kScopeDetailsEndPositionIndex = 4; 41 static const int kScopeDetailsFunctionIndex = 5; 42 static const int kScopeDetailsSize = 6; 43 44 enum class ReparseStrategy { 45 kScript, 46 kFunctionLiteral, 47 }; 48 49 ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector, 50 ReparseStrategy strategy); 51 52 ScopeIterator(Isolate* isolate, Handle<JSFunction> function); 53 ScopeIterator(Isolate* isolate, Handle<JSGeneratorObject> generator); 54 ~ScopeIterator(); 55 56 Handle<JSObject> MaterializeScopeDetails(); 57 58 // More scopes? Done()59 bool Done() const { return context_.is_null(); } 60 61 // Move to the next scope. 62 void Next(); 63 64 // Restart to the first scope and context. 65 void Restart(); 66 67 // Return the type of the current scope. 68 ScopeType Type() const; 69 70 // Indicates which variables should be visited. Either only variables from the 71 // scope that are available on the stack, or all variables. 72 enum class Mode { STACK, ALL }; 73 74 // Return the JavaScript object with the content of the current scope. 75 Handle<JSObject> ScopeObject(Mode mode); 76 77 // Returns whether the current scope declares any variables. 78 bool DeclaresLocals(Mode mode) const; 79 80 // Set variable value and return true on success. 81 bool SetVariableValue(Handle<String> variable_name, Handle<Object> new_value); 82 83 bool ClosureScopeHasThisReference() const; 84 85 // Populate the set with collected non-local variable names. GetLocals()86 Handle<StringSet> GetLocals() { return locals_; } 87 88 // Similar to JSFunction::GetName return the function's name or it's inferred 89 // name. 90 Handle<Object> GetFunctionDebugName() const; 91 GetScript()92 Handle<Script> GetScript() const { return script_; } 93 94 bool HasPositionInfo(); 95 int start_position(); 96 int end_position(); 97 98 #ifdef DEBUG 99 // Debug print of the content of the current scope. 100 void DebugPrint(); 101 #endif 102 InInnerScope()103 bool InInnerScope() const { return !function_.is_null(); } 104 bool HasContext() const; 105 bool NeedsAndHasContext() const; CurrentContext()106 Handle<Context> CurrentContext() const { 107 DCHECK(HasContext()); 108 return context_; 109 } 110 111 private: 112 Isolate* isolate_; 113 std::unique_ptr<ParseInfo> info_; 114 FrameInspector* const frame_inspector_ = nullptr; 115 Handle<JSGeneratorObject> generator_; 116 117 // The currently-executing function from the inspected frame, or null if this 118 // ScopeIterator has already iterated to any Scope outside that function. 119 Handle<JSFunction> function_; 120 121 Handle<Context> context_; 122 Handle<Script> script_; 123 Handle<StringSet> locals_; 124 DeclarationScope* closure_scope_ = nullptr; 125 Scope* start_scope_ = nullptr; 126 Scope* current_scope_ = nullptr; 127 bool seen_script_scope_ = false; 128 GetFrame()129 inline JavaScriptFrame* GetFrame() const { 130 return frame_inspector_->javascript_frame(); 131 } 132 133 void AdvanceOneScope(); 134 void AdvanceToNonHiddenScope(); 135 void AdvanceContext(); 136 void CollectLocalsFromCurrentScope(); 137 138 int GetSourcePosition(); 139 140 void TryParseAndRetrieveScopes(ReparseStrategy strategy); 141 142 void UnwrapEvaluationContext(); 143 144 using Visitor = std::function<bool(Handle<String> name, Handle<Object> value, 145 ScopeType scope_type)>; 146 147 Handle<JSObject> WithContextExtension(); 148 149 bool SetLocalVariableValue(Handle<String> variable_name, 150 Handle<Object> new_value); 151 bool SetContextVariableValue(Handle<String> variable_name, 152 Handle<Object> new_value); 153 bool SetContextExtensionValue(Handle<String> variable_name, 154 Handle<Object> new_value); 155 bool SetScriptVariableValue(Handle<String> variable_name, 156 Handle<Object> new_value); 157 bool SetModuleVariableValue(Handle<String> variable_name, 158 Handle<Object> new_value); 159 160 // Helper functions. 161 void VisitScope(const Visitor& visitor, Mode mode) const; 162 void VisitLocalScope(const Visitor& visitor, Mode mode, 163 ScopeType scope_type) const; 164 void VisitScriptScope(const Visitor& visitor) const; 165 void VisitModuleScope(const Visitor& visitor) const; 166 bool VisitLocals(const Visitor& visitor, Mode mode, 167 ScopeType scope_type) const; 168 bool VisitContextLocals(const Visitor& visitor, Handle<ScopeInfo> scope_info, 169 Handle<Context> context, ScopeType scope_type) const; 170 171 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); 172 }; 173 174 } // namespace internal 175 } // namespace v8 176 177 #endif // V8_DEBUG_DEBUG_SCOPES_H_ 178