• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 #include "src/debug/debug-scope-iterator.h"
6 
7 #include "src/api/api-inl.h"
8 #include "src/debug/debug.h"
9 #include "src/debug/liveedit.h"
10 #include "src/execution/frames-inl.h"
11 #include "src/execution/isolate.h"
12 #include "src/objects/js-generator-inl.h"
13 #include "src/wasm/wasm-debug.h"
14 #include "src/wasm/wasm-objects-inl.h"
15 
16 namespace v8 {
17 
CreateForFunction(v8::Isolate * v8_isolate,v8::Local<v8::Function> v8_func)18 std::unique_ptr<debug::ScopeIterator> debug::ScopeIterator::CreateForFunction(
19     v8::Isolate* v8_isolate, v8::Local<v8::Function> v8_func) {
20   internal::Handle<internal::JSReceiver> receiver =
21       internal::Handle<internal::JSReceiver>::cast(Utils::OpenHandle(*v8_func));
22 
23   // Besides JSFunction and JSBoundFunction, {v8_func} could be an
24   // ObjectTemplate with a CallAsFunctionHandler. We only handle plain
25   // JSFunctions.
26   if (!receiver->IsJSFunction()) return nullptr;
27 
28   internal::Handle<internal::JSFunction> function =
29       internal::Handle<internal::JSFunction>::cast(receiver);
30 
31   // Blink has function objects with callable map, JS_SPECIAL_API_OBJECT_TYPE
32   // but without context on heap.
33   if (!function->has_context()) return nullptr;
34   return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator(
35       reinterpret_cast<internal::Isolate*>(v8_isolate), function));
36 }
37 
38 std::unique_ptr<debug::ScopeIterator>
CreateForGeneratorObject(v8::Isolate * v8_isolate,v8::Local<v8::Object> v8_generator)39 debug::ScopeIterator::CreateForGeneratorObject(
40     v8::Isolate* v8_isolate, v8::Local<v8::Object> v8_generator) {
41   internal::Handle<internal::Object> generator =
42       Utils::OpenHandle(*v8_generator);
43   DCHECK(generator->IsJSGeneratorObject());
44   return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator(
45       reinterpret_cast<internal::Isolate*>(v8_isolate),
46       internal::Handle<internal::JSGeneratorObject>::cast(generator)));
47 }
48 
49 namespace internal {
50 
DebugScopeIterator(Isolate * isolate,FrameInspector * frame_inspector)51 DebugScopeIterator::DebugScopeIterator(Isolate* isolate,
52                                        FrameInspector* frame_inspector)
53     : iterator_(
54           isolate, frame_inspector,
55           ::v8::internal::ScopeIterator::ReparseStrategy::kFunctionLiteral) {
56   if (!Done() && ShouldIgnore()) Advance();
57 }
58 
DebugScopeIterator(Isolate * isolate,Handle<JSFunction> function)59 DebugScopeIterator::DebugScopeIterator(Isolate* isolate,
60                                        Handle<JSFunction> function)
61     : iterator_(isolate, function) {
62   if (!Done() && ShouldIgnore()) Advance();
63 }
64 
DebugScopeIterator(Isolate * isolate,Handle<JSGeneratorObject> generator)65 DebugScopeIterator::DebugScopeIterator(Isolate* isolate,
66                                        Handle<JSGeneratorObject> generator)
67     : iterator_(isolate, generator) {
68   if (!Done() && ShouldIgnore()) Advance();
69 }
70 
Done()71 bool DebugScopeIterator::Done() { return iterator_.Done(); }
72 
Advance()73 void DebugScopeIterator::Advance() {
74   DCHECK(!Done());
75   iterator_.Next();
76   while (!Done() && ShouldIgnore()) {
77     iterator_.Next();
78   }
79 }
80 
ShouldIgnore()81 bool DebugScopeIterator::ShouldIgnore() {
82   if (GetType() == debug::ScopeIterator::ScopeTypeLocal) return false;
83   return !iterator_.DeclaresLocals(i::ScopeIterator::Mode::ALL);
84 }
85 
GetType()86 v8::debug::ScopeIterator::ScopeType DebugScopeIterator::GetType() {
87   DCHECK(!Done());
88   return static_cast<v8::debug::ScopeIterator::ScopeType>(iterator_.Type());
89 }
90 
GetObject()91 v8::Local<v8::Object> DebugScopeIterator::GetObject() {
92   DCHECK(!Done());
93   Handle<JSObject> value = iterator_.ScopeObject(i::ScopeIterator::Mode::ALL);
94   return Utils::ToLocal(value);
95 }
96 
GetScriptId()97 int DebugScopeIterator::GetScriptId() {
98   DCHECK(!Done());
99   return iterator_.GetScript()->id();
100 }
101 
GetFunctionDebugName()102 v8::Local<v8::Value> DebugScopeIterator::GetFunctionDebugName() {
103   DCHECK(!Done());
104   Handle<Object> name = iterator_.GetFunctionDebugName();
105   return Utils::ToLocal(name);
106 }
107 
HasLocationInfo()108 bool DebugScopeIterator::HasLocationInfo() {
109   return iterator_.HasPositionInfo();
110 }
111 
GetStartLocation()112 debug::Location DebugScopeIterator::GetStartLocation() {
113   DCHECK(!Done());
114   return ToApiHandle<v8::debug::Script>(iterator_.GetScript())
115       ->GetSourceLocation(iterator_.start_position());
116 }
117 
GetEndLocation()118 debug::Location DebugScopeIterator::GetEndLocation() {
119   DCHECK(!Done());
120   return ToApiHandle<v8::debug::Script>(iterator_.GetScript())
121       ->GetSourceLocation(iterator_.end_position());
122 }
123 
SetVariableValue(v8::Local<v8::String> name,v8::Local<v8::Value> value)124 bool DebugScopeIterator::SetVariableValue(v8::Local<v8::String> name,
125                                           v8::Local<v8::Value> value) {
126   DCHECK(!Done());
127   return iterator_.SetVariableValue(Utils::OpenHandle(*name),
128                                     Utils::OpenHandle(*value));
129 }
130 
DebugWasmScopeIterator(Isolate * isolate,WasmFrame * frame)131 DebugWasmScopeIterator::DebugWasmScopeIterator(Isolate* isolate,
132                                                WasmFrame* frame)
133     : isolate_(isolate),
134       frame_(frame),
135       type_(debug::ScopeIterator::ScopeTypeModule) {}
136 
Done()137 bool DebugWasmScopeIterator::Done() {
138   return type_ == debug::ScopeIterator::ScopeTypeWith;
139 }
140 
Advance()141 void DebugWasmScopeIterator::Advance() {
142   DCHECK(!Done());
143   switch (type_) {
144     case ScopeTypeModule:
145       // Skip local scope and expression stack scope if the frame is not
146       // inspectable.
147       type_ = frame_->is_inspectable() ? debug::ScopeIterator::ScopeTypeLocal
148                                        : debug::ScopeIterator::ScopeTypeWith;
149       break;
150     case ScopeTypeLocal:
151       type_ = debug::ScopeIterator::ScopeTypeWasmExpressionStack;
152       break;
153     case ScopeTypeWasmExpressionStack:
154       // We use ScopeTypeWith type as marker for done.
155       type_ = debug::ScopeIterator::ScopeTypeWith;
156       break;
157     default:
158       UNREACHABLE();
159   }
160 }
161 
GetType()162 v8::debug::ScopeIterator::ScopeType DebugWasmScopeIterator::GetType() {
163   DCHECK(!Done());
164   return type_;
165 }
166 
GetObject()167 v8::Local<v8::Object> DebugWasmScopeIterator::GetObject() {
168   DCHECK(!Done());
169   switch (type_) {
170     case debug::ScopeIterator::ScopeTypeModule: {
171       Handle<WasmInstanceObject> instance =
172           FrameSummary::GetTop(frame_).AsWasm().wasm_instance();
173       return Utils::ToLocal(wasm::GetModuleScopeObject(instance));
174     }
175     case debug::ScopeIterator::ScopeTypeLocal: {
176       DCHECK(frame_->is_wasm());
177       wasm::DebugInfo* debug_info = frame_->native_module()->GetDebugInfo();
178       return Utils::ToLocal(debug_info->GetLocalScopeObject(
179           isolate_, frame_->pc(), frame_->fp(), frame_->callee_fp()));
180     }
181     case debug::ScopeIterator::ScopeTypeWasmExpressionStack: {
182       DCHECK(frame_->is_wasm());
183       wasm::DebugInfo* debug_info = frame_->native_module()->GetDebugInfo();
184       return Utils::ToLocal(debug_info->GetStackScopeObject(
185           isolate_, frame_->pc(), frame_->fp(), frame_->callee_fp()));
186     }
187     default:
188       return {};
189   }
190 }
191 
GetScriptId()192 int DebugWasmScopeIterator::GetScriptId() {
193   DCHECK(!Done());
194   return -1;
195 }
196 
GetFunctionDebugName()197 v8::Local<v8::Value> DebugWasmScopeIterator::GetFunctionDebugName() {
198   DCHECK(!Done());
199   return Utils::ToLocal(isolate_->factory()->empty_string());
200 }
201 
HasLocationInfo()202 bool DebugWasmScopeIterator::HasLocationInfo() { return false; }
203 
GetStartLocation()204 debug::Location DebugWasmScopeIterator::GetStartLocation() {
205   DCHECK(!Done());
206   return debug::Location();
207 }
208 
GetEndLocation()209 debug::Location DebugWasmScopeIterator::GetEndLocation() {
210   DCHECK(!Done());
211   return debug::Location();
212 }
213 
SetVariableValue(v8::Local<v8::String> name,v8::Local<v8::Value> value)214 bool DebugWasmScopeIterator::SetVariableValue(v8::Local<v8::String> name,
215                                               v8::Local<v8::Value> value) {
216   DCHECK(!Done());
217   return false;
218 }
219 }  // namespace internal
220 }  // namespace v8
221