// 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 "src/debug/debug-frames.h" #include "src/frames.h" namespace v8 { namespace internal { // 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, ScopeTypeModule }; static const int kScopeDetailsTypeIndex = 0; static const int kScopeDetailsObjectIndex = 1; static const int kScopeDetailsNameIndex = 2; static const int kScopeDetailsSize = 3; enum Option { DEFAULT, IGNORE_NESTED_SCOPES, COLLECT_NON_LOCALS }; ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector, Option options = DEFAULT); ScopeIterator(Isolate* isolate, Handle function); ~ScopeIterator() { delete non_locals_; } MUST_USE_RESULT MaybeHandle MaterializeScopeDetails(); // More scopes? bool Done() { DCHECK(!failed_); return context_.is_null(); } bool Failed() { return failed_; } // Move to the next scope. void Next(); // Return the type of the current scope. ScopeType Type(); // Return the JavaScript object with the content of the current scope. MaybeHandle ScopeObject(); bool HasContext(); // Set variable value and return true on success. bool SetVariableValue(Handle variable_name, Handle new_value); Handle CurrentScopeInfo(); // Return the context for this scope. For the local context there might not // be an actual context. Handle CurrentContext(); // Populate the list with collected non-local variable names. void GetNonLocals(List >* list_out); bool ThisIsNonLocal(); #ifdef DEBUG // Debug print of the content of the current scope. void DebugPrint(); #endif private: Isolate* isolate_; FrameInspector* const frame_inspector_; Handle context_; List > nested_scope_chain_; HashMap* non_locals_; bool seen_script_scope_; bool failed_; inline JavaScriptFrame* GetFrame() { return frame_inspector_->GetArgumentsFrame(); } inline Handle GetFunction() { return Handle( JSFunction::cast(frame_inspector_->GetFunction())); } static bool InternalizedStringMatch(void* key1, void* key2) { Handle s1(reinterpret_cast(key1)); Handle s2(reinterpret_cast(key2)); DCHECK(s1->IsInternalizedString()); DCHECK(s2->IsInternalizedString()); return s1.is_identical_to(s2); } void RetrieveScopeChain(Scope* scope); void CollectNonLocals(Scope* scope); MUST_USE_RESULT MaybeHandle MaterializeScriptScope(); MUST_USE_RESULT MaybeHandle MaterializeLocalScope(); MUST_USE_RESULT MaybeHandle MaterializeModuleScope(); Handle MaterializeClosure(); Handle MaterializeCatchScope(); Handle MaterializeBlockScope(); bool SetLocalVariableValue(Handle variable_name, Handle new_value); bool SetBlockVariableValue(Handle variable_name, Handle new_value); bool SetClosureVariableValue(Handle variable_name, Handle new_value); bool SetScriptVariableValue(Handle variable_name, Handle new_value); bool SetCatchVariableValue(Handle variable_name, Handle new_value); bool SetContextLocalValue(Handle scope_info, Handle context, Handle variable_name, Handle new_value); void CopyContextLocalsToScopeObject(Handle scope_info, Handle context, Handle scope_object); bool CopyContextExtensionToScopeObject(Handle extension, Handle scope_object, JSReceiver::KeyCollectionType type); DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); }; } // namespace internal } // namespace v8 #endif // V8_DEBUG_DEBUG_SCOPES_H_