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 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> 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 50 DebugScopeIterator::DebugScopeIterator(Isolate* isolate, 51 FrameInspector* frame_inspector) 52 : iterator_(isolate, frame_inspector) { 53 if (!Done() && ShouldIgnore()) Advance(); 54 } 55 56 DebugScopeIterator::DebugScopeIterator(Isolate* isolate, 57 Handle<JSFunction> function) 58 : iterator_(isolate, function) { 59 if (!Done() && ShouldIgnore()) Advance(); 60 } 61 62 DebugScopeIterator::DebugScopeIterator(Isolate* isolate, 63 Handle<JSGeneratorObject> generator) 64 : iterator_(isolate, generator) { 65 if (!Done() && ShouldIgnore()) Advance(); 66 } 67 68 bool DebugScopeIterator::Done() { return iterator_.Done(); } 69 70 void DebugScopeIterator::Advance() { 71 DCHECK(!Done()); 72 iterator_.Next(); 73 while (!Done() && ShouldIgnore()) { 74 iterator_.Next(); 75 } 76 } 77 78 bool DebugScopeIterator::ShouldIgnore() { 79 if (GetType() == debug::ScopeIterator::ScopeTypeLocal) return false; 80 return !iterator_.DeclaresLocals(i::ScopeIterator::Mode::ALL); 81 } 82 83 v8::debug::ScopeIterator::ScopeType DebugScopeIterator::GetType() { 84 DCHECK(!Done()); 85 return static_cast<v8::debug::ScopeIterator::ScopeType>(iterator_.Type()); 86 } 87 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 94 int DebugScopeIterator::GetScriptId() { 95 DCHECK(!Done()); 96 return iterator_.GetScript()->id(); 97 } 98 99 v8::Local<v8::Value> DebugScopeIterator::GetFunctionDebugName() { 100 DCHECK(!Done()); 101 Handle<Object> name = iterator_.GetFunctionDebugName(); 102 return Utils::ToLocal(name); 103 } 104 105 bool DebugScopeIterator::HasLocationInfo() { 106 return iterator_.HasPositionInfo(); 107 } 108 109 debug::Location DebugScopeIterator::GetStartLocation() { 110 DCHECK(!Done()); 111 return ToApiHandle<v8::debug::Script>(iterator_.GetScript()) 112 ->GetSourceLocation(iterator_.start_position()); 113 } 114 115 debug::Location DebugScopeIterator::GetEndLocation() { 116 DCHECK(!Done()); 117 return ToApiHandle<v8::debug::Script>(iterator_.GetScript()) 118 ->GetSourceLocation(iterator_.end_position()); 119 } 120 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 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 136 bool DebugWasmScopeIterator::Done() { 137 return type_ != debug::ScopeIterator::ScopeTypeGlobal && 138 type_ != debug::ScopeIterator::ScopeTypeLocal; 139 } 140 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 151 v8::debug::ScopeIterator::ScopeType DebugWasmScopeIterator::GetType() { 152 DCHECK(!Done()); 153 return type_; 154 } 155 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 173 int DebugWasmScopeIterator::GetScriptId() { 174 DCHECK(!Done()); 175 return -1; 176 } 177 178 v8::Local<v8::Value> DebugWasmScopeIterator::GetFunctionDebugName() { 179 DCHECK(!Done()); 180 return Utils::ToLocal(isolate_->factory()->empty_string()); 181 } 182 183 bool DebugWasmScopeIterator::HasLocationInfo() { return false; } 184 185 debug::Location DebugWasmScopeIterator::GetStartLocation() { 186 DCHECK(!Done()); 187 return debug::Location(); 188 } 189 190 debug::Location DebugWasmScopeIterator::GetEndLocation() { 191 DCHECK(!Done()); 192 return debug::Location(); 193 } 194 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