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     ScopeTypeModule
29   };
30 
31   static const int kScopeDetailsTypeIndex = 0;
32   static const int kScopeDetailsObjectIndex = 1;
33   static const int kScopeDetailsNameIndex = 2;
34   static const int kScopeDetailsSize = 3;
35 
36   enum Option { DEFAULT, IGNORE_NESTED_SCOPES, COLLECT_NON_LOCALS };
37 
38   ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector,
39                 Option options = DEFAULT);
40 
41   ScopeIterator(Isolate* isolate, Handle<JSFunction> function);
42 
~ScopeIterator()43   ~ScopeIterator() { delete non_locals_; }
44 
45   MUST_USE_RESULT MaybeHandle<JSObject> MaterializeScopeDetails();
46 
47   // More scopes?
Done()48   bool Done() {
49     DCHECK(!failed_);
50     return context_.is_null();
51   }
52 
Failed()53   bool Failed() { return failed_; }
54 
55   // Move to the next scope.
56   void Next();
57 
58   // Return the type of the current scope.
59   ScopeType Type();
60 
61   // Return the JavaScript object with the content of the current scope.
62   MaybeHandle<JSObject> ScopeObject();
63 
64   bool HasContext();
65 
66   // Set variable value and return true on success.
67   bool SetVariableValue(Handle<String> variable_name, Handle<Object> new_value);
68 
69   Handle<ScopeInfo> CurrentScopeInfo();
70 
71   // Return the context for this scope. For the local context there might not
72   // be an actual context.
73   Handle<Context> CurrentContext();
74 
75   // Populate the list with collected non-local variable names.
76   void GetNonLocals(List<Handle<String> >* list_out);
77 
78   bool ThisIsNonLocal();
79 
80 #ifdef DEBUG
81   // Debug print of the content of the current scope.
82   void DebugPrint();
83 #endif
84 
85  private:
86   Isolate* isolate_;
87   FrameInspector* const frame_inspector_;
88   Handle<Context> context_;
89   List<Handle<ScopeInfo> > nested_scope_chain_;
90   HashMap* non_locals_;
91   bool seen_script_scope_;
92   bool failed_;
93 
GetFrame()94   inline JavaScriptFrame* GetFrame() {
95     return frame_inspector_->GetArgumentsFrame();
96   }
97 
GetFunction()98   inline Handle<JSFunction> GetFunction() {
99     return Handle<JSFunction>(
100         JSFunction::cast(frame_inspector_->GetFunction()));
101   }
102 
InternalizedStringMatch(void * key1,void * key2)103   static bool InternalizedStringMatch(void* key1, void* key2) {
104     Handle<String> s1(reinterpret_cast<String**>(key1));
105     Handle<String> s2(reinterpret_cast<String**>(key2));
106     DCHECK(s1->IsInternalizedString());
107     DCHECK(s2->IsInternalizedString());
108     return s1.is_identical_to(s2);
109   }
110 
111   void RetrieveScopeChain(Scope* scope);
112 
113   void CollectNonLocals(Scope* scope);
114 
115   MUST_USE_RESULT MaybeHandle<JSObject> MaterializeScriptScope();
116   MUST_USE_RESULT MaybeHandle<JSObject> MaterializeLocalScope();
117   MUST_USE_RESULT MaybeHandle<JSObject> MaterializeModuleScope();
118   Handle<JSObject> MaterializeClosure();
119   Handle<JSObject> MaterializeCatchScope();
120   Handle<JSObject> MaterializeBlockScope();
121 
122   bool SetLocalVariableValue(Handle<String> variable_name,
123                              Handle<Object> new_value);
124   bool SetBlockVariableValue(Handle<String> variable_name,
125                              Handle<Object> new_value);
126   bool SetClosureVariableValue(Handle<String> variable_name,
127                                Handle<Object> new_value);
128   bool SetScriptVariableValue(Handle<String> variable_name,
129                               Handle<Object> new_value);
130   bool SetCatchVariableValue(Handle<String> variable_name,
131                              Handle<Object> new_value);
132   bool SetContextLocalValue(Handle<ScopeInfo> scope_info,
133                             Handle<Context> context,
134                             Handle<String> variable_name,
135                             Handle<Object> new_value);
136 
137   void CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
138                                       Handle<Context> context,
139                                       Handle<JSObject> scope_object);
140   bool CopyContextExtensionToScopeObject(Handle<JSObject> extension,
141                                          Handle<JSObject> scope_object,
142                                          JSReceiver::KeyCollectionType type);
143 
144   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
145 };
146 
147 }  // namespace internal
148 }  // namespace v8
149 
150 #endif  // V8_DEBUG_DEBUG_SCOPES_H_
151