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
14 namespace v8 {
15
CreateForFunction(v8::Isolate * v8_isolate,v8::Local<v8::Function> v8_func)16 std::unique_ptr<debug::ScopeIterator> debug::ScopeIterator::CreateForFunction(
17 v8::Isolate* v8_isolate, v8::Local<v8::Function> v8_func) {
18 internal::Handle<internal::JSReceiver> receiver =
19 internal::Handle<internal::JSReceiver>::cast(Utils::OpenHandle(*v8_func));
20
21 // Besides JSFunction and JSBoundFunction, {v8_func} could be an
22 // ObjectTemplate with a CallAsFunctionHandler. We only handle plain
23 // JSFunctions.
24 if (!receiver->IsJSFunction()) return nullptr;
25
26 internal::Handle<internal::JSFunction> function =
27 internal::Handle<internal::JSFunction>::cast(receiver);
28
29 // Blink has function objects with callable map, JS_SPECIAL_API_OBJECT_TYPE
30 // but without context on heap.
31 if (!function->has_context()) return nullptr;
32 return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator(
33 reinterpret_cast<internal::Isolate*>(v8_isolate), function));
34 }
35
36 std::unique_ptr<debug::ScopeIterator>
CreateForGeneratorObject(v8::Isolate * v8_isolate,v8::Local<v8::Object> v8_generator)37 debug::ScopeIterator::CreateForGeneratorObject(
38 v8::Isolate* v8_isolate, v8::Local<v8::Object> v8_generator) {
39 internal::Handle<internal::Object> generator =
40 Utils::OpenHandle(*v8_generator);
41 DCHECK(generator->IsJSGeneratorObject());
42 return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator(
43 reinterpret_cast<internal::Isolate*>(v8_isolate),
44 internal::Handle<internal::JSGeneratorObject>::cast(generator)));
45 }
46
47 namespace internal {
48
DebugScopeIterator(Isolate * isolate,FrameInspector * frame_inspector)49 DebugScopeIterator::DebugScopeIterator(Isolate* isolate,
50 FrameInspector* frame_inspector)
51 : iterator_(
52 isolate, frame_inspector,
53 ::v8::internal::ScopeIterator::ReparseStrategy::kFunctionLiteral) {
54 if (!Done() && ShouldIgnore()) Advance();
55 }
56
DebugScopeIterator(Isolate * isolate,Handle<JSFunction> function)57 DebugScopeIterator::DebugScopeIterator(Isolate* isolate,
58 Handle<JSFunction> function)
59 : iterator_(isolate, function) {
60 if (!Done() && ShouldIgnore()) Advance();
61 }
62
DebugScopeIterator(Isolate * isolate,Handle<JSGeneratorObject> generator)63 DebugScopeIterator::DebugScopeIterator(Isolate* isolate,
64 Handle<JSGeneratorObject> generator)
65 : iterator_(isolate, generator) {
66 if (!Done() && ShouldIgnore()) Advance();
67 }
68
Done()69 bool DebugScopeIterator::Done() { return iterator_.Done(); }
70
Advance()71 void DebugScopeIterator::Advance() {
72 DCHECK(!Done());
73 iterator_.Next();
74 while (!Done() && ShouldIgnore()) {
75 iterator_.Next();
76 }
77 }
78
ShouldIgnore()79 bool DebugScopeIterator::ShouldIgnore() {
80 if (GetType() == debug::ScopeIterator::ScopeTypeLocal) return false;
81 return !iterator_.DeclaresLocals(i::ScopeIterator::Mode::ALL);
82 }
83
GetType()84 v8::debug::ScopeIterator::ScopeType DebugScopeIterator::GetType() {
85 DCHECK(!Done());
86 return static_cast<v8::debug::ScopeIterator::ScopeType>(iterator_.Type());
87 }
88
GetObject()89 v8::Local<v8::Object> DebugScopeIterator::GetObject() {
90 DCHECK(!Done());
91 Handle<JSObject> value = iterator_.ScopeObject(i::ScopeIterator::Mode::ALL);
92 return Utils::ToLocal(value);
93 }
94
GetScriptId()95 int DebugScopeIterator::GetScriptId() {
96 DCHECK(!Done());
97 return iterator_.GetScript()->id();
98 }
99
GetFunctionDebugName()100 v8::Local<v8::Value> DebugScopeIterator::GetFunctionDebugName() {
101 DCHECK(!Done());
102 Handle<Object> name = iterator_.GetFunctionDebugName();
103 return Utils::ToLocal(name);
104 }
105
HasLocationInfo()106 bool DebugScopeIterator::HasLocationInfo() {
107 return iterator_.HasPositionInfo();
108 }
109
GetStartLocation()110 debug::Location DebugScopeIterator::GetStartLocation() {
111 DCHECK(!Done());
112 return ToApiHandle<v8::debug::Script>(iterator_.GetScript())
113 ->GetSourceLocation(iterator_.start_position());
114 }
115
GetEndLocation()116 debug::Location DebugScopeIterator::GetEndLocation() {
117 DCHECK(!Done());
118 return ToApiHandle<v8::debug::Script>(iterator_.GetScript())
119 ->GetSourceLocation(iterator_.end_position());
120 }
121
SetVariableValue(v8::Local<v8::String> name,v8::Local<v8::Value> value)122 bool DebugScopeIterator::SetVariableValue(v8::Local<v8::String> name,
123 v8::Local<v8::Value> value) {
124 DCHECK(!Done());
125 return iterator_.SetVariableValue(Utils::OpenHandle(*name),
126 Utils::OpenHandle(*value));
127 }
128
129 } // namespace internal
130 } // namespace v8
131