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