| // Copyright 2015 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_DEBUG_DEBUG_SCOPES_H_ |
| #define V8_DEBUG_DEBUG_SCOPES_H_ |
| |
| #include <vector> |
| |
| #include "src/debug/debug-frames.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| class JavaScriptFrame; |
| class ParseInfo; |
| |
| // Iterate over the actual scopes visible from a stack frame or from a closure. |
| // The iteration proceeds from the innermost visible nested scope outwards. |
| // All scopes are backed by an actual context except the local scope, |
| // which is inserted "artificially" in the context chain. |
| class ScopeIterator { |
| public: |
| enum ScopeType { |
| ScopeTypeGlobal = 0, |
| ScopeTypeLocal, |
| ScopeTypeWith, |
| ScopeTypeClosure, |
| ScopeTypeCatch, |
| ScopeTypeBlock, |
| ScopeTypeScript, |
| ScopeTypeEval, |
| ScopeTypeModule |
| }; |
| |
| static const int kScopeDetailsTypeIndex = 0; |
| static const int kScopeDetailsObjectIndex = 1; |
| static const int kScopeDetailsNameIndex = 2; |
| static const int kScopeDetailsStartPositionIndex = 3; |
| static const int kScopeDetailsEndPositionIndex = 4; |
| static const int kScopeDetailsFunctionIndex = 5; |
| static const int kScopeDetailsSize = 6; |
| |
| enum class ReparseStrategy { |
| kScript, |
| kFunctionLiteral, |
| }; |
| |
| ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector, |
| ReparseStrategy strategy); |
| |
| ScopeIterator(Isolate* isolate, Handle<JSFunction> function); |
| ScopeIterator(Isolate* isolate, Handle<JSGeneratorObject> generator); |
| ~ScopeIterator(); |
| |
| Handle<JSObject> MaterializeScopeDetails(); |
| |
| // More scopes? |
| bool Done() const { return context_.is_null(); } |
| |
| // Move to the next scope. |
| void Next(); |
| |
| // Restart to the first scope and context. |
| void Restart(); |
| |
| // Return the type of the current scope. |
| ScopeType Type() const; |
| |
| // Indicates which variables should be visited. Either only variables from the |
| // scope that are available on the stack, or all variables. |
| enum class Mode { STACK, ALL }; |
| |
| // Return the JavaScript object with the content of the current scope. |
| Handle<JSObject> ScopeObject(Mode mode); |
| |
| // Returns whether the current scope declares any variables. |
| bool DeclaresLocals(Mode mode) const; |
| |
| // Set variable value and return true on success. |
| bool SetVariableValue(Handle<String> variable_name, Handle<Object> new_value); |
| |
| bool ClosureScopeHasThisReference() const; |
| |
| // Populate the set with collected non-local variable names. |
| Handle<StringSet> GetLocals() { return locals_; } |
| |
| // Similar to JSFunction::GetName return the function's name or it's inferred |
| // name. |
| Handle<Object> GetFunctionDebugName() const; |
| |
| Handle<Script> GetScript() const { return script_; } |
| |
| bool HasPositionInfo(); |
| int start_position(); |
| int end_position(); |
| |
| #ifdef DEBUG |
| // Debug print of the content of the current scope. |
| void DebugPrint(); |
| #endif |
| |
| bool InInnerScope() const { return !function_.is_null(); } |
| bool HasContext() const; |
| bool NeedsAndHasContext() const; |
| Handle<Context> CurrentContext() const { |
| DCHECK(HasContext()); |
| return context_; |
| } |
| |
| private: |
| Isolate* isolate_; |
| std::unique_ptr<ParseInfo> info_; |
| FrameInspector* const frame_inspector_ = nullptr; |
| Handle<JSGeneratorObject> generator_; |
| |
| // The currently-executing function from the inspected frame, or null if this |
| // ScopeIterator has already iterated to any Scope outside that function. |
| Handle<JSFunction> function_; |
| |
| Handle<Context> context_; |
| Handle<Script> script_; |
| Handle<StringSet> locals_; |
| DeclarationScope* closure_scope_ = nullptr; |
| Scope* start_scope_ = nullptr; |
| Scope* current_scope_ = nullptr; |
| bool seen_script_scope_ = false; |
| |
| inline JavaScriptFrame* GetFrame() const { |
| return frame_inspector_->javascript_frame(); |
| } |
| |
| void AdvanceOneScope(); |
| void AdvanceToNonHiddenScope(); |
| void AdvanceContext(); |
| void CollectLocalsFromCurrentScope(); |
| |
| int GetSourcePosition(); |
| |
| void TryParseAndRetrieveScopes(ReparseStrategy strategy); |
| |
| void UnwrapEvaluationContext(); |
| |
| using Visitor = std::function<bool(Handle<String> name, Handle<Object> value, |
| ScopeType scope_type)>; |
| |
| Handle<JSObject> WithContextExtension(); |
| |
| bool SetLocalVariableValue(Handle<String> variable_name, |
| Handle<Object> new_value); |
| bool SetContextVariableValue(Handle<String> variable_name, |
| Handle<Object> new_value); |
| bool SetContextExtensionValue(Handle<String> variable_name, |
| Handle<Object> new_value); |
| bool SetScriptVariableValue(Handle<String> variable_name, |
| Handle<Object> new_value); |
| bool SetModuleVariableValue(Handle<String> variable_name, |
| Handle<Object> new_value); |
| |
| // Helper functions. |
| void VisitScope(const Visitor& visitor, Mode mode) const; |
| void VisitLocalScope(const Visitor& visitor, Mode mode, |
| ScopeType scope_type) const; |
| void VisitScriptScope(const Visitor& visitor) const; |
| void VisitModuleScope(const Visitor& visitor) const; |
| bool VisitLocals(const Visitor& visitor, Mode mode, |
| ScopeType scope_type) const; |
| bool VisitContextLocals(const Visitor& visitor, Handle<ScopeInfo> scope_info, |
| Handle<Context> context, ScopeType scope_type) const; |
| |
| DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); |
| }; |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_DEBUG_DEBUG_SCOPES_H_ |