1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include <include/dart_api.h>
6#include "include/dart_tools_api.h"
7
8#include "vm/class_finalizer.h"
9#include "vm/compiler/jit/compiler.h"
10#include "vm/dart_api_impl.h"
11#include "vm/dart_api_state.h"
12#include "vm/debugger.h"
13#include "vm/debugger_api_impl_test.h"
14#include "vm/isolate.h"
15#include "vm/object_store.h"
16#include "vm/symbols.h"
17
18namespace dart {
19
20// Facilitate quick access to the current zone once we have the current thread.
21#define Z (T->zone())
22
23#ifndef PRODUCT
24
25#define UNWRAP_AND_CHECK_PARAM(type, var, param) \
26 type& var = type::Handle(); \
27 do { \
28 const Object& tmp = Object::Handle(Api::UnwrapHandle(param)); \
29 if (tmp.IsNull()) { \
30 return Api::NewError("%s expects argument '%s' to be non-null.", \
31 CURRENT_FUNC, #param); \
32 } else if (tmp.IsApiError()) { \
33 return param; \
34 } else if (!tmp.Is##type()) { \
35 return Api::NewError("%s expects argument '%s' to be of type %s.", \
36 CURRENT_FUNC, #param, #type); \
37 } \
38 var ^= tmp.ptr(); \
39 } while (0)
40
41#define CHECK_AND_CAST(type, var, param) \
42 type* var = nullptr; \
43 do { \
44 if (param == nullptr) { \
45 return Api::NewError("%s expects argument '%s' to be non-null.", \
46 CURRENT_FUNC, #param); \
47 } \
48 var = reinterpret_cast<type*>(param); \
49 } while (0)
50
51#define CHECK_NOT_NULL(param) \
52 if (param == nullptr) { \
53 return Api::NewError("%s expects argument '%s' to be non-null.", \
54 CURRENT_FUNC, #param); \
55 }
56
57#define CHECK_DEBUGGER(isolate) \
58 if (isolate->debugger() == nullptr) { \
59 return Api::NewError("%s requires debugger support.", CURRENT_FUNC); \
60 }
61
62DART_EXPORT Dart_Handle Dart_StackTraceLength(Dart_StackTrace trace,
63 intptr_t* length) {
64 DARTSCOPE(Thread::Current());
65 CHECK_NOT_NULL(length);
66 CHECK_AND_CAST(DebuggerStackTrace, stack_trace, trace);
67 *length = stack_trace->Length();
68 return Api::Success();
69}
70
71DART_EXPORT Dart_Handle Dart_GetActivationFrame(Dart_StackTrace trace,
72 int frame_index,
73 Dart_ActivationFrame* frame) {
74 DARTSCOPE(Thread::Current());
75 CHECK_NOT_NULL(frame);
76 CHECK_AND_CAST(DebuggerStackTrace, stack_trace, trace);
77 if ((frame_index < 0) || (frame_index >= stack_trace->Length())) {
78 return Api::NewError(format: "argument 'frame_index' is out of range for %s",
79 CURRENT_FUNC);
80 }
81 *frame =
82 reinterpret_cast<Dart_ActivationFrame>(stack_trace->FrameAt(i: frame_index));
83 return Api::Success();
84}
85
86DART_EXPORT Dart_Handle Dart_GetStackTrace(Dart_StackTrace* trace) {
87 DARTSCOPE(Thread::Current());
88 Isolate* I = T->isolate();
89 CHECK_DEBUGGER(I);
90 CHECK_NOT_NULL(trace);
91 *trace = reinterpret_cast<Dart_StackTrace>(DebuggerStackTrace::Collect());
92 return Api::Success();
93}
94
95DART_EXPORT Dart_Handle Dart_GetStackTraceFromError(Dart_Handle handle,
96 Dart_StackTrace* trace) {
97 DARTSCOPE(Thread::Current());
98 CHECK_DEBUGGER(T->isolate());
99 CHECK_NOT_NULL(trace);
100 const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object: handle));
101 if (obj.IsUnhandledException()) {
102 const UnhandledException& error = UnhandledException::Cast(obj);
103 StackTrace& dart_stacktrace = StackTrace::Handle(Z);
104 dart_stacktrace ^= error.stacktrace();
105 if (dart_stacktrace.IsNull()) {
106 *trace = nullptr;
107 } else {
108 *trace = reinterpret_cast<Dart_StackTrace>(
109 DebuggerStackTrace::From(ex_trace: dart_stacktrace));
110 }
111 return Api::Success();
112 } else {
113 return Api::NewError(
114 format: "Can only get stacktraces from error handles or "
115 "instances of Error.");
116 }
117}
118
119DART_EXPORT Dart_Handle
120Dart_ActivationFrameInfo(Dart_ActivationFrame activation_frame,
121 Dart_Handle* function_name,
122 Dart_Handle* script_url,
123 intptr_t* line_number,
124 intptr_t* column_number) {
125 DARTSCOPE(Thread::Current());
126 CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
127 if (function_name != nullptr) {
128 *function_name = Api::NewHandle(thread: T, raw: frame->QualifiedFunctionName());
129 }
130 if (script_url != nullptr) {
131 *script_url = Api::NewHandle(thread: T, raw: frame->SourceUrl());
132 }
133 if (line_number != nullptr) {
134 *line_number = frame->LineNumber();
135 }
136 if (column_number != nullptr) {
137 *column_number = frame->ColumnNumber();
138 }
139 return Api::Success();
140}
141
142DART_EXPORT Dart_Handle Dart_SetBreakpoint(Dart_Handle script_url_in,
143 intptr_t line_number) {
144 Breakpoint* bpt;
145 {
146 DARTSCOPE(Thread::Current());
147 Isolate* I = T->isolate();
148 CHECK_DEBUGGER(I);
149 UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
150
151 Debugger* debugger = I->debugger();
152 bpt = debugger->SetBreakpointAtLineCol(script_url, line_number, column_number: -1);
153 if (bpt == nullptr) {
154 return Api::NewError("%s: could not set breakpoint at line %" Pd
155 " in '%s'",
156 CURRENT_FUNC, line_number, script_url.ToCString());
157 }
158 }
159 return Dart_NewInteger(bpt->id());
160}
161
162DART_EXPORT Dart_Handle Dart_EvaluateStaticExpr(Dart_Handle lib_handle,
163 Dart_Handle expr_in) {
164 DARTSCOPE(Thread::Current());
165 CHECK_DEBUGGER(T->isolate());
166
167 const Object& target = Object::Handle(Z, Api::UnwrapHandle(object: lib_handle));
168 if (target.IsError()) return lib_handle;
169 if (target.IsNull()) {
170 return Api::NewError(format: "%s expects argument 'target' to be non-null",
171 CURRENT_FUNC);
172 }
173 const Library& lib = Library::Cast(obj: target);
174 UNWRAP_AND_CHECK_PARAM(String, expr, expr_in);
175
176 if (!KernelIsolate::IsRunning()) {
177 UNREACHABLE();
178 } else {
179 Dart_KernelCompilationResult compilation_result =
180 KernelIsolate::CompileExpressionToKernel(
181 /* platform_kernel= */ nullptr, /* platform_kernel_size= */ 0,
182 expression: expr.ToCString(),
183 /* definitions= */ Array::empty_array(),
184 /* definition_types= */ Array::empty_array(),
185 /* type_definitions= */ Array::empty_array(),
186 /* type_bounds= */ Array::empty_array(),
187 /* type_defaults= */ Array::empty_array(),
188 library_url: String::Handle(ptr: lib.url()).ToCString(),
189 /* klass= */ nullptr,
190 /* method= */ nullptr,
191 /* is_static= */ true);
192 if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
193 return Api::NewError(format: "Failed to compile expression.");
194 }
195
196 const ExternalTypedData& kernel_buffer =
197 ExternalTypedData::Handle(ExternalTypedData::NewFinalizeWithFree(
198 data: const_cast<uint8_t*>(compilation_result.kernel),
199 len: compilation_result.kernel_size));
200
201 Dart_Handle result = Api::NewHandle(
202 thread: T,
203 raw: lib.EvaluateCompiledExpression(kernel_buffer,
204 /* type_definitions= */
205 Array::empty_array(),
206 /* param_values= */
207 Array::empty_array(),
208 /* type_param_values= */
209 TypeArguments::null_type_arguments()));
210 return result;
211 }
212}
213
214DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
215 intptr_t* library_id) {
216 DARTSCOPE(Thread::Current());
217 const Library& lib = Api::UnwrapLibraryHandle(Z, object: library);
218 if (lib.IsNull()) {
219 RETURN_TYPE_ERROR(Z, library, Library);
220 }
221 if (library_id == nullptr) {
222 RETURN_NULL_ERROR(library_id);
223 }
224 *library_id = lib.index();
225 return Api::Success();
226}
227
228DART_EXPORT Dart_Handle Dart_GetLibraryDebuggable(intptr_t library_id,
229 bool* is_debuggable) {
230 DARTSCOPE(Thread::Current());
231 CHECK_NOT_NULL(is_debuggable);
232 const Library& lib = Library::Handle(ptr: Library::GetLibrary(index: library_id));
233 if (lib.IsNull()) {
234 return Api::NewError("%s: %" Pd " is not a valid library id", CURRENT_FUNC,
235 library_id);
236 }
237 *is_debuggable = lib.IsDebuggable();
238 return Api::Success();
239}
240
241DART_EXPORT Dart_Handle Dart_SetLibraryDebuggable(intptr_t library_id,
242 bool is_debuggable) {
243 DARTSCOPE(Thread::Current());
244 const Library& lib = Library::Handle(Z, Library::GetLibrary(index: library_id));
245 if (lib.IsNull()) {
246 return Api::NewError("%s: %" Pd " is not a valid library id", CURRENT_FUNC,
247 library_id);
248 }
249 lib.set_debuggable(is_debuggable);
250 return Api::Success();
251}
252
253#endif // !PRODUCT
254
255} // namespace dart
256

source code of dart_sdk/runtime/vm/debugger_api_impl_test.cc