summaryrefslogtreecommitdiff
path: root/deps/v8/src/debug/debug-scopes.h
blob: 026a1da0f55329cdc55c1cb0ba199e61614e6b73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// 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 {

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 Option { DEFAULT, IGNORE_NESTED_SCOPES, COLLECT_NON_LOCALS };

  ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector,
                Option options = DEFAULT);

  ScopeIterator(Isolate* isolate, Handle<JSFunction> function);
  ScopeIterator(Isolate* isolate, Handle<JSGeneratorObject> generator);

  MUST_USE_RESULT MaybeHandle<JSObject> 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<JSObject> ScopeObject();

  bool HasContext();

  // Set variable value and return true on success.
  bool SetVariableValue(Handle<String> variable_name, Handle<Object> new_value);

  Handle<ScopeInfo> CurrentScopeInfo();

  // Return the context for this scope. For the local context there might not
  // be an actual context.
  Handle<Context> CurrentContext();

  // Populate the set with collected non-local variable names.
  Handle<StringSet> GetNonLocals();

#ifdef DEBUG
  // Debug print of the content of the current scope.
  void DebugPrint();
#endif

 private:
  struct ExtendedScopeInfo {
    ExtendedScopeInfo(Handle<ScopeInfo> info, int start, int end)
        : scope_info(info), start_position(start), end_position(end) {}
    explicit ExtendedScopeInfo(Handle<ScopeInfo> info)
        : scope_info(info), start_position(-1), end_position(-1) {}
    Handle<ScopeInfo> scope_info;
    int start_position;
    int end_position;
    bool is_hidden() { return start_position == -1 && end_position == -1; }
  };

  Isolate* isolate_;
  FrameInspector* const frame_inspector_;
  Handle<Context> context_;
  List<ExtendedScopeInfo> nested_scope_chain_;
  Handle<StringSet> non_locals_;
  bool seen_script_scope_;
  bool failed_;

  inline JavaScriptFrame* GetFrame() {
    return frame_inspector_->GetArgumentsFrame();
  }

  inline Handle<JSFunction> GetFunction() {
    return frame_inspector_->GetFunction();
  }

  void RetrieveScopeChain(DeclarationScope* scope);

  void CollectNonLocals(ParseInfo* info, DeclarationScope* scope);

  void UnwrapEvaluationContext();

  MUST_USE_RESULT MaybeHandle<JSObject> MaterializeScriptScope();
  MUST_USE_RESULT MaybeHandle<JSObject> MaterializeLocalScope();
  MUST_USE_RESULT MaybeHandle<JSObject> MaterializeModuleScope();
  Handle<JSObject> MaterializeClosure();
  Handle<JSObject> MaterializeCatchScope();
  Handle<JSObject> MaterializeInnerScope();
  Handle<JSObject> WithContextExtension();

  bool SetLocalVariableValue(Handle<String> variable_name,
                             Handle<Object> new_value);
  bool SetInnerScopeVariableValue(Handle<String> variable_name,
                                  Handle<Object> new_value);
  bool SetClosureVariableValue(Handle<String> variable_name,
                               Handle<Object> new_value);
  bool SetScriptVariableValue(Handle<String> variable_name,
                              Handle<Object> new_value);
  bool SetCatchVariableValue(Handle<String> variable_name,
                             Handle<Object> new_value);

  // Helper functions.
  bool SetParameterValue(Handle<ScopeInfo> scope_info, JavaScriptFrame* frame,
                         Handle<String> parameter_name,
                         Handle<Object> new_value);
  bool SetStackVariableValue(Handle<ScopeInfo> scope_info,
                             Handle<String> variable_name,
                             Handle<Object> new_value);
  bool SetContextVariableValue(Handle<ScopeInfo> scope_info,
                               Handle<Context> context,
                               Handle<String> variable_name,
                               Handle<Object> new_value);

  void CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
                                      Handle<Context> context,
                                      Handle<JSObject> scope_object);
  void CopyContextExtensionToScopeObject(Handle<Context> context,
                                         Handle<JSObject> scope_object,
                                         KeyCollectionMode mode);

  // Get the chain of nested scopes within this scope for the source statement
  // position. The scopes will be added to the list from the outermost scope to
  // the innermost scope. Only nested block, catch or with scopes are tracked
  // and will be returned, but no inner function scopes.
  void GetNestedScopeChain(Isolate* isolate, Scope* scope,
                           int statement_position);

  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_DEBUG_DEBUG_SCOPES_H_