• 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-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