| // Copyright 2017 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/debug/debug-scope-iterator.h" |
| |
| #include "src/api-inl.h" |
| #include "src/debug/debug.h" |
| #include "src/debug/liveedit.h" |
| #include "src/frames-inl.h" |
| #include "src/isolate.h" |
| #include "src/objects/js-generator-inl.h" |
| #include "src/wasm/wasm-objects-inl.h" |
| |
| namespace v8 { |
| |
| std::unique_ptr<debug::ScopeIterator> debug::ScopeIterator::CreateForFunction( |
| v8::Isolate* v8_isolate, v8::Local<v8::Function> v8_func) { |
| internal::Handle<internal::JSReceiver> receiver = |
| internal::Handle<internal::JSReceiver>::cast(Utils::OpenHandle(*v8_func)); |
| |
| // Besides JSFunction and JSBoundFunction, {v8_func} could be an |
| // ObjectTemplate with a CallAsFunctionHandler. We only handle plain |
| // JSFunctions. |
| if (!receiver->IsJSFunction()) return nullptr; |
| |
| internal::Handle<internal::JSFunction> function = |
| internal::Handle<internal::JSFunction>::cast(receiver); |
| |
| // Blink has function objects with callable map, JS_SPECIAL_API_OBJECT_TYPE |
| // but without context on heap. |
| if (!function->has_context()) return nullptr; |
| return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator( |
| reinterpret_cast<internal::Isolate*>(v8_isolate), function)); |
| } |
| |
| std::unique_ptr<debug::ScopeIterator> |
| debug::ScopeIterator::CreateForGeneratorObject( |
| v8::Isolate* v8_isolate, v8::Local<v8::Object> v8_generator) { |
| internal::Handle<internal::Object> generator = |
| Utils::OpenHandle(*v8_generator); |
| DCHECK(generator->IsJSGeneratorObject()); |
| return std::unique_ptr<debug::ScopeIterator>(new internal::DebugScopeIterator( |
| reinterpret_cast<internal::Isolate*>(v8_isolate), |
| internal::Handle<internal::JSGeneratorObject>::cast(generator))); |
| } |
| |
| namespace internal { |
| |
| DebugScopeIterator::DebugScopeIterator(Isolate* isolate, |
| FrameInspector* frame_inspector) |
| : iterator_(isolate, frame_inspector) { |
| if (!Done() && ShouldIgnore()) Advance(); |
| } |
| |
| DebugScopeIterator::DebugScopeIterator(Isolate* isolate, |
| Handle<JSFunction> function) |
| : iterator_(isolate, function) { |
| if (!Done() && ShouldIgnore()) Advance(); |
| } |
| |
| DebugScopeIterator::DebugScopeIterator(Isolate* isolate, |
| Handle<JSGeneratorObject> generator) |
| : iterator_(isolate, generator) { |
| if (!Done() && ShouldIgnore()) Advance(); |
| } |
| |
| bool DebugScopeIterator::Done() { return iterator_.Done(); } |
| |
| void DebugScopeIterator::Advance() { |
| DCHECK(!Done()); |
| iterator_.Next(); |
| while (!Done() && ShouldIgnore()) { |
| iterator_.Next(); |
| } |
| } |
| |
| bool DebugScopeIterator::ShouldIgnore() { |
| if (GetType() == debug::ScopeIterator::ScopeTypeLocal) return false; |
| return !iterator_.DeclaresLocals(i::ScopeIterator::Mode::ALL); |
| } |
| |
| v8::debug::ScopeIterator::ScopeType DebugScopeIterator::GetType() { |
| DCHECK(!Done()); |
| return static_cast<v8::debug::ScopeIterator::ScopeType>(iterator_.Type()); |
| } |
| |
| v8::Local<v8::Object> DebugScopeIterator::GetObject() { |
| DCHECK(!Done()); |
| Handle<JSObject> value = iterator_.ScopeObject(i::ScopeIterator::Mode::ALL); |
| return Utils::ToLocal(value); |
| } |
| |
| int DebugScopeIterator::GetScriptId() { |
| DCHECK(!Done()); |
| return iterator_.GetScript()->id(); |
| } |
| |
| v8::Local<v8::Value> DebugScopeIterator::GetFunctionDebugName() { |
| DCHECK(!Done()); |
| Handle<Object> name = iterator_.GetFunctionDebugName(); |
| return Utils::ToLocal(name); |
| } |
| |
| bool DebugScopeIterator::HasLocationInfo() { |
| return iterator_.HasPositionInfo(); |
| } |
| |
| debug::Location DebugScopeIterator::GetStartLocation() { |
| DCHECK(!Done()); |
| return ToApiHandle<v8::debug::Script>(iterator_.GetScript()) |
| ->GetSourceLocation(iterator_.start_position()); |
| } |
| |
| debug::Location DebugScopeIterator::GetEndLocation() { |
| DCHECK(!Done()); |
| return ToApiHandle<v8::debug::Script>(iterator_.GetScript()) |
| ->GetSourceLocation(iterator_.end_position()); |
| } |
| |
| bool DebugScopeIterator::SetVariableValue(v8::Local<v8::String> name, |
| v8::Local<v8::Value> value) { |
| DCHECK(!Done()); |
| return iterator_.SetVariableValue(Utils::OpenHandle(*name), |
| Utils::OpenHandle(*value)); |
| } |
| |
| DebugWasmScopeIterator::DebugWasmScopeIterator(Isolate* isolate, |
| StandardFrame* frame, |
| int inlined_frame_index) |
| : isolate_(isolate), |
| frame_(frame), |
| inlined_frame_index_(inlined_frame_index), |
| type_(debug::ScopeIterator::ScopeTypeGlobal) {} |
| |
| bool DebugWasmScopeIterator::Done() { |
| return type_ != debug::ScopeIterator::ScopeTypeGlobal && |
| type_ != debug::ScopeIterator::ScopeTypeLocal; |
| } |
| |
| void DebugWasmScopeIterator::Advance() { |
| DCHECK(!Done()); |
| if (type_ == debug::ScopeIterator::ScopeTypeGlobal) { |
| type_ = debug::ScopeIterator::ScopeTypeLocal; |
| } else { |
| // We use ScopeTypeWith type as marker for done. |
| type_ = debug::ScopeIterator::ScopeTypeWith; |
| } |
| } |
| |
| v8::debug::ScopeIterator::ScopeType DebugWasmScopeIterator::GetType() { |
| DCHECK(!Done()); |
| return type_; |
| } |
| |
| v8::Local<v8::Object> DebugWasmScopeIterator::GetObject() { |
| DCHECK(!Done()); |
| Handle<WasmDebugInfo> debug_info( |
| WasmInterpreterEntryFrame::cast(frame_)->debug_info(), isolate_); |
| switch (type_) { |
| case debug::ScopeIterator::ScopeTypeGlobal: |
| return Utils::ToLocal(WasmDebugInfo::GetGlobalScopeObject( |
| debug_info, frame_->fp(), inlined_frame_index_)); |
| case debug::ScopeIterator::ScopeTypeLocal: |
| return Utils::ToLocal(WasmDebugInfo::GetLocalScopeObject( |
| debug_info, frame_->fp(), inlined_frame_index_)); |
| default: |
| return v8::Local<v8::Object>(); |
| } |
| return v8::Local<v8::Object>(); |
| } |
| |
| int DebugWasmScopeIterator::GetScriptId() { |
| DCHECK(!Done()); |
| return -1; |
| } |
| |
| v8::Local<v8::Value> DebugWasmScopeIterator::GetFunctionDebugName() { |
| DCHECK(!Done()); |
| return Utils::ToLocal(isolate_->factory()->empty_string()); |
| } |
| |
| bool DebugWasmScopeIterator::HasLocationInfo() { return false; } |
| |
| debug::Location DebugWasmScopeIterator::GetStartLocation() { |
| DCHECK(!Done()); |
| return debug::Location(); |
| } |
| |
| debug::Location DebugWasmScopeIterator::GetEndLocation() { |
| DCHECK(!Done()); |
| return debug::Location(); |
| } |
| |
| bool DebugWasmScopeIterator::SetVariableValue(v8::Local<v8::String> name, |
| v8::Local<v8::Value> value) { |
| DCHECK(!Done()); |
| return false; |
| } |
| } // namespace internal |
| } // namespace v8 |