87e8bc2c96
BUG=http://dartbug.com/26161 R=hausner@google.com Review URL: https://codereview.chromium.org/1854243002 .
975 lines
34 KiB
C++
975 lines
34 KiB
C++
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "include/dart_tools_api.h"
|
|
|
|
#include "vm/class_finalizer.h"
|
|
#include "vm/compiler.h"
|
|
#include "vm/dart_api_impl.h"
|
|
#include "vm/dart_api_state.h"
|
|
#include "vm/debugger.h"
|
|
#include "vm/isolate.h"
|
|
#include "vm/object_store.h"
|
|
#include "vm/symbols.h"
|
|
|
|
namespace dart {
|
|
|
|
// Facilitate quick access to the current zone once we have the curren thread.
|
|
#define Z (T->zone())
|
|
|
|
#ifndef PRODUCT
|
|
|
|
#define UNWRAP_AND_CHECK_PARAM(type, var, param) \
|
|
type& var = type::Handle(); \
|
|
do { \
|
|
const Object& tmp = Object::Handle(Api::UnwrapHandle(param)); \
|
|
if (tmp.IsNull()) { \
|
|
return Api::NewError("%s expects argument '%s' to be non-null.", \
|
|
CURRENT_FUNC, #param); \
|
|
} else if (tmp.IsApiError()) { \
|
|
return param; \
|
|
} else if (!tmp.Is##type()) { \
|
|
return Api::NewError("%s expects argument '%s' to be of type %s.", \
|
|
CURRENT_FUNC, #param, #type); \
|
|
} \
|
|
var ^= tmp.raw(); \
|
|
} while (0)
|
|
|
|
|
|
#define CHECK_AND_CAST(type, var, param) \
|
|
type* var = NULL; \
|
|
do { \
|
|
if (param == NULL) { \
|
|
return Api::NewError("%s expects argument '%s' to be non-null.", \
|
|
CURRENT_FUNC, #param); \
|
|
} \
|
|
var = reinterpret_cast<type*>(param); \
|
|
} while (0)
|
|
|
|
|
|
#define CHECK_NOT_NULL(param) \
|
|
if (param == NULL) { \
|
|
return Api::NewError("%s expects argument '%s' to be non-null.", \
|
|
CURRENT_FUNC, #param); \
|
|
}
|
|
|
|
|
|
DART_EXPORT intptr_t Dart_CacheObject(Dart_Handle object_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object_in));
|
|
if (obj.IsApiError()) {
|
|
return -1;
|
|
}
|
|
return I->debugger()->CacheObject(obj);
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetCachedObject(intptr_t obj_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
if (!I->debugger()->IsValidObjectId(obj_id)) {
|
|
return Api::NewError("%s: object id %" Pd " is invalid",
|
|
CURRENT_FUNC, obj_id);
|
|
}
|
|
return Api::NewHandle(T, I->debugger()->GetCachedObject(obj_id));
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_StackTraceLength(
|
|
Dart_StackTrace trace,
|
|
intptr_t* length) {
|
|
DARTSCOPE(Thread::Current());
|
|
CHECK_NOT_NULL(length);
|
|
CHECK_AND_CAST(DebuggerStackTrace, stack_trace, trace);
|
|
*length = stack_trace->Length();
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetActivationFrame(
|
|
Dart_StackTrace trace,
|
|
int frame_index,
|
|
Dart_ActivationFrame* frame) {
|
|
DARTSCOPE(Thread::Current());
|
|
CHECK_NOT_NULL(frame);
|
|
CHECK_AND_CAST(DebuggerStackTrace, stack_trace, trace);
|
|
if ((frame_index < 0) || (frame_index >= stack_trace->Length())) {
|
|
return Api::NewError("argument 'frame_index' is out of range for %s",
|
|
CURRENT_FUNC);
|
|
}
|
|
*frame = reinterpret_cast<Dart_ActivationFrame>(
|
|
stack_trace->FrameAt(frame_index));
|
|
return Api::Success();
|
|
}
|
|
|
|
static Dart_PausedEventHandler* paused_event_handler = NULL;
|
|
static Dart_BreakpointResolvedHandler* bp_resolved_handler = NULL;
|
|
static Dart_ExceptionThrownHandler* exc_thrown_handler = NULL;
|
|
static Dart_IsolateEventHandler* isolate_event_handler = NULL;
|
|
|
|
|
|
static void DebuggerEventHandler(DebuggerEvent* event) {
|
|
Thread* thread = Thread::Current();
|
|
Isolate* isolate = thread->isolate();
|
|
ASSERT(isolate != NULL);
|
|
Dart_EnterScope();
|
|
Dart_IsolateId isolate_id = isolate->debugger()->GetIsolateId();
|
|
if (event->type() == DebuggerEvent::kBreakpointReached) {
|
|
if (paused_event_handler != NULL) {
|
|
Dart_CodeLocation location;
|
|
ActivationFrame* top_frame = event->top_frame();
|
|
location.script_url = Api::NewHandle(thread, top_frame->SourceUrl());
|
|
const Library& lib = Library::Handle(top_frame->Library());
|
|
location.library_id = lib.index();
|
|
location.token_pos = top_frame->TokenPos().Pos();
|
|
intptr_t bp_id = 0;
|
|
if (event->breakpoint() != NULL) {
|
|
ASSERT(event->breakpoint()->id() != ILLEGAL_BREAKPOINT_ID);
|
|
bp_id = event->breakpoint()->id();
|
|
}
|
|
(*paused_event_handler)(isolate_id, bp_id, location);
|
|
}
|
|
} else if (event->type() == DebuggerEvent::kBreakpointResolved) {
|
|
if (bp_resolved_handler != NULL) {
|
|
Breakpoint* bpt = event->breakpoint();
|
|
ASSERT(bpt != NULL);
|
|
Dart_CodeLocation location;
|
|
Zone* zone = thread->zone();
|
|
Library& library = Library::Handle(zone);
|
|
Script& script = Script::Handle(zone);
|
|
TokenPosition token_pos;
|
|
bpt->bpt_location()->GetCodeLocation(&library, &script, &token_pos);
|
|
location.script_url = Api::NewHandle(thread, script.url());
|
|
location.library_id = library.index();
|
|
location.token_pos = token_pos.Pos();
|
|
(*bp_resolved_handler)(isolate_id, bpt->id(), location);
|
|
}
|
|
} else if (event->type() == DebuggerEvent::kExceptionThrown) {
|
|
if (exc_thrown_handler != NULL) {
|
|
Dart_Handle exception =
|
|
Api::NewHandle(thread, event->exception()->raw());
|
|
Dart_StackTrace trace =
|
|
reinterpret_cast<Dart_StackTrace>(isolate->debugger()->StackTrace());
|
|
(*exc_thrown_handler)(isolate_id, exception, trace);
|
|
}
|
|
} else if (event->type() == DebuggerEvent::kIsolateCreated) {
|
|
if (isolate_event_handler != NULL) {
|
|
(*isolate_event_handler)(event->isolate_id(), kCreated);
|
|
}
|
|
} else if (event->type() == DebuggerEvent::kIsolateInterrupted) {
|
|
if (isolate_event_handler != NULL) {
|
|
(*isolate_event_handler)(event->isolate_id(), kInterrupted);
|
|
}
|
|
} else if (event->type() == DebuggerEvent::kIsolateShutdown) {
|
|
if (isolate_event_handler != NULL) {
|
|
(*isolate_event_handler)(event->isolate_id(), kShutdown);
|
|
}
|
|
} else {
|
|
UNIMPLEMENTED();
|
|
}
|
|
Dart_ExitScope();
|
|
}
|
|
|
|
|
|
DART_EXPORT void Dart_SetPausedEventHandler(Dart_PausedEventHandler handler) {
|
|
paused_event_handler = handler;
|
|
Debugger::SetEventHandler(DebuggerEventHandler);
|
|
}
|
|
|
|
|
|
DART_EXPORT void Dart_SetBreakpointResolvedHandler(
|
|
Dart_BreakpointResolvedHandler handler) {
|
|
bp_resolved_handler = handler;
|
|
Debugger::SetEventHandler(DebuggerEventHandler);
|
|
}
|
|
|
|
|
|
DART_EXPORT void Dart_SetExceptionThrownHandler(
|
|
Dart_ExceptionThrownHandler handler) {
|
|
exc_thrown_handler = handler;
|
|
Debugger::SetEventHandler(DebuggerEventHandler);
|
|
}
|
|
|
|
|
|
DART_EXPORT void Dart_SetIsolateEventHandler(Dart_IsolateEventHandler handler) {
|
|
isolate_event_handler = handler;
|
|
Debugger::SetEventHandler(DebuggerEventHandler);
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_SetExceptionPauseInfo(
|
|
Dart_ExceptionPauseInfo pause_info) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
I->debugger()->SetExceptionPauseInfo(pause_info);
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_ExceptionPauseInfo Dart_GetExceptionPauseInfo() {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
return I->debugger()->GetExceptionPauseInfo();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetStackTrace(Dart_StackTrace* trace) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
CHECK_NOT_NULL(trace);
|
|
*trace = reinterpret_cast<Dart_StackTrace>(
|
|
I->debugger()->CurrentStackTrace());
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetStackTraceFromError(Dart_Handle handle,
|
|
Dart_StackTrace* trace) {
|
|
DARTSCOPE(Thread::Current());
|
|
CHECK_NOT_NULL(trace);
|
|
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
|
|
if (obj.IsUnhandledException()) {
|
|
const UnhandledException& error = UnhandledException::Cast(obj);
|
|
Stacktrace& dart_stacktrace = Stacktrace::Handle(Z);
|
|
dart_stacktrace ^= error.stacktrace();
|
|
if (dart_stacktrace.IsNull()) {
|
|
*trace = NULL;
|
|
} else {
|
|
Isolate* I = T->isolate();
|
|
*trace = reinterpret_cast<Dart_StackTrace>(
|
|
I->debugger()->StackTraceFrom(dart_stacktrace));
|
|
}
|
|
return Api::Success();
|
|
} else {
|
|
return Api::NewError("Can only get stacktraces from error handles or "
|
|
"instances of Error.");
|
|
}
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ActivationFrameInfo(
|
|
Dart_ActivationFrame activation_frame,
|
|
Dart_Handle* function_name,
|
|
Dart_Handle* script_url,
|
|
intptr_t* line_number,
|
|
intptr_t* column_number) {
|
|
DARTSCOPE(Thread::Current());
|
|
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
|
|
if (function_name != NULL) {
|
|
*function_name = Api::NewHandle(T, frame->QualifiedFunctionName());
|
|
}
|
|
if (script_url != NULL) {
|
|
*script_url = Api::NewHandle(T, frame->SourceUrl());
|
|
}
|
|
if (line_number != NULL) {
|
|
*line_number = frame->LineNumber();
|
|
}
|
|
if (column_number != NULL) {
|
|
*column_number = frame->ColumnNumber();
|
|
}
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ActivationFrameGetLocation(
|
|
Dart_ActivationFrame activation_frame,
|
|
Dart_Handle* function_name,
|
|
Dart_Handle* function,
|
|
Dart_CodeLocation* location) {
|
|
// TODO(hausner): Implement a way to recognize when there
|
|
// is no source code for the code in the frame.
|
|
DARTSCOPE(Thread::Current());
|
|
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
|
|
if (function_name != NULL) {
|
|
*function_name = Api::NewHandle(T, frame->QualifiedFunctionName());
|
|
}
|
|
if (function != NULL) {
|
|
*function = Api::NewHandle(T, frame->function().raw());
|
|
}
|
|
|
|
if (location != NULL) {
|
|
location->script_url = Api::NewHandle(T, frame->SourceUrl());
|
|
const Library& lib = Library::Handle(Z, frame->Library());
|
|
location->library_id = lib.index();
|
|
location->token_pos = frame->TokenPos().Pos();
|
|
}
|
|
return Api::Success();
|
|
}
|
|
|
|
DART_EXPORT Dart_Handle Dart_ActivationFrameGetFramePointer(
|
|
Dart_ActivationFrame activation_frame,
|
|
uintptr_t* frame_pointer) {
|
|
DARTSCOPE(Thread::Current());
|
|
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
|
|
|
|
if (frame_pointer != NULL) {
|
|
*frame_pointer = static_cast<uintptr_t>(frame->fp());
|
|
}
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetFunctionOrigin(Dart_Handle function_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
UNWRAP_AND_CHECK_PARAM(Function, function, function_in);
|
|
|
|
const Class& cls = Class::Handle(Z, function.origin());
|
|
if (!cls.IsTopLevel()) {
|
|
return Dart_NewInteger(cls.id());
|
|
}
|
|
return Api::Null();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetLocalVariables(
|
|
Dart_ActivationFrame activation_frame) {
|
|
DARTSCOPE(Thread::Current());
|
|
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
|
|
return Api::NewHandle(T, frame->GetLocalVariables());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_SetBreakpoint(
|
|
Dart_Handle script_url_in,
|
|
intptr_t line_number) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
|
|
|
|
Debugger* debugger = I->debugger();
|
|
Breakpoint* bpt =
|
|
debugger->SetBreakpointAtLine(script_url, line_number);
|
|
if (bpt == NULL) {
|
|
return Api::NewError("%s: could not set breakpoint at line %" Pd " in '%s'",
|
|
CURRENT_FUNC, line_number, script_url.ToCString());
|
|
}
|
|
return Dart_NewInteger(bpt->id());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetBreakpointURL(intptr_t bp_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
Debugger* debugger = I->debugger();
|
|
|
|
Breakpoint* bpt = debugger->GetBreakpointById(bp_id);
|
|
if (bpt == NULL) {
|
|
return Api::NewError("%s: breakpoint with id %" Pd " does not exist",
|
|
CURRENT_FUNC, bp_id);
|
|
}
|
|
return Api::NewHandle(T, bpt->bpt_location()->url());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetBreakpointLine(intptr_t bp_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
Debugger* debugger = I->debugger();
|
|
|
|
Breakpoint* bpt = debugger->GetBreakpointById(bp_id);
|
|
if (bpt == NULL) {
|
|
return Api::NewError("%s: breakpoint with id %" Pd " does not exist",
|
|
CURRENT_FUNC, bp_id);
|
|
}
|
|
if (bpt->bpt_location()->IsResolved()) {
|
|
return Dart_NewInteger(bpt->bpt_location()->LineNumber());
|
|
} else {
|
|
return Dart_NewInteger(bpt->bpt_location()->requested_line_number());
|
|
}
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_SetBreakpointAtEntry(
|
|
Dart_Handle library_in,
|
|
Dart_Handle class_name_in,
|
|
Dart_Handle function_name_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
UNWRAP_AND_CHECK_PARAM(Library, library, library_in);
|
|
UNWRAP_AND_CHECK_PARAM(String, class_name, class_name_in);
|
|
UNWRAP_AND_CHECK_PARAM(String, function_name, function_name_in);
|
|
|
|
// Ensure that the library is loaded.
|
|
if (!library.Loaded()) {
|
|
return Api::NewError(
|
|
"%s expects library argument 'library_in' to be loaded.",
|
|
CURRENT_FUNC);
|
|
}
|
|
|
|
// Resolve the breakpoint target function.
|
|
Debugger* debugger = I->debugger();
|
|
const Function& bp_target = Function::Handle(
|
|
debugger->ResolveFunction(library, class_name, function_name));
|
|
if (bp_target.IsNull()) {
|
|
const bool toplevel = class_name.Length() == 0;
|
|
return Api::NewError("%s: could not find function '%s%s%s'",
|
|
CURRENT_FUNC,
|
|
toplevel ? "" : class_name.ToCString(),
|
|
toplevel ? "" : ".",
|
|
function_name.ToCString());
|
|
}
|
|
|
|
Breakpoint* bpt = debugger->SetBreakpointAtEntry(bp_target, false);
|
|
if (bpt == NULL) {
|
|
const char* target_name = Debugger::QualifiedFunctionName(bp_target);
|
|
return Api::NewError("%s: no breakpoint location found in '%s'",
|
|
CURRENT_FUNC, target_name);
|
|
}
|
|
return Dart_NewInteger(bpt->id());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_OneTimeBreakAtEntry(
|
|
Dart_Handle library_in,
|
|
Dart_Handle class_name_in,
|
|
Dart_Handle function_name_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
UNWRAP_AND_CHECK_PARAM(Library, library, library_in);
|
|
UNWRAP_AND_CHECK_PARAM(String, class_name, class_name_in);
|
|
UNWRAP_AND_CHECK_PARAM(String, function_name, function_name_in);
|
|
|
|
// Ensure that the library is loaded.
|
|
if (!library.Loaded()) {
|
|
return Api::NewError(
|
|
"%s expects library argument 'library_in' to be loaded.",
|
|
CURRENT_FUNC);
|
|
}
|
|
|
|
// Resolve the breakpoint target function.
|
|
Debugger* debugger = I->debugger();
|
|
const Function& bp_target = Function::Handle(
|
|
debugger->ResolveFunction(library, class_name, function_name));
|
|
if (bp_target.IsNull()) {
|
|
const bool toplevel = class_name.Length() == 0;
|
|
return Api::NewError("%s: could not find function '%s%s%s'",
|
|
CURRENT_FUNC,
|
|
toplevel ? "" : class_name.ToCString(),
|
|
toplevel ? "" : ".",
|
|
function_name.ToCString());
|
|
}
|
|
|
|
const Error& error = Error::Handle(Z,
|
|
debugger->OneTimeBreakAtEntry(bp_target));
|
|
if (!error.IsNull()) {
|
|
return Api::NewHandle(T, error.raw());
|
|
}
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_RemoveBreakpoint(intptr_t bp_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
I->debugger()->RemoveBreakpoint(bp_id);
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_SetStepOver() {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
I->debugger()->SetStepOver();
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_SetStepInto() {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
I->debugger()->SetSingleStep();
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_SetStepOut() {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
I->debugger()->SetStepOut();
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetInstanceFields(Dart_Handle object_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in);
|
|
return Api::NewHandle(T, I->debugger()->GetInstanceFields(obj));
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle target) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
const Type& type_obj = Api::UnwrapTypeHandle(Z, target);
|
|
if (type_obj.IsNull()) {
|
|
return Api::NewError("%s expects argument 'target' to be a type",
|
|
CURRENT_FUNC);
|
|
}
|
|
const Class& cls = Class::Handle(Z, type_obj.type_class());
|
|
return Api::NewHandle(T, I->debugger()->GetStaticFields(cls));
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetLibraryFields(intptr_t library_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
const Library& lib =
|
|
Library::Handle(Z, Library::GetLibrary(library_id));
|
|
if (lib.IsNull()) {
|
|
return Api::NewError("%s: %" Pd " is not a valid library id",
|
|
CURRENT_FUNC, library_id);
|
|
}
|
|
return Api::NewHandle(T, I->debugger()->GetLibraryFields(lib));
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetGlobalVariables(intptr_t library_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
|
|
const Library& lib = Library::Handle(Z, Library::GetLibrary(library_id));
|
|
if (lib.IsNull()) {
|
|
return Api::NewError("%s: %" Pd " is not a valid library id",
|
|
CURRENT_FUNC, library_id);
|
|
}
|
|
return Api::NewHandle(T, I->debugger()->GetGlobalFields(lib));
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ActivationFrameEvaluate(
|
|
Dart_ActivationFrame activation_frame,
|
|
Dart_Handle expr_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
|
|
UNWRAP_AND_CHECK_PARAM(String, expr, expr_in);
|
|
return Api::NewHandle(T, frame->Evaluate(expr));
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_EvaluateExpr(Dart_Handle target_in,
|
|
Dart_Handle expr_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
|
|
const Object& target = Object::Handle(Z, Api::UnwrapHandle(target_in));
|
|
if (target.IsError()) return target_in;
|
|
if (target.IsNull()) {
|
|
return Api::NewError("%s expects argument 'target' to be non-null",
|
|
CURRENT_FUNC);
|
|
}
|
|
UNWRAP_AND_CHECK_PARAM(String, expr, expr_in);
|
|
// Type extends Instance, must check first.
|
|
if (target.IsType()) {
|
|
const Class& cls = Class::Handle(Z, Type::Cast(target).type_class());
|
|
return Api::NewHandle(T, cls.Evaluate(expr,
|
|
Array::empty_array(),
|
|
Array::empty_array()));
|
|
} else if (target.IsInstance()) {
|
|
const Instance& inst = Instance::Cast(target);
|
|
const Class& receiver_cls = Class::Handle(Z, inst.clazz());
|
|
return Api::NewHandle(T, inst.Evaluate(receiver_cls,
|
|
expr,
|
|
Array::empty_array(),
|
|
Array::empty_array()));
|
|
} else if (target.IsLibrary()) {
|
|
const Library& lib = Library::Cast(target);
|
|
return Api::NewHandle(T, lib.Evaluate(expr,
|
|
Array::empty_array(),
|
|
Array::empty_array()));
|
|
} else if (target.IsClass()) {
|
|
const Class& cls = Class::Cast(target);
|
|
return Api::NewHandle(T, cls.Evaluate(expr,
|
|
Array::empty_array(),
|
|
Array::empty_array()));
|
|
}
|
|
return Api::NewError("%s: unsupported target type", CURRENT_FUNC);
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetObjClass(Dart_Handle object_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in);
|
|
return Api::NewHandle(T, obj.GetType());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetObjClassId(Dart_Handle object_in,
|
|
intptr_t* class_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in);
|
|
CHECK_NOT_NULL(class_id);
|
|
*class_id = obj.GetClassId();
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetClassFromId(intptr_t class_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
if (!I->class_table()->IsValidIndex(class_id)) {
|
|
return Api::NewError("%s: %" Pd " is not a valid class id",
|
|
CURRENT_FUNC, class_id);
|
|
}
|
|
return Api::NewHandle(T, I->class_table()->At(class_id));
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetSupertype(Dart_Handle type_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
|
|
UNWRAP_AND_CHECK_PARAM(Type, type, type_in);
|
|
if (!type.IsFinalized()) {
|
|
return Api::NewError("%s: type in 'type_in' is not a finalized type",
|
|
CURRENT_FUNC);
|
|
}
|
|
if (!type.IsInstantiated()) {
|
|
return Api::NewError("%s: type in 'type_in' is not an instantiated type",
|
|
CURRENT_FUNC);
|
|
}
|
|
const Class& cls = Class::Handle(type.type_class());
|
|
if (cls.NumTypeParameters() == 0) {
|
|
// The super type has no type parameters or it is already instantiated
|
|
// just return it.
|
|
const AbstractType& type = AbstractType::Handle(cls.super_type());
|
|
if (type.IsNull()) {
|
|
return Dart_Null();
|
|
}
|
|
return Api::NewHandle(T, type.Canonicalize());
|
|
}
|
|
// Set up the type arguments array for the super class type.
|
|
const Class& super_cls = Class::Handle(cls.SuperClass());
|
|
intptr_t num_expected_type_arguments = super_cls.NumTypeArguments();
|
|
TypeArguments& super_type_args_array = TypeArguments::Handle();
|
|
const TypeArguments& type_args_array =
|
|
TypeArguments::Handle(type.arguments());
|
|
if (!type_args_array.IsNull() && (num_expected_type_arguments > 0)) {
|
|
super_type_args_array = TypeArguments::New(num_expected_type_arguments);
|
|
AbstractType& type_arg = AbstractType::Handle();
|
|
for (intptr_t i = 0; i < num_expected_type_arguments; i++) {
|
|
type_arg ^= type_args_array.TypeAt(i);
|
|
super_type_args_array.SetTypeAt(i, type_arg);
|
|
}
|
|
}
|
|
|
|
// Construct the super type object, canonicalize it and return.
|
|
Type& instantiated_type = Type::Handle(
|
|
Type::New(super_cls, super_type_args_array, TokenPosition::kNoSource));
|
|
ASSERT(!instantiated_type.IsNull());
|
|
instantiated_type.SetIsFinalized();
|
|
return Api::NewHandle(T, instantiated_type.Canonicalize());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetClosureInfo(
|
|
Dart_Handle closure,
|
|
Dart_Handle* name,
|
|
Dart_Handle* signature,
|
|
Dart_CodeLocation* location) {
|
|
DARTSCOPE(Thread::Current());
|
|
UNWRAP_AND_CHECK_PARAM(Instance, instance, closure);
|
|
CHECK_NOT_NULL(location);
|
|
|
|
if (!instance.IsClosure()) {
|
|
return Api::NewError("%s: parameter 0 is not a closure", CURRENT_FUNC);
|
|
}
|
|
const Function& func = Function::Handle(Closure::Cast(instance).function());
|
|
ASSERT(!func.IsNull());
|
|
if (name != NULL) {
|
|
*name = Api::NewHandle(T, func.QualifiedUserVisibleName());
|
|
}
|
|
if (signature != NULL) {
|
|
*signature = Api::NewHandle(T, func.UserVisibleSignature());
|
|
}
|
|
|
|
if (location != NULL) {
|
|
if (func.token_pos().IsReal()) {
|
|
const Class& cls = Class::Handle(Z, func.origin());
|
|
ASSERT(!cls.IsNull());
|
|
const Library& lib = Library::Handle(Z, cls.library());
|
|
ASSERT(!lib.IsNull());
|
|
// Note func.script() is not the same as cls.script() for eval functions.
|
|
const Script& script = Script::Handle(Z, func.script());
|
|
ASSERT(!script.IsNull());
|
|
location->script_url = Api::NewHandle(T, script.url());
|
|
location->library_id = lib.index();
|
|
location->token_pos = func.token_pos().Pos();
|
|
} else {
|
|
location->script_url = Api::NewHandle(T, String::null());
|
|
location->library_id = -1;
|
|
location->token_pos = -1;
|
|
}
|
|
}
|
|
return Api::True();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetClassInfo(
|
|
intptr_t cls_id,
|
|
Dart_Handle* class_name,
|
|
intptr_t* library_id,
|
|
intptr_t* super_class_id,
|
|
Dart_Handle* static_fields) {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
if (!I->class_table()->IsValidIndex(cls_id)) {
|
|
return Api::NewError("%s: %" Pd " is not a valid class id",
|
|
CURRENT_FUNC, cls_id);
|
|
}
|
|
Class& cls = Class::Handle(Z, I->class_table()->At(cls_id));
|
|
if (class_name != NULL) {
|
|
*class_name = Api::NewHandle(T, cls.Name());
|
|
}
|
|
if (library_id != NULL) {
|
|
const Library& lib = Library::Handle(Z, cls.library());
|
|
*library_id = lib.index();
|
|
}
|
|
if (super_class_id != NULL) {
|
|
*super_class_id = 0;
|
|
Class& super_cls = Class::Handle(Z, cls.SuperClass());
|
|
if (!super_cls.IsNull()) {
|
|
*super_class_id = super_cls.id();
|
|
}
|
|
}
|
|
if (static_fields != NULL) {
|
|
*static_fields =
|
|
Api::NewHandle(T, I->debugger()->GetStaticFields(cls));
|
|
}
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ScriptGetSource(
|
|
intptr_t library_id,
|
|
Dart_Handle script_url_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
const Library& lib = Library::Handle(Library::GetLibrary(library_id));
|
|
if (lib.IsNull()) {
|
|
return Api::NewError("%s: %" Pd " is not a valid library id",
|
|
CURRENT_FUNC, library_id);
|
|
}
|
|
UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
|
|
const Script& script = Script::Handle(lib.LookupScript(script_url));
|
|
if (script.IsNull()) {
|
|
return Api::NewError("%s: script '%s' not found in library '%s'",
|
|
CURRENT_FUNC, script_url.ToCString(),
|
|
String::Handle(lib.url()).ToCString());
|
|
}
|
|
return Api::NewHandle(T, script.Source());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_ScriptGetTokenInfo(
|
|
intptr_t library_id,
|
|
Dart_Handle script_url_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
const Library& lib = Library::Handle(Library::GetLibrary(library_id));
|
|
if (lib.IsNull()) {
|
|
return Api::NewError("%s: %" Pd " is not a valid library id",
|
|
CURRENT_FUNC, library_id);
|
|
}
|
|
UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
|
|
const Script& script = Script::Handle(lib.LookupScript(script_url));
|
|
if (script.IsNull()) {
|
|
return Api::NewError("%s: script '%s' not found in library '%s'",
|
|
CURRENT_FUNC, script_url.ToCString(),
|
|
String::Handle(lib.url()).ToCString());
|
|
}
|
|
|
|
const GrowableObjectArray& info =
|
|
GrowableObjectArray::Handle(script.GenerateLineNumberArray());
|
|
return Api::NewHandle(T, Array::MakeArray(info));
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GenerateScriptSource(Dart_Handle library_url_in,
|
|
Dart_Handle script_url_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
UNWRAP_AND_CHECK_PARAM(String, library_url, library_url_in);
|
|
UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
|
|
|
|
const Library& library = Library::Handle(Library::LookupLibrary(library_url));
|
|
if (library.IsNull()) {
|
|
return Api::NewError("%s: library '%s' not found",
|
|
CURRENT_FUNC, library_url.ToCString());
|
|
}
|
|
|
|
const Script& script = Script::Handle(library.LookupScript(script_url));
|
|
if (script.IsNull()) {
|
|
return Api::NewError("%s: script '%s' not found in library '%s'",
|
|
CURRENT_FUNC, script_url.ToCString(),
|
|
library_url.ToCString());
|
|
}
|
|
|
|
return Api::NewHandle(T, script.GenerateSource());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetScriptURLs(Dart_Handle library_url_in) {
|
|
DARTSCOPE(Thread::Current());
|
|
UNWRAP_AND_CHECK_PARAM(String, library_url, library_url_in);
|
|
|
|
const Library& library = Library::Handle(Library::LookupLibrary(library_url));
|
|
if (library.IsNull()) {
|
|
return Api::NewError("%s: library '%s' not found",
|
|
CURRENT_FUNC, library_url.ToCString());
|
|
}
|
|
const Array& loaded_scripts = Array::Handle(library.LoadedScripts());
|
|
ASSERT(!loaded_scripts.IsNull());
|
|
intptr_t num_scripts = loaded_scripts.Length();
|
|
const Array& script_list = Array::Handle(Array::New(num_scripts));
|
|
Script& script = Script::Handle();
|
|
String& url = String::Handle();
|
|
for (int i = 0; i < num_scripts; i++) {
|
|
script ^= loaded_scripts.At(i);
|
|
url = script.url();
|
|
script_list.SetAt(i, url);
|
|
}
|
|
return Api::NewHandle(T, script_list.raw());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetLibraryIds() {
|
|
DARTSCOPE(Thread::Current());
|
|
Isolate* I = T->isolate();
|
|
|
|
const GrowableObjectArray& libs =
|
|
GrowableObjectArray::Handle(Z, I->object_store()->libraries());
|
|
int num_libs = libs.Length();
|
|
|
|
// Create new list and populate with the url of loaded libraries.
|
|
Library &lib = Library::Handle();
|
|
const Array& library_id_list = Array::Handle(Z, Array::New(num_libs));
|
|
for (int i = 0; i < num_libs; i++) {
|
|
lib ^= libs.At(i);
|
|
ASSERT(!lib.IsNull());
|
|
ASSERT(Smi::IsValid(lib.index()));
|
|
library_id_list.SetAt(i, Smi::Handle(Smi::New(lib.index())));
|
|
}
|
|
return Api::NewHandle(T, library_id_list.raw());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetLibraryFromId(intptr_t library_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
const Library& lib = Library::Handle(Z, Library::GetLibrary(library_id));
|
|
if (lib.IsNull()) {
|
|
return Api::NewError("%s: %" Pd " is not a valid library id",
|
|
CURRENT_FUNC, library_id);
|
|
}
|
|
return Api::NewHandle(T, lib.raw());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
|
|
intptr_t* library_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
const Library& lib = Api::UnwrapLibraryHandle(Z, library);
|
|
if (lib.IsNull()) {
|
|
RETURN_TYPE_ERROR(Z, library, Library);
|
|
}
|
|
if (library_id == NULL) {
|
|
RETURN_NULL_ERROR(library_id);
|
|
}
|
|
*library_id = lib.index();
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetLibraryImports(intptr_t library_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
const Library& lib = Library::Handle(Library::GetLibrary(library_id));
|
|
if (lib.IsNull()) {
|
|
return Api::NewError("%s: %" Pd " is not a valid library id",
|
|
CURRENT_FUNC, library_id);
|
|
}
|
|
const GrowableObjectArray& import_list =
|
|
GrowableObjectArray::Handle(GrowableObjectArray::New(8));
|
|
|
|
String& prefix_name = String::Handle(Z);
|
|
Library& imported = Library::Handle(Z);
|
|
intptr_t num_imports = lib.num_imports();
|
|
for (int i = 0; i < num_imports; i++) {
|
|
import_list.Add(prefix_name); // Null prefix name means no prefix.
|
|
imported = lib.ImportLibraryAt(i);
|
|
ASSERT(!imported.IsNull());
|
|
ASSERT(Smi::IsValid(imported.index()));
|
|
import_list.Add(Smi::Handle(Z, Smi::New(imported.index())));
|
|
}
|
|
LibraryPrefixIterator it(lib);
|
|
LibraryPrefix& prefix = LibraryPrefix::Handle(Z);
|
|
while (it.HasNext()) {
|
|
prefix = it.GetNext();
|
|
prefix_name = prefix.name();
|
|
ASSERT(!prefix_name.IsNull());
|
|
prefix_name = String::Concat(prefix_name, Symbols::Dot());
|
|
for (int32_t i = 0; i < prefix.num_imports(); i++) {
|
|
imported = prefix.GetLibrary(i);
|
|
import_list.Add(prefix_name);
|
|
import_list.Add(Smi::Handle(Smi::New(imported.index())));
|
|
}
|
|
}
|
|
return Api::NewHandle(T, Array::MakeArray(import_list));
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetLibraryURL(intptr_t library_id) {
|
|
DARTSCOPE(Thread::Current());
|
|
const Library& lib = Library::Handle(Z, Library::GetLibrary(library_id));
|
|
if (lib.IsNull()) {
|
|
return Api::NewError("%s: %" Pd " is not a valid library id",
|
|
CURRENT_FUNC, library_id);
|
|
}
|
|
return Api::NewHandle(T, lib.url());
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_GetLibraryDebuggable(intptr_t library_id,
|
|
bool* is_debuggable) {
|
|
DARTSCOPE(Thread::Current());
|
|
CHECK_NOT_NULL(is_debuggable);
|
|
const Library& lib = Library::Handle(Library::GetLibrary(library_id));
|
|
if (lib.IsNull()) {
|
|
return Api::NewError("%s: %" Pd " is not a valid library id",
|
|
CURRENT_FUNC, library_id);
|
|
}
|
|
*is_debuggable = lib.IsDebuggable();
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Handle Dart_SetLibraryDebuggable(intptr_t library_id,
|
|
bool is_debuggable) {
|
|
DARTSCOPE(Thread::Current());
|
|
const Library& lib = Library::Handle(Z, Library::GetLibrary(library_id));
|
|
if (lib.IsNull()) {
|
|
return Api::NewError("%s: %" Pd " is not a valid library id",
|
|
CURRENT_FUNC, library_id);
|
|
}
|
|
lib.set_debuggable(is_debuggable);
|
|
return Api::Success();
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_Isolate Dart_GetIsolate(Dart_IsolateId isolate_id) {
|
|
Isolate* isolate = PortMap::GetIsolate(isolate_id);
|
|
return Api::CastIsolate(isolate);
|
|
}
|
|
|
|
|
|
DART_EXPORT Dart_IsolateId Dart_GetIsolateId(Dart_Isolate dart_isolate) {
|
|
Isolate* isolate = reinterpret_cast<Isolate*>(dart_isolate);
|
|
return isolate->debugger()->GetIsolateId();
|
|
}
|
|
|
|
#else
|
|
|
|
DART_EXPORT void Dart_SetPausedEventHandler(Dart_PausedEventHandler handler) {
|
|
// NOOP.
|
|
}
|
|
|
|
#endif // !PRODUCT
|
|
|
|
} // namespace dart
|