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