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