// 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_debugger_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 { #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(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) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); const Object& obj = Object::Handle(Api::UnwrapHandle(object_in)); if (obj.IsApiError()) { return -1; } return isolate->debugger()->CacheObject(obj); } DART_EXPORT Dart_Handle Dart_GetCachedObject(intptr_t obj_id) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); if (!isolate->debugger()->IsValidObjectId(obj_id)) { return Api::NewError("%s: object id %" Pd " is invalid", CURRENT_FUNC, obj_id); } return Api::NewHandle(isolate, isolate->debugger()->GetCachedObject(obj_id)); } DART_EXPORT Dart_Handle Dart_StackTraceLength( Dart_StackTrace trace, intptr_t* length) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); 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) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); 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( 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) { Isolate* isolate = Isolate::Current(); ASSERT(isolate != NULL); ASSERT(isolate->debugger() != 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(isolate, top_frame->SourceUrl()); const Library& lib = Library::Handle(top_frame->Library()); location.library_id = lib.index(); location.token_pos = top_frame->TokenPos(); 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) { SourceBreakpoint* bpt = event->breakpoint(); ASSERT(bpt != NULL); Dart_CodeLocation location; Library& library = Library::Handle(isolate); Script& script = Script::Handle(isolate); intptr_t token_pos; bpt->GetCodeLocation(&library, &script, &token_pos); location.script_url = Api::NewHandle(isolate, script.url()); location.library_id = library.index(); location.token_pos = token_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(isolate, event->exception()->raw()); Dart_StackTrace trace = reinterpret_cast(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) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); isolate->debugger()->SetExceptionPauseInfo(pause_info); return Api::Success(); } DART_EXPORT Dart_ExceptionPauseInfo Dart_GetExceptionPauseInfo() { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); return isolate->debugger()->GetExceptionPauseInfo(); } DART_EXPORT Dart_Handle Dart_GetStackTrace(Dart_StackTrace* trace) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); CHECK_NOT_NULL(trace); *trace = reinterpret_cast( isolate->debugger()->CurrentStackTrace()); return Api::Success(); } DART_EXPORT Dart_Handle Dart_GetStackTraceFromError(Dart_Handle handle, Dart_StackTrace* trace) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); CHECK_NOT_NULL(trace); const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle)); if (obj.IsUnhandledException()) { const UnhandledException& error = UnhandledException::Cast(obj); Stacktrace& dart_stacktrace = Stacktrace::Handle(isolate); dart_stacktrace ^= error.stacktrace(); if (dart_stacktrace.IsNull()) { *trace = NULL; } else { *trace = reinterpret_cast( isolate->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) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); CHECK_AND_CAST(ActivationFrame, frame, activation_frame); if (function_name != NULL) { *function_name = Api::NewHandle(isolate, frame->QualifiedFunctionName()); } if (script_url != NULL) { *script_url = Api::NewHandle(isolate, 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. Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); CHECK_AND_CAST(ActivationFrame, frame, activation_frame); if (function_name != NULL) { *function_name = Api::NewHandle(isolate, frame->QualifiedFunctionName()); } if (function != NULL) { *function = Api::NewHandle(isolate, frame->function().raw()); } if (location != NULL) { location->script_url = Api::NewHandle(isolate, frame->SourceUrl()); const Library& lib = Library::Handle(frame->Library()); location->library_id = lib.index(); location->token_pos = frame->TokenPos(); } return Api::Success(); } DART_EXPORT Dart_Handle Dart_ActivationFrameGetFramePointer( Dart_ActivationFrame activation_frame, uintptr_t* frame_pointer) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); CHECK_AND_CAST(ActivationFrame, frame, activation_frame); if (frame_pointer != NULL) { *frame_pointer = static_cast(frame->fp()); } return Api::Success(); } DART_EXPORT Dart_Handle Dart_GetFunctionOrigin(Dart_Handle function_in) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); UNWRAP_AND_CHECK_PARAM(Function, function, function_in); const Class& cls = Class::Handle(function.origin()); if (!cls.IsTopLevel()) { return Dart_NewInteger(cls.id()); } return Api::Null(); } DART_EXPORT Dart_Handle Dart_GetLocalVariables( Dart_ActivationFrame activation_frame) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); CHECK_AND_CAST(ActivationFrame, frame, activation_frame); return Api::NewHandle(isolate, frame->GetLocalVariables()); } DART_EXPORT Dart_Handle Dart_SetBreakpoint( Dart_Handle script_url_in, intptr_t line_number) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in); Debugger* debugger = isolate->debugger(); ASSERT(debugger != NULL); SourceBreakpoint* 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) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); Debugger* debugger = isolate->debugger(); ASSERT(debugger != NULL); SourceBreakpoint* 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(isolate, bpt->url()); } DART_EXPORT Dart_Handle Dart_GetBreakpointLine(intptr_t bp_id) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); Debugger* debugger = isolate->debugger(); ASSERT(debugger != NULL); SourceBreakpoint* bpt = debugger->GetBreakpointById(bp_id); if (bpt == NULL) { return Api::NewError("%s: breakpoint with id %" Pd " does not exist", CURRENT_FUNC, bp_id); } return Dart_NewInteger(bpt->LineNumber()); } DART_EXPORT Dart_Handle Dart_SetBreakpointAtEntry( Dart_Handle library_in, Dart_Handle class_name_in, Dart_Handle function_name_in) { Isolate* isolate = Isolate::Current(); DARTSCOPE(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 = isolate->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()); } SourceBreakpoint* bpt = debugger->SetBreakpointAtEntry(bp_target); 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) { Isolate* isolate = Isolate::Current(); DARTSCOPE(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 = isolate->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(isolate, debugger->OneTimeBreakAtEntry(bp_target)); if (!error.IsNull()) { return Api::NewHandle(isolate, error.raw()); } return Api::Success(); } DART_EXPORT Dart_Handle Dart_RemoveBreakpoint(intptr_t bp_id) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); Debugger* debugger = isolate->debugger(); ASSERT(debugger != NULL); isolate->debugger()->RemoveBreakpoint(bp_id); return Api::Success(); } DART_EXPORT Dart_Handle Dart_SetStepOver() { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); isolate->debugger()->SetStepOver(); return Api::Success(); } DART_EXPORT Dart_Handle Dart_SetStepInto() { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); isolate->debugger()->SetSingleStep(); return Api::Success(); } DART_EXPORT Dart_Handle Dart_SetStepOut() { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); isolate->debugger()->SetStepOut(); return Api::Success(); } DART_EXPORT Dart_Handle Dart_GetInstanceFields(Dart_Handle object_in) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in); return Api::NewHandle(isolate, isolate->debugger()->GetInstanceFields(obj)); } DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle target) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); const Type& type_obj = Api::UnwrapTypeHandle(isolate, target); if (type_obj.IsNull()) { return Api::NewError("%s expects argument 'target' to be a type", CURRENT_FUNC); } const Class& cls = Class::Handle(isolate, type_obj.type_class()); return Api::NewHandle(isolate, isolate->debugger()->GetStaticFields(cls)); } DART_EXPORT Dart_Handle Dart_GetLibraryFields(intptr_t library_id) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); const Library& lib = Library::Handle(isolate, 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(isolate, isolate->debugger()->GetLibraryFields(lib)); } DART_EXPORT Dart_Handle Dart_GetGlobalVariables(intptr_t library_id) { Isolate* isolate = Isolate::Current(); ASSERT(isolate != NULL); DARTSCOPE(isolate); 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); } return Api::NewHandle(isolate, isolate->debugger()->GetGlobalFields(lib)); } DART_EXPORT Dart_Handle Dart_ActivationFrameEvaluate( Dart_ActivationFrame activation_frame, Dart_Handle expr_in) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); CHECK_AND_CAST(ActivationFrame, frame, activation_frame); UNWRAP_AND_CHECK_PARAM(String, expr, expr_in); return Api::NewHandle(isolate, frame->Evaluate(expr)); } DART_EXPORT Dart_Handle Dart_EvaluateExpr(Dart_Handle target_in, Dart_Handle expr_in) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); const Object& target = Object::Handle(isolate, 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(isolate, Type::Cast(target).type_class()); return Api::NewHandle(isolate, cls.Evaluate(expr, Array::empty_array(), Array::empty_array())); } else if (target.IsInstance()) { const Instance& inst = Instance::Cast(target); return Api::NewHandle(isolate, inst.Evaluate(expr, Array::empty_array(), Array::empty_array())); } else if (target.IsLibrary()) { const Library& lib = Library::Cast(target); return Api::NewHandle(isolate, lib.Evaluate(expr, Array::empty_array(), Array::empty_array())); } else if (target.IsClass()) { const Class& cls = Class::Cast(target); return Api::NewHandle(isolate, 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) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in); return Api::NewHandle(isolate, obj.GetType()); } DART_EXPORT Dart_Handle Dart_GetObjClassId(Dart_Handle object_in, intptr_t* class_id) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); 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) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); if (!isolate->class_table()->IsValidIndex(class_id)) { return Api::NewError("%s: %" Pd " is not a valid class id", CURRENT_FUNC, class_id); } return Api::NewHandle(isolate, isolate->class_table()->At(class_id)); } DART_EXPORT Dart_Handle Dart_GetSupertype(Dart_Handle type_in) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); 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(isolate, 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, Scanner::kNoSourcePos)); ASSERT(!instantiated_type.IsNull()); instantiated_type.SetIsFinalized(); return Api::NewHandle(isolate, instantiated_type.Canonicalize()); } DART_EXPORT Dart_Handle Dart_GetClosureInfo( Dart_Handle closure, Dart_Handle* name, Dart_Handle* signature, Dart_CodeLocation* location) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); 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::function(instance)); ASSERT(!func.IsNull()); if (name != NULL) { *name = Api::NewHandle(isolate, func.QualifiedUserVisibleName()); } if (signature != NULL) { *signature = Api::NewHandle(isolate, func.UserVisibleSignature()); } if (location != NULL) { if (func.token_pos() >= 0) { const Class& cls = Class::Handle(func.origin()); ASSERT(!cls.IsNull()); const Library& lib = Library::Handle(isolate, cls.library()); ASSERT(!lib.IsNull()); // Note func.script() is not the same as cls.script() for eval functions. const Script& script = Script::Handle(func.script()); ASSERT(!script.IsNull()); location->script_url = Api::NewHandle(isolate, script.url()); location->library_id = lib.index(); location->token_pos = func.token_pos(); } else { location->script_url = Api::NewHandle(isolate, 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) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); if (!isolate->class_table()->IsValidIndex(cls_id)) { return Api::NewError("%s: %" Pd " is not a valid class id", CURRENT_FUNC, cls_id); } Class& cls = Class::Handle(isolate, isolate->class_table()->At(cls_id)); if (class_name != NULL) { *class_name = Api::NewHandle(isolate, cls.Name()); } if (library_id != NULL) { const Library& lib = Library::Handle(isolate, cls.library()); *library_id = lib.index(); } if (super_class_id != NULL) { *super_class_id = 0; Class& super_cls = Class::Handle(isolate, cls.SuperClass()); if (!super_cls.IsNull()) { *super_class_id = super_cls.id(); } } if (static_fields != NULL) { *static_fields = Api::NewHandle(isolate, isolate->debugger()->GetStaticFields(cls)); } return Api::Success(); } DART_EXPORT Dart_Handle Dart_ScriptGetSource( intptr_t library_id, Dart_Handle script_url_in) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); 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(isolate, script.Source()); } DART_EXPORT Dart_Handle Dart_ScriptGetTokenInfo( intptr_t library_id, Dart_Handle script_url_in) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); 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(isolate, Array::MakeArray(info)); } DART_EXPORT Dart_Handle Dart_GenerateScriptSource(Dart_Handle library_url_in, Dart_Handle script_url_in) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); 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(isolate, script.GenerateSource()); } DART_EXPORT Dart_Handle Dart_GetScriptURLs(Dart_Handle library_url_in) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); 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(isolate, script_list.raw()); } DART_EXPORT Dart_Handle Dart_GetLibraryIds() { Isolate* isolate = Isolate::Current(); ASSERT(isolate != NULL); DARTSCOPE(isolate); const GrowableObjectArray& libs = GrowableObjectArray::Handle(isolate->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(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(isolate, library_id_list.raw()); } DART_EXPORT Dart_Handle Dart_GetLibraryFromId(intptr_t library_id) { Isolate* isolate = Isolate::Current(); ASSERT(isolate != NULL); DARTSCOPE(isolate); 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); } return Api::NewHandle(isolate, lib.raw()); } DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library, intptr_t* library_id) { Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate); const Library& lib = Api::UnwrapLibraryHandle(isolate, library); if (lib.IsNull()) { RETURN_TYPE_ERROR(isolate, 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) { Isolate* isolate = Isolate::Current(); ASSERT(isolate != NULL); DARTSCOPE(isolate); 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(isolate); Library& imported = Library::Handle(isolate); 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(Smi::New(imported.index()))); } LibraryPrefixIterator it(lib); LibraryPrefix& prefix = LibraryPrefix::Handle(isolate); 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(isolate, Array::MakeArray(import_list)); } DART_EXPORT Dart_Handle Dart_GetLibraryURL(intptr_t library_id) { Isolate* isolate = Isolate::Current(); ASSERT(isolate != NULL); DARTSCOPE(isolate); 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); } return Api::NewHandle(isolate, lib.url()); } DART_EXPORT Dart_Handle Dart_GetLibraryDebuggable(intptr_t library_id, bool* is_debuggable) { Isolate* isolate = Isolate::Current(); ASSERT(isolate != NULL); DARTSCOPE(isolate); 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) { Isolate* isolate = Isolate::Current(); ASSERT(isolate != NULL); DARTSCOPE(isolate); 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); } 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(dart_isolate); return isolate->debugger()->GetIsolateId(); } } // namespace dart