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 "vm/dart_api_impl.h"
6#include "bin/builtin.h"
7#include "bin/dartutils.h"
8#include "include/dart_api.h"
9#include "include/dart_native_api.h"
10#include "include/dart_tools_api.h"
11#include "platform/assert.h"
12#include "platform/text_buffer.h"
13#include "platform/utils.h"
14#include "vm/class_finalizer.h"
15#include "vm/compiler/jit/compiler.h"
16#include "vm/dart.h"
17#include "vm/dart_api_state.h"
18#include "vm/debugger_api_impl_test.h"
19#include "vm/heap/verifier.h"
20#include "vm/lockers.h"
21#include "vm/timeline.h"
22#include "vm/unit_test.h"
23
24namespace dart {
25
26DECLARE_FLAG(bool, verify_acquired_data);
27
28#ifndef PRODUCT
29
30UNIT_TEST_CASE(DartAPI_DartInitializeAfterCleanup) {
31 EXPECT(Dart_SetVMFlags(TesterState::argc, TesterState::argv) == NULL);
32 Dart_InitializeParams params;
33 memset(&params, 0, sizeof(Dart_InitializeParams));
34 params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
35 params.vm_snapshot_data = TesterState::vm_snapshot_data;
36 params.create_group = TesterState::create_callback;
37 params.shutdown_isolate = TesterState::shutdown_callback;
38 params.cleanup_group = TesterState::group_cleanup_callback;
39 params.start_kernel_isolate = true;
40
41 // Reinitialize and ensure we can execute Dart code.
42 EXPECT(Dart_Initialize(&params) == NULL);
43 {
44 TestIsolateScope scope;
45 const char* kScriptChars =
46 "int testMain() {\n"
47 " return 42;\n"
48 "}\n";
49 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
50 EXPECT_VALID(lib);
51 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
52 EXPECT_VALID(result);
53 int64_t value = 0;
54 EXPECT_VALID(Dart_IntegerToInt64(result, &value));
55 EXPECT_EQ(42, value);
56 }
57 EXPECT(Dart_Cleanup() == NULL);
58}
59
60UNIT_TEST_CASE(DartAPI_DartInitializeCallsCodeObserver) {
61 EXPECT(Dart_SetVMFlags(TesterState::argc, TesterState::argv) == NULL);
62 Dart_InitializeParams params;
63 memset(&params, 0, sizeof(Dart_InitializeParams));
64 params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
65 params.vm_snapshot_data = TesterState::vm_snapshot_data;
66 params.create_group = TesterState::create_callback;
67 params.shutdown_isolate = TesterState::shutdown_callback;
68 params.cleanup_group = TesterState::group_cleanup_callback;
69 params.start_kernel_isolate = true;
70
71 bool was_called = false;
72 Dart_CodeObserver code_observer;
73 code_observer.data = &was_called;
74 code_observer.on_new_code = [](Dart_CodeObserver* observer, const char* name,
75 uintptr_t base, uintptr_t size) {
76 *static_cast<bool*>(observer->data) = true;
77 };
78 params.code_observer = &code_observer;
79
80 // Reinitialize and ensure we can execute Dart code.
81 EXPECT(Dart_Initialize(&params) == NULL);
82
83 // Wait for 5 seconds to let the kernel service load the snapshot,
84 // which should trigger calls to the code observer.
85 OS::Sleep(5);
86
87 EXPECT(was_called);
88 EXPECT(Dart_Cleanup() == NULL);
89}
90
91TEST_CASE(Dart_KillIsolate) {
92 const char* kScriptChars =
93 "int testMain() {\n"
94 " return 42;\n"
95 "}\n";
96 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
97 EXPECT_VALID(lib);
98 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
99 EXPECT_VALID(result);
100 int64_t value = 0;
101 EXPECT_VALID(Dart_IntegerToInt64(result, &value));
102 EXPECT_EQ(42, value);
103 Dart_Isolate isolate = reinterpret_cast<Dart_Isolate>(Isolate::Current());
104 Dart_KillIsolate(isolate);
105 result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
106 EXPECT(Dart_IsError(result));
107 EXPECT_STREQ("isolate terminated by Isolate.kill", Dart_GetError(result));
108}
109
110class InfiniteLoopTask : public ThreadPool::Task {
111 public:
112 InfiniteLoopTask(Dart_Isolate* isolate, Monitor* monitor, bool* interrupted)
113 : isolate_(isolate), monitor_(monitor), interrupted_(interrupted) {}
114 virtual void Run() {
115 TestIsolateScope scope;
116 const char* kScriptChars =
117 "testMain() {\n"
118 " while(true) {};"
119 "}\n";
120 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
121 EXPECT_VALID(lib);
122 *isolate_ = reinterpret_cast<Dart_Isolate>(Isolate::Current());
123 {
124 MonitorLocker ml(monitor_);
125 ml.Notify();
126 }
127 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
128 // Test should run an inifinite loop and expect that to be killed.
129 EXPECT(Dart_IsError(result));
130 EXPECT_STREQ("isolate terminated by Isolate.kill", Dart_GetError(result));
131 {
132 MonitorLocker ml(monitor_);
133 *interrupted_ = true;
134 ml.Notify();
135 }
136 }
137
138 private:
139 Dart_Isolate* isolate_;
140 Monitor* monitor_;
141 bool* interrupted_;
142};
143
144TEST_CASE(Dart_KillIsolatePriority) {
145 Monitor monitor;
146 bool interrupted = false;
147 Dart_Isolate isolate;
148 Dart::thread_pool()->Run<InfiniteLoopTask>(&isolate, &monitor, &interrupted);
149 {
150 MonitorLocker ml(&monitor);
151 ml.Wait();
152 }
153
154 Dart_KillIsolate(isolate);
155
156 {
157 MonitorLocker ml(&monitor);
158 while (!interrupted) {
159 ml.Wait();
160 }
161 }
162 EXPECT(interrupted);
163}
164
165TEST_CASE(DartAPI_ErrorHandleBasics) {
166 const char* kScriptChars =
167 "void testMain() {\n"
168 " throw new Exception(\"bad news\");\n"
169 "}\n";
170
171 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
172
173 Dart_Handle instance = Dart_True();
174 Dart_Handle error = Api::NewError("myerror");
175 Dart_Handle exception = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
176
177 EXPECT_VALID(instance);
178 EXPECT(Dart_IsError(error));
179 EXPECT(Dart_IsError(exception));
180
181 EXPECT(!Dart_ErrorHasException(instance));
182 EXPECT(!Dart_ErrorHasException(error));
183 EXPECT(Dart_ErrorHasException(exception));
184
185 EXPECT_STREQ("", Dart_GetError(instance));
186 EXPECT_STREQ("myerror", Dart_GetError(error));
187 EXPECT_STREQ(ZONE_STR("Unhandled exception:\n"
188 "Exception: bad news\n"
189 "#0 testMain (%s:2:3)",
190 TestCase::url()),
191 Dart_GetError(exception));
192
193 EXPECT(Dart_IsError(Dart_ErrorGetException(instance)));
194 EXPECT(Dart_IsError(Dart_ErrorGetException(error)));
195 EXPECT_VALID(Dart_ErrorGetException(exception));
196 EXPECT(Dart_IsError(Dart_ErrorGetStackTrace(instance)));
197 EXPECT(Dart_IsError(Dart_ErrorGetStackTrace(error)));
198 EXPECT_VALID(Dart_ErrorGetStackTrace(exception));
199}
200
201TEST_CASE(DartAPI_StackTraceInfo) {
202 const char* kScriptChars =
203 "bar() => throw new Error();\n"
204 "foo() => bar();\n"
205 "testMain() => foo();\n";
206
207 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
208 Dart_Handle error = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
209
210 EXPECT(Dart_IsError(error));
211
212 Dart_StackTrace stacktrace;
213 Dart_Handle result = Dart_GetStackTraceFromError(error, &stacktrace);
214 EXPECT_VALID(result);
215
216 intptr_t frame_count = 0;
217 result = Dart_StackTraceLength(stacktrace, &frame_count);
218 EXPECT_VALID(result);
219 EXPECT_EQ(3, frame_count);
220
221 Dart_Handle function_name;
222 Dart_Handle script_url;
223 intptr_t line_number = 0;
224 intptr_t column_number = 0;
225 const char* cstr = "";
226
227 Dart_ActivationFrame frame;
228 result = Dart_GetActivationFrame(stacktrace, 0, &frame);
229 EXPECT_VALID(result);
230 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
231 &line_number, &column_number);
232 EXPECT_VALID(result);
233 Dart_StringToCString(function_name, &cstr);
234 EXPECT_STREQ("bar", cstr);
235 Dart_StringToCString(script_url, &cstr);
236 EXPECT_SUBSTRING("test-lib", cstr);
237 EXPECT_EQ(1, line_number);
238 EXPECT_EQ(10, column_number);
239
240 result = Dart_GetActivationFrame(stacktrace, 1, &frame);
241 EXPECT_VALID(result);
242 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
243 &line_number, &column_number);
244 EXPECT_VALID(result);
245 Dart_StringToCString(function_name, &cstr);
246 EXPECT_STREQ("foo", cstr);
247 Dart_StringToCString(script_url, &cstr);
248 EXPECT_SUBSTRING("test-lib", cstr);
249 EXPECT_EQ(2, line_number);
250 EXPECT_EQ(10, column_number);
251
252 result = Dart_GetActivationFrame(stacktrace, 2, &frame);
253 EXPECT_VALID(result);
254 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
255 &line_number, &column_number);
256 EXPECT_VALID(result);
257 Dart_StringToCString(function_name, &cstr);
258 EXPECT_STREQ("testMain", cstr);
259 Dart_StringToCString(script_url, &cstr);
260 EXPECT_SUBSTRING("test-lib", cstr);
261 EXPECT_EQ(3, line_number);
262 EXPECT_EQ(15, column_number);
263
264 // Out-of-bounds frames.
265 result = Dart_GetActivationFrame(stacktrace, frame_count, &frame);
266 EXPECT(Dart_IsError(result));
267 result = Dart_GetActivationFrame(stacktrace, -1, &frame);
268 EXPECT(Dart_IsError(result));
269}
270
271TEST_CASE(DartAPI_DeepStackTraceInfo) {
272 const char* kScriptChars =
273 "foo(n) => n == 1 ? throw new Error() : foo(n-1);\n"
274 "testMain() => foo(100);\n";
275
276 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
277 Dart_Handle error = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
278
279 EXPECT(Dart_IsError(error));
280
281 Dart_StackTrace stacktrace;
282 Dart_Handle result = Dart_GetStackTraceFromError(error, &stacktrace);
283 EXPECT_VALID(result);
284
285 intptr_t frame_count = 0;
286 result = Dart_StackTraceLength(stacktrace, &frame_count);
287 EXPECT_VALID(result);
288 EXPECT_EQ(101, frame_count);
289 // Test something bigger than the preallocated size to verify nothing was
290 // truncated.
291 EXPECT(101 > StackTrace::kPreallocatedStackdepth);
292
293 Dart_Handle function_name;
294 Dart_Handle script_url;
295 intptr_t line_number = 0;
296 intptr_t column_number = 0;
297 const char* cstr = "";
298
299 // Top frame at positioned at throw.
300 Dart_ActivationFrame frame;
301 result = Dart_GetActivationFrame(stacktrace, 0, &frame);
302 EXPECT_VALID(result);
303 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
304 &line_number, &column_number);
305 EXPECT_VALID(result);
306 Dart_StringToCString(function_name, &cstr);
307 EXPECT_STREQ("foo", cstr);
308 Dart_StringToCString(script_url, &cstr);
309 EXPECT_SUBSTRING("test-lib", cstr);
310 EXPECT_EQ(1, line_number);
311 EXPECT_EQ(20, column_number);
312
313 // Middle frames positioned at the recursive call.
314 for (intptr_t frame_index = 1; frame_index < (frame_count - 1);
315 frame_index++) {
316 result = Dart_GetActivationFrame(stacktrace, frame_index, &frame);
317 EXPECT_VALID(result);
318 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
319 &line_number, &column_number);
320 EXPECT_VALID(result);
321 Dart_StringToCString(function_name, &cstr);
322 EXPECT_STREQ("foo", cstr);
323 Dart_StringToCString(script_url, &cstr);
324 EXPECT_SUBSTRING("test-lib", cstr);
325 EXPECT_EQ(1, line_number);
326 EXPECT_EQ(40, column_number);
327 }
328
329 // Bottom frame positioned at testMain().
330 result = Dart_GetActivationFrame(stacktrace, frame_count - 1, &frame);
331 EXPECT_VALID(result);
332 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
333 &line_number, &column_number);
334 EXPECT_VALID(result);
335 Dart_StringToCString(function_name, &cstr);
336 EXPECT_STREQ("testMain", cstr);
337 Dart_StringToCString(script_url, &cstr);
338 EXPECT_SUBSTRING("test-lib", cstr);
339 EXPECT_EQ(2, line_number);
340 EXPECT_EQ(15, column_number);
341
342 // Out-of-bounds frames.
343 result = Dart_GetActivationFrame(stacktrace, frame_count, &frame);
344 EXPECT(Dart_IsError(result));
345 result = Dart_GetActivationFrame(stacktrace, -1, &frame);
346 EXPECT(Dart_IsError(result));
347}
348
349void VerifyStackOverflowStackTraceInfo(const char* script,
350 const char* top_frame_func_name,
351 const char* entry_func_name,
352 int expected_line_number,
353 int expected_column_number) {
354 Dart_Handle lib = TestCase::LoadTestScript(script, NULL);
355 Dart_Handle error = Dart_Invoke(lib, NewString(entry_func_name), 0, NULL);
356
357 EXPECT(Dart_IsError(error));
358
359 Dart_StackTrace stacktrace;
360 Dart_Handle result = Dart_GetStackTraceFromError(error, &stacktrace);
361 EXPECT_VALID(result);
362
363 intptr_t frame_count = 0;
364 result = Dart_StackTraceLength(stacktrace, &frame_count);
365 EXPECT_VALID(result);
366 EXPECT_EQ(StackTrace::kPreallocatedStackdepth - 1, frame_count);
367
368 Dart_Handle function_name;
369 Dart_Handle script_url;
370 intptr_t line_number = 0;
371 intptr_t column_number = 0;
372 const char* cstr = "";
373
374 // Top frame at recursive call.
375 Dart_ActivationFrame frame;
376 result = Dart_GetActivationFrame(stacktrace, 0, &frame);
377 EXPECT_VALID(result);
378 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
379 &line_number, &column_number);
380 EXPECT_VALID(result);
381 Dart_StringToCString(function_name, &cstr);
382 EXPECT_STREQ(top_frame_func_name, cstr);
383 Dart_StringToCString(script_url, &cstr);
384 EXPECT_STREQ(TestCase::url(), cstr);
385 EXPECT_EQ(expected_line_number, line_number);
386 EXPECT_EQ(expected_column_number, column_number);
387
388 // Out-of-bounds frames.
389 result = Dart_GetActivationFrame(stacktrace, frame_count, &frame);
390 EXPECT(Dart_IsError(result));
391 result = Dart_GetActivationFrame(stacktrace, -1, &frame);
392 EXPECT(Dart_IsError(result));
393}
394
395TEST_CASE(DartAPI_StackOverflowStackTraceInfoBraceFunction1) {
396 int line = 2;
397 int col = 3;
398 VerifyStackOverflowStackTraceInfo(
399 "class C {\n"
400 " static foo(int i) { foo(i); }\n"
401 "}\n"
402 "testMain() => C.foo(10);\n",
403 "C.foo", "testMain", line, col);
404}
405
406TEST_CASE(DartAPI_StackOverflowStackTraceInfoBraceFunction2) {
407 int line = 2;
408 int col = 3;
409 VerifyStackOverflowStackTraceInfo(
410 "class C {\n"
411 " static foo(int i, int j) {\n"
412 " foo(i, j);\n"
413 " }\n"
414 "}\n"
415 "testMain() => C.foo(10, 11);\n",
416 "C.foo", "testMain", line, col);
417}
418
419TEST_CASE(DartAPI_StackOverflowStackTraceInfoArrowFunction) {
420 int line = 2;
421 int col = 3;
422 VerifyStackOverflowStackTraceInfo(
423 "class C {\n"
424 " static foo(int i) => foo(i);\n"
425 "}\n"
426 "testMain() => C.foo(10);\n",
427 "C.foo", "testMain", line, col);
428}
429
430TEST_CASE(DartAPI_OutOfMemoryStackTraceInfo) {
431 const char* kScriptChars =
432 "var number_of_ints = 134000000;\n"
433 "testMain() {\n"
434 " new List<int>(number_of_ints)\n"
435 "}\n";
436
437 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
438 Dart_Handle error = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
439
440 EXPECT(Dart_IsError(error));
441
442 Dart_StackTrace stacktrace;
443 Dart_Handle result = Dart_GetStackTraceFromError(error, &stacktrace);
444 EXPECT(Dart_IsError(result)); // No StackTrace for OutOfMemory.
445}
446
447void CurrentStackTraceNative(Dart_NativeArguments args) {
448 Dart_EnterScope();
449
450 Dart_StackTrace stacktrace;
451 Dart_Handle result = Dart_GetStackTrace(&stacktrace);
452 EXPECT_VALID(result);
453
454 intptr_t frame_count = 0;
455 result = Dart_StackTraceLength(stacktrace, &frame_count);
456 EXPECT_VALID(result);
457 EXPECT_EQ(102, frame_count);
458 // Test something bigger than the preallocated size to verify nothing was
459 // truncated.
460 EXPECT(102 > StackTrace::kPreallocatedStackdepth);
461
462 Dart_Handle function_name;
463 Dart_Handle script_url;
464 intptr_t line_number = 0;
465 intptr_t column_number = 0;
466 const char* cstr = "";
467 const char* test_lib = "file:///test-lib";
468
469 // Top frame is inspectStack().
470 Dart_ActivationFrame frame;
471 result = Dart_GetActivationFrame(stacktrace, 0, &frame);
472 EXPECT_VALID(result);
473 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
474 &line_number, &column_number);
475 EXPECT_VALID(result);
476 Dart_StringToCString(function_name, &cstr);
477 EXPECT_STREQ("inspectStack", cstr);
478 Dart_StringToCString(script_url, &cstr);
479 EXPECT_STREQ(test_lib, cstr);
480 EXPECT_EQ(1, line_number);
481 EXPECT_EQ(47, column_number);
482
483 // Second frame is foo() positioned at call to inspectStack().
484 result = Dart_GetActivationFrame(stacktrace, 1, &frame);
485 EXPECT_VALID(result);
486 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
487 &line_number, &column_number);
488 EXPECT_VALID(result);
489 Dart_StringToCString(function_name, &cstr);
490 EXPECT_STREQ("foo", cstr);
491 Dart_StringToCString(script_url, &cstr);
492 EXPECT_STREQ(test_lib, cstr);
493 EXPECT_EQ(2, line_number);
494 EXPECT_EQ(20, column_number);
495
496 // Middle frames positioned at the recursive call.
497 for (intptr_t frame_index = 2; frame_index < (frame_count - 1);
498 frame_index++) {
499 result = Dart_GetActivationFrame(stacktrace, frame_index, &frame);
500 EXPECT_VALID(result);
501 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
502 &line_number, &column_number);
503 EXPECT_VALID(result);
504 Dart_StringToCString(function_name, &cstr);
505 EXPECT_STREQ("foo", cstr);
506 Dart_StringToCString(script_url, &cstr);
507 EXPECT_STREQ(test_lib, cstr);
508 EXPECT_EQ(2, line_number);
509 EXPECT_EQ(37, column_number);
510 }
511
512 // Bottom frame positioned at testMain().
513 result = Dart_GetActivationFrame(stacktrace, frame_count - 1, &frame);
514 EXPECT_VALID(result);
515 result = Dart_ActivationFrameInfo(frame, &function_name, &script_url,
516 &line_number, &column_number);
517 EXPECT_VALID(result);
518 Dart_StringToCString(function_name, &cstr);
519 EXPECT_STREQ("testMain", cstr);
520 Dart_StringToCString(script_url, &cstr);
521 EXPECT_STREQ(test_lib, cstr);
522 EXPECT_EQ(3, line_number);
523 EXPECT_EQ(15, column_number);
524
525 // Out-of-bounds frames.
526 result = Dart_GetActivationFrame(stacktrace, frame_count, &frame);
527 EXPECT(Dart_IsError(result));
528 result = Dart_GetActivationFrame(stacktrace, -1, &frame);
529 EXPECT(Dart_IsError(result));
530
531 Dart_SetReturnValue(args, Dart_NewInteger(42));
532 Dart_ExitScope();
533}
534
535static Dart_NativeFunction CurrentStackTraceNativeLookup(
536 Dart_Handle name,
537 int argument_count,
538 bool* auto_setup_scope) {
539 ASSERT(auto_setup_scope != NULL);
540 *auto_setup_scope = true;
541 return reinterpret_cast<Dart_NativeFunction>(&CurrentStackTraceNative);
542}
543
544TEST_CASE(DartAPI_CurrentStackTraceInfo) {
545 const char* kScriptChars =
546 "inspectStack() native 'CurrentStackTraceNatve';\n"
547 "foo(n) => n == 1 ? inspectStack() : foo(n-1);\n"
548 "testMain() => foo(100);\n";
549
550 Dart_Handle lib =
551 TestCase::LoadTestScript(kScriptChars, &CurrentStackTraceNativeLookup);
552 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
553 EXPECT_VALID(result);
554 EXPECT(Dart_IsInteger(result));
555 int64_t value = 0;
556 EXPECT_VALID(Dart_IntegerToInt64(result, &value));
557 EXPECT_EQ(42, value);
558}
559
560#endif // !PRODUCT
561
562TEST_CASE(DartAPI_ErrorHandleTypes) {
563 Dart_Handle not_error = NewString("NotError");
564 Dart_Handle api_error = Dart_NewApiError("ApiError");
565 Dart_Handle exception_error =
566 Dart_NewUnhandledExceptionError(NewString("ExceptionError"));
567 Dart_Handle compile_error = Dart_NewCompilationError("CompileError");
568 Dart_Handle fatal_error;
569 {
570 TransitionNativeToVM transition(thread);
571 const String& fatal_message = String::Handle(String::New("FatalError"));
572 fatal_error = Api::NewHandle(thread, UnwindError::New(fatal_message));
573 }
574
575 EXPECT_VALID(not_error);
576 EXPECT(Dart_IsError(api_error));
577 EXPECT(Dart_IsError(exception_error));
578 EXPECT(Dart_IsError(compile_error));
579 EXPECT(Dart_IsError(fatal_error));
580
581 EXPECT(!Dart_IsApiError(not_error));
582 EXPECT(Dart_IsApiError(api_error));
583 EXPECT(!Dart_IsApiError(exception_error));
584 EXPECT(!Dart_IsApiError(compile_error));
585 EXPECT(!Dart_IsApiError(fatal_error));
586
587 EXPECT(!Dart_IsUnhandledExceptionError(not_error));
588 EXPECT(!Dart_IsUnhandledExceptionError(api_error));
589 EXPECT(Dart_IsUnhandledExceptionError(exception_error));
590 EXPECT(!Dart_IsUnhandledExceptionError(compile_error));
591 EXPECT(!Dart_IsUnhandledExceptionError(fatal_error));
592
593 EXPECT(!Dart_IsCompilationError(not_error));
594 EXPECT(!Dart_IsCompilationError(api_error));
595 EXPECT(!Dart_IsCompilationError(exception_error));
596 EXPECT(Dart_IsCompilationError(compile_error));
597 EXPECT(!Dart_IsCompilationError(fatal_error));
598
599 EXPECT(!Dart_IsFatalError(not_error));
600 EXPECT(!Dart_IsFatalError(api_error));
601 EXPECT(!Dart_IsFatalError(exception_error));
602 EXPECT(!Dart_IsFatalError(compile_error));
603 EXPECT(Dart_IsFatalError(fatal_error));
604
605 EXPECT_STREQ("", Dart_GetError(not_error));
606 EXPECT_STREQ("ApiError", Dart_GetError(api_error));
607 EXPECT_SUBSTRING("Unhandled exception:\nExceptionError",
608 Dart_GetError(exception_error));
609 EXPECT_STREQ("CompileError", Dart_GetError(compile_error));
610 EXPECT_STREQ("FatalError", Dart_GetError(fatal_error));
611}
612
613TEST_CASE(DartAPI_UnhandleExceptionError) {
614 const char* exception_cstr = "";
615
616 // Test with an API Error.
617 const char* kApiError = "Api Error Exception Test.";
618 Dart_Handle api_error = Dart_NewApiError(kApiError);
619 Dart_Handle exception_error = Dart_NewUnhandledExceptionError(api_error);
620 EXPECT(!Dart_IsApiError(exception_error));
621 EXPECT(Dart_IsUnhandledExceptionError(exception_error));
622 EXPECT(Dart_IsString(Dart_ErrorGetException(exception_error)));
623 EXPECT_VALID(Dart_StringToCString(Dart_ErrorGetException(exception_error),
624 &exception_cstr));
625 EXPECT_STREQ(kApiError, exception_cstr);
626
627 // Test with a Compilation Error.
628 const char* kCompileError = "CompileError Exception Test.";
629 Dart_Handle compile_error = Dart_NewCompilationError(kCompileError);
630 exception_error = Dart_NewUnhandledExceptionError(compile_error);
631 EXPECT(!Dart_IsApiError(exception_error));
632 EXPECT(Dart_IsUnhandledExceptionError(exception_error));
633 EXPECT(Dart_IsString(Dart_ErrorGetException(exception_error)));
634 EXPECT_VALID(Dart_StringToCString(Dart_ErrorGetException(exception_error),
635 &exception_cstr));
636 EXPECT_STREQ(kCompileError, exception_cstr);
637
638 // Test with a Fatal Error.
639 Dart_Handle fatal_error;
640 {
641 TransitionNativeToVM transition(thread);
642 const String& fatal_message =
643 String::Handle(String::New("FatalError Exception Test."));
644 fatal_error = Api::NewHandle(thread, UnwindError::New(fatal_message));
645 }
646 exception_error = Dart_NewUnhandledExceptionError(fatal_error);
647 EXPECT(Dart_IsError(exception_error));
648 EXPECT(!Dart_IsUnhandledExceptionError(exception_error));
649
650 // Test with a Regular object.
651 const char* kRegularString = "Regular String Exception Test.";
652 exception_error = Dart_NewUnhandledExceptionError(NewString(kRegularString));
653 EXPECT(!Dart_IsApiError(exception_error));
654 EXPECT(Dart_IsUnhandledExceptionError(exception_error));
655 EXPECT(Dart_IsString(Dart_ErrorGetException(exception_error)));
656 EXPECT_VALID(Dart_StringToCString(Dart_ErrorGetException(exception_error),
657 &exception_cstr));
658 EXPECT_STREQ(kRegularString, exception_cstr);
659}
660
661// Should we propagate the error via Dart_SetReturnValue?
662static bool use_set_return = false;
663
664// Should we propagate the error via Dart_ThrowException?
665static bool use_throw_exception = false;
666
667void PropagateErrorNative(Dart_NativeArguments args) {
668 Dart_Handle closure = Dart_GetNativeArgument(args, 0);
669 EXPECT(Dart_IsClosure(closure));
670 Dart_Handle result = Dart_InvokeClosure(closure, 0, NULL);
671 EXPECT(Dart_IsError(result));
672 if (use_set_return) {
673 Dart_SetReturnValue(args, result);
674 } else if (use_throw_exception) {
675 result = Dart_ThrowException(result);
676 EXPECT_VALID(result); // We do not expect to reach here.
677 UNREACHABLE();
678 } else {
679 Dart_PropagateError(result);
680 UNREACHABLE();
681 }
682}
683
684static Dart_NativeFunction PropagateError_native_lookup(
685 Dart_Handle name,
686 int argument_count,
687 bool* auto_setup_scope) {
688 ASSERT(auto_setup_scope != NULL);
689 *auto_setup_scope = true;
690 return reinterpret_cast<Dart_NativeFunction>(&PropagateErrorNative);
691}
692
693TEST_CASE(DartAPI_PropagateCompileTimeError) {
694 const char* kScriptChars =
695 "raiseCompileError() {\n"
696 " return missing_semicolon\n"
697 "}\n"
698 "\n"
699 "void nativeFunc(closure) native 'Test_nativeFunc';\n"
700 "\n"
701 "void Func1() {\n"
702 " nativeFunc(() => raiseCompileError());\n"
703 "}\n";
704 Dart_Handle lib =
705 TestCase::LoadTestScript(kScriptChars, &PropagateError_native_lookup);
706 Dart_Handle result;
707
708 // Use Dart_PropagateError to propagate the error.
709 use_throw_exception = false;
710 use_set_return = false;
711
712 result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
713 EXPECT(Dart_IsError(result));
714
715 EXPECT_SUBSTRING("Expected ';' after this.", Dart_GetError(result));
716
717 // Use Dart_SetReturnValue to propagate the error.
718 use_throw_exception = false;
719 use_set_return = true;
720
721 result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
722 EXPECT(Dart_IsError(result));
723 EXPECT_SUBSTRING("Expected ';' after this.", Dart_GetError(result));
724
725 // Use Dart_ThrowException to propagate the error.
726 use_throw_exception = true;
727 use_set_return = false;
728
729 result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
730 EXPECT(Dart_IsError(result));
731 EXPECT_SUBSTRING("Expected ';' after this.", Dart_GetError(result));
732}
733
734TEST_CASE(DartAPI_PropagateError) {
735 const char* kScriptChars =
736 "void throwException() {\n"
737 " throw new Exception('myException');\n"
738 "}\n"
739 "\n"
740 "void nativeFunc(closure) native 'Test_nativeFunc';\n"
741 "\n"
742 "void Func2() {\n"
743 " nativeFunc(() => throwException());\n"
744 "}\n";
745 Dart_Handle lib =
746 TestCase::LoadTestScript(kScriptChars, &PropagateError_native_lookup);
747 Dart_Handle result;
748
749 // Use Dart_PropagateError to propagate the error.
750 use_throw_exception = false;
751 use_set_return = false;
752
753 result = Dart_Invoke(lib, NewString("Func2"), 0, NULL);
754 EXPECT(Dart_IsError(result));
755 EXPECT(Dart_ErrorHasException(result));
756 EXPECT_SUBSTRING("myException", Dart_GetError(result));
757
758 // Use Dart_SetReturnValue to propagate the error.
759 use_throw_exception = false;
760 use_set_return = true;
761
762 result = Dart_Invoke(lib, NewString("Func2"), 0, NULL);
763 EXPECT(Dart_IsError(result));
764 EXPECT(Dart_ErrorHasException(result));
765 EXPECT_SUBSTRING("myException", Dart_GetError(result));
766
767 // Use Dart_ThrowException to propagate the error.
768 use_throw_exception = true;
769 use_set_return = false;
770
771 result = Dart_Invoke(lib, NewString("Func2"), 0, NULL);
772 EXPECT(Dart_IsError(result));
773 EXPECT(Dart_ErrorHasException(result));
774 EXPECT_SUBSTRING("myException", Dart_GetError(result));
775}
776
777TEST_CASE(DartAPI_Error) {
778 Dart_Handle error;
779 {
780 TransitionNativeToVM transition(thread);
781 error = Api::NewError("An %s", "error");
782 }
783 EXPECT(Dart_IsError(error));
784 EXPECT_STREQ("An error", Dart_GetError(error));
785}
786
787TEST_CASE(DartAPI_Null) {
788 Dart_Handle null = Dart_Null();
789 EXPECT_VALID(null);
790 EXPECT(Dart_IsNull(null));
791
792 Dart_Handle str = NewString("test");
793 EXPECT_VALID(str);
794 EXPECT(!Dart_IsNull(str));
795}
796
797TEST_CASE(DartAPI_EmptyString) {
798 Dart_Handle empty = Dart_EmptyString();
799 EXPECT_VALID(empty);
800 EXPECT(!Dart_IsNull(empty));
801 EXPECT(Dart_IsString(empty));
802 intptr_t length = -1;
803 EXPECT_VALID(Dart_StringLength(empty, &length));
804 EXPECT_EQ(0, length);
805}
806
807TEST_CASE(DartAPI_TypeDynamic) {
808 Dart_Handle type = Dart_TypeDynamic();
809 EXPECT_VALID(type);
810 EXPECT(Dart_IsType(type));
811
812 Dart_Handle str = Dart_ToString(type);
813 EXPECT_VALID(str);
814 const char* cstr = nullptr;
815 EXPECT_VALID(Dart_StringToCString(str, &cstr));
816 EXPECT_STREQ("dynamic", cstr);
817}
818
819TEST_CASE(DartAPI_TypeVoid) {
820 Dart_Handle type = Dart_TypeVoid();
821 EXPECT_VALID(type);
822 EXPECT(Dart_IsType(type));
823
824 Dart_Handle str = Dart_ToString(type);
825 EXPECT_VALID(str);
826 const char* cstr = nullptr;
827 EXPECT_VALID(Dart_StringToCString(str, &cstr));
828 EXPECT_STREQ("void", cstr);
829}
830
831TEST_CASE(DartAPI_TypeNever) {
832 Dart_Handle type = Dart_TypeNever();
833 EXPECT_VALID(type);
834 EXPECT(Dart_IsType(type));
835
836 Dart_Handle str = Dart_ToString(type);
837 EXPECT_VALID(str);
838 const char* cstr = nullptr;
839 EXPECT_VALID(Dart_StringToCString(str, &cstr));
840 EXPECT_STREQ("Never", cstr);
841}
842
843TEST_CASE(DartAPI_IdentityEquals) {
844 Dart_Handle five = Dart_NewInteger(5);
845 Dart_Handle five_again = Dart_NewInteger(5);
846 Dart_Handle mint = Dart_NewInteger(0xFFFFFFFF);
847 Dart_Handle mint_again = Dart_NewInteger(0xFFFFFFFF);
848 Dart_Handle abc = NewString("abc");
849 Dart_Handle abc_again = NewString("abc");
850 Dart_Handle xyz = NewString("xyz");
851 Dart_Handle dart_core = NewString("dart:core");
852 Dart_Handle dart_mirrors = NewString("dart:mirrors");
853
854 // Same objects.
855 EXPECT(Dart_IdentityEquals(five, five));
856 EXPECT(Dart_IdentityEquals(mint, mint));
857 EXPECT(Dart_IdentityEquals(abc, abc));
858 EXPECT(Dart_IdentityEquals(xyz, xyz));
859
860 // Equal objects with special spec rules.
861 EXPECT(Dart_IdentityEquals(five, five_again));
862 EXPECT(Dart_IdentityEquals(mint, mint_again));
863
864 // Equal objects without special spec rules.
865 EXPECT(!Dart_IdentityEquals(abc, abc_again));
866
867 // Different objects.
868 EXPECT(!Dart_IdentityEquals(five, mint));
869 EXPECT(!Dart_IdentityEquals(abc, xyz));
870
871 // Case where identical() is not the same as pointer equality.
872 Dart_Handle nan1 = Dart_NewDouble(NAN);
873 Dart_Handle nan2 = Dart_NewDouble(NAN);
874 EXPECT(Dart_IdentityEquals(nan1, nan2));
875
876 // Non-instance objects.
877 {
878 CHECK_API_SCOPE(thread);
879 Dart_Handle lib1 = Dart_LookupLibrary(dart_core);
880 Dart_Handle lib2 = Dart_LookupLibrary(dart_mirrors);
881
882 EXPECT(Dart_IdentityEquals(lib1, lib1));
883 EXPECT(Dart_IdentityEquals(lib2, lib2));
884 EXPECT(!Dart_IdentityEquals(lib1, lib2));
885
886 // Mix instance and non-instance.
887 EXPECT(!Dart_IdentityEquals(lib1, nan1));
888 EXPECT(!Dart_IdentityEquals(nan1, lib1));
889 }
890}
891
892TEST_CASE(DartAPI_ObjectEquals) {
893 bool equal = false;
894 Dart_Handle five = NewString("5");
895 Dart_Handle five_again = NewString("5");
896 Dart_Handle seven = NewString("7");
897
898 // Same objects.
899 EXPECT_VALID(Dart_ObjectEquals(five, five, &equal));
900 EXPECT(equal);
901
902 // Equal objects.
903 EXPECT_VALID(Dart_ObjectEquals(five, five_again, &equal));
904 EXPECT(equal);
905
906 // Different objects.
907 EXPECT_VALID(Dart_ObjectEquals(five, seven, &equal));
908 EXPECT(!equal);
909
910 // Case where identity is not equality.
911 Dart_Handle nan = Dart_NewDouble(NAN);
912 EXPECT_VALID(Dart_ObjectEquals(nan, nan, &equal));
913 EXPECT(!equal);
914}
915
916TEST_CASE(DartAPI_InstanceValues) {
917 EXPECT(Dart_IsInstance(NewString("test")));
918 EXPECT(Dart_IsInstance(Dart_True()));
919
920 // By convention, our Is*() functions exclude null.
921 EXPECT(!Dart_IsInstance(Dart_Null()));
922}
923
924TEST_CASE(DartAPI_InstanceGetType) {
925 Zone* zone = thread->zone();
926 // Get the handle from a valid instance handle.
927 Dart_Handle type = Dart_InstanceGetType(Dart_Null());
928 EXPECT_VALID(type);
929 EXPECT(Dart_IsType(type));
930 {
931 TransitionNativeToVM transition(thread);
932 const Type& null_type_obj = Api::UnwrapTypeHandle(zone, type);
933 EXPECT(null_type_obj.raw() == Type::NullType());
934 }
935
936 Dart_Handle instance = Dart_True();
937 type = Dart_InstanceGetType(instance);
938 EXPECT_VALID(type);
939 EXPECT(Dart_IsType(type));
940 {
941 TransitionNativeToVM transition(thread);
942 const Type& bool_type_obj = Api::UnwrapTypeHandle(zone, type);
943 EXPECT(bool_type_obj.raw() == Type::BoolType());
944 }
945
946 // Errors propagate.
947 Dart_Handle error = Dart_NewApiError("MyError");
948 Dart_Handle error_type = Dart_InstanceGetType(error);
949 EXPECT_ERROR(error_type, "MyError");
950
951 // Get the handle from a non-instance handle.
952 Dart_Handle dart_core = NewString("dart:core");
953 Dart_Handle obj = Dart_LookupLibrary(dart_core);
954 Dart_Handle type_type = Dart_InstanceGetType(obj);
955 EXPECT_ERROR(type_type,
956 "Dart_InstanceGetType expects argument 'instance' to be of "
957 "type Instance.");
958}
959
960TEST_CASE(DartAPI_FunctionName) {
961 const char* kScriptChars = "int getInt() { return 1; }\n";
962 // Create a test library and Load up a test script in it.
963 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
964 EXPECT_VALID(lib);
965
966 Dart_Handle closure = Dart_GetField(lib, NewString("getInt"));
967 EXPECT_VALID(closure);
968 if (Dart_IsClosure(closure)) {
969 closure = Dart_ClosureFunction(closure);
970 EXPECT_VALID(closure);
971 }
972
973 Dart_Handle name = Dart_FunctionName(closure);
974 EXPECT_VALID(name);
975 const char* result_str = "";
976 Dart_StringToCString(name, &result_str);
977 EXPECT_STREQ(result_str, "getInt");
978}
979
980TEST_CASE(DartAPI_FunctionOwner) {
981 const char* kScriptChars = "int getInt() { return 1; }\n";
982 // Create a test library and Load up a test script in it.
983 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
984 EXPECT_VALID(lib);
985
986 Dart_Handle closure = Dart_GetField(lib, NewString("getInt"));
987 EXPECT_VALID(closure);
988 if (Dart_IsClosure(closure)) {
989 closure = Dart_ClosureFunction(closure);
990 EXPECT_VALID(closure);
991 }
992
993 const char* url = "";
994 Dart_Handle owner = Dart_FunctionOwner(closure);
995 EXPECT_VALID(owner);
996 Dart_Handle owner_url = Dart_LibraryUrl(owner);
997 EXPECT_VALID(owner_url);
998 Dart_StringToCString(owner_url, &url);
999
1000 const char* lib_url = "";
1001 Dart_Handle library_url = Dart_LibraryUrl(lib);
1002 EXPECT_VALID(library_url);
1003 Dart_StringToCString(library_url, &lib_url);
1004
1005 EXPECT_STREQ(url, lib_url);
1006}
1007
1008TEST_CASE(DartAPI_IsTearOff) {
1009 const char* kScriptChars =
1010 "int getInt() { return 1; }\n"
1011 "getTearOff() => getInt;\n"
1012 "Function foo = () { print('baz'); };\n"
1013 "class Baz {\n"
1014 " static int foo() => 42;\n"
1015 " getTearOff() => bar;\n"
1016 " int bar() => 24;\n"
1017 "}\n"
1018 "Baz getBaz() => Baz();\n";
1019 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
1020 EXPECT_VALID(lib);
1021
1022 // Check tear-off of top-level static method.
1023 Dart_Handle get_tear_off = Dart_GetField(lib, NewString("getTearOff"));
1024 EXPECT_VALID(get_tear_off);
1025 EXPECT(Dart_IsTearOff(get_tear_off));
1026 Dart_Handle tear_off = Dart_InvokeClosure(get_tear_off, 0, NULL);
1027 EXPECT_VALID(tear_off);
1028 EXPECT(Dart_IsTearOff(tear_off));
1029
1030 // Check anonymous closures are not considered tear-offs.
1031 Dart_Handle anonymous_closure = Dart_GetField(lib, NewString("foo"));
1032 EXPECT_VALID(anonymous_closure);
1033 EXPECT(!Dart_IsTearOff(anonymous_closure));
1034
1035 Dart_Handle baz_cls = Dart_GetClass(lib, NewString("Baz"));
1036 EXPECT_VALID(baz_cls);
1037
1038 // Check tear-off for a static method in a class.
1039 Dart_Handle closure =
1040 Dart_GetStaticMethodClosure(lib, baz_cls, NewString("foo"));
1041 EXPECT_VALID(closure);
1042 EXPECT(Dart_IsTearOff(closure));
1043
1044 // Flutter will use Dart_IsTearOff in conjunction with Dart_ClosureFunction
1045 // and Dart_FunctionIsStatic to prevent anonymous closures from being used to
1046 // generate callback handles. We'll test that case here, just to be sure.
1047 Dart_Handle function = Dart_ClosureFunction(closure);
1048 EXPECT_VALID(function);
1049 bool is_static = false;
1050 Dart_Handle result = Dart_FunctionIsStatic(function, &is_static);
1051 EXPECT_VALID(result);
1052 EXPECT(is_static);
1053
1054 // Check tear-off for an instance method in a class.
1055 Dart_Handle instance = Dart_Invoke(lib, NewString("getBaz"), 0, NULL);
1056 EXPECT_VALID(instance);
1057 closure = Dart_Invoke(instance, NewString("getTearOff"), 0, NULL);
1058 EXPECT_VALID(closure);
1059 EXPECT(Dart_IsTearOff(closure));
1060}
1061
1062TEST_CASE(DartAPI_FunctionIsStatic) {
1063 const char* kScriptChars =
1064 "int getInt() { return 1; }\n"
1065 "class Foo { String getString() => 'foobar'; }\n";
1066 // Create a test library and Load up a test script in it.
1067 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
1068 EXPECT_VALID(lib);
1069
1070 Dart_Handle closure = Dart_GetField(lib, NewString("getInt"));
1071 EXPECT_VALID(closure);
1072 if (Dart_IsClosure(closure)) {
1073 closure = Dart_ClosureFunction(closure);
1074 EXPECT_VALID(closure);
1075 }
1076
1077 bool is_static = false;
1078 Dart_Handle result = Dart_FunctionIsStatic(closure, &is_static);
1079 EXPECT_VALID(result);
1080 EXPECT(is_static);
1081
1082 Dart_Handle klass = Dart_GetNonNullableType(lib, NewString("Foo"), 0, NULL);
1083 EXPECT_VALID(klass);
1084
1085 Dart_Handle instance = Dart_Allocate(klass);
1086
1087 closure = Dart_GetField(instance, NewString("getString"));
1088 EXPECT_VALID(closure);
1089 if (Dart_IsClosure(closure)) {
1090 closure = Dart_ClosureFunction(closure);
1091 EXPECT_VALID(closure);
1092 }
1093
1094 result = Dart_FunctionIsStatic(closure, &is_static);
1095 EXPECT_VALID(result);
1096 EXPECT(!is_static);
1097}
1098
1099TEST_CASE(DartAPI_ClosureFunction) {
1100 const char* kScriptChars = "int getInt() { return 1; }\n";
1101 // Create a test library and Load up a test script in it.
1102 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
1103 EXPECT_VALID(lib);
1104
1105 Dart_Handle closure = Dart_GetField(lib, NewString("getInt"));
1106 EXPECT_VALID(closure);
1107 EXPECT(Dart_IsClosure(closure));
1108 Dart_Handle closure_str = Dart_ToString(closure);
1109 const char* result = "";
1110 Dart_StringToCString(closure_str, &result);
1111 EXPECT(strstr(result, "getInt") != NULL);
1112
1113 Dart_Handle function = Dart_ClosureFunction(closure);
1114 EXPECT_VALID(function);
1115 EXPECT(Dart_IsFunction(function));
1116 Dart_Handle func_str = Dart_ToString(function);
1117 Dart_StringToCString(func_str, &result);
1118 EXPECT(strstr(result, "getInt"));
1119}
1120
1121TEST_CASE(DartAPI_GetStaticMethodClosure) {
1122 const char* kScriptChars =
1123 "class Foo {\n"
1124 " static int getInt() {\n"
1125 " return 1;\n"
1126 " }\n"
1127 " double getDouble() {\n"
1128 " return 1.0;\n"
1129 " }\n"
1130 "}\n";
1131 // Create a test library and Load up a test script in it.
1132 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
1133 EXPECT_VALID(lib);
1134 Dart_Handle foo_cls = Dart_GetClass(lib, NewString("Foo"));
1135 EXPECT_VALID(foo_cls);
1136
1137 Dart_Handle closure =
1138 Dart_GetStaticMethodClosure(lib, foo_cls, NewString("getInt"));
1139 EXPECT_VALID(closure);
1140 EXPECT(Dart_IsClosure(closure));
1141 Dart_Handle closure_str = Dart_ToString(closure);
1142 const char* result = "";
1143 Dart_StringToCString(closure_str, &result);
1144 EXPECT_SUBSTRING("getInt", result);
1145
1146 Dart_Handle function = Dart_ClosureFunction(closure);
1147 EXPECT_VALID(function);
1148 EXPECT(Dart_IsFunction(function));
1149 Dart_Handle func_str = Dart_ToString(function);
1150 Dart_StringToCString(func_str, &result);
1151 EXPECT_SUBSTRING("getInt", result);
1152
1153 Dart_Handle cls = Dart_FunctionOwner(function);
1154 EXPECT_VALID(cls);
1155 EXPECT(Dart_IsInstance(cls));
1156 Dart_Handle cls_str = Dart_ClassName(cls);
1157 Dart_StringToCString(cls_str, &result);
1158 EXPECT_SUBSTRING("Foo", result);
1159
1160 EXPECT_ERROR(Dart_ClassName(Dart_Null()),
1161 "Dart_ClassName expects argument 'cls_type' to be non-null.");
1162 EXPECT_ERROR(
1163 Dart_GetStaticMethodClosure(Dart_Null(), foo_cls, NewString("getInt")),
1164 "Dart_GetStaticMethodClosure expects argument 'library' to be non-null.");
1165 EXPECT_ERROR(
1166 Dart_GetStaticMethodClosure(lib, Dart_Null(), NewString("getInt")),
1167 "Dart_GetStaticMethodClosure expects argument 'cls_type' to be "
1168 "non-null.");
1169 EXPECT_ERROR(Dart_GetStaticMethodClosure(lib, foo_cls, Dart_Null()),
1170 "Dart_GetStaticMethodClosure expects argument 'function_name' "
1171 "to be non-null.");
1172}
1173
1174TEST_CASE(DartAPI_ClassLibrary) {
1175 Dart_Handle lib = Dart_LookupLibrary(NewString("dart:core"));
1176 EXPECT_VALID(lib);
1177 Dart_Handle type = Dart_GetNonNullableType(lib, NewString("int"), 0, NULL);
1178 EXPECT_VALID(type);
1179 Dart_Handle result = Dart_ClassLibrary(type);
1180 EXPECT_VALID(result);
1181 Dart_Handle lib_url = Dart_LibraryUrl(result);
1182 const char* str = NULL;
1183 Dart_StringToCString(lib_url, &str);
1184 EXPECT_STREQ("dart:core", str);
1185}
1186
1187TEST_CASE(DartAPI_BooleanValues) {
1188 Dart_Handle str = NewString("test");
1189 EXPECT(!Dart_IsBoolean(str));
1190
1191 bool value = false;
1192 Dart_Handle result = Dart_BooleanValue(str, &value);
1193 EXPECT(Dart_IsError(result));
1194
1195 Dart_Handle val1 = Dart_NewBoolean(true);
1196 EXPECT(Dart_IsBoolean(val1));
1197
1198 result = Dart_BooleanValue(val1, &value);
1199 EXPECT_VALID(result);
1200 EXPECT(value);
1201
1202 Dart_Handle val2 = Dart_NewBoolean(false);
1203 EXPECT(Dart_IsBoolean(val2));
1204
1205 result = Dart_BooleanValue(val2, &value);
1206 EXPECT_VALID(result);
1207 EXPECT(!value);
1208}
1209
1210TEST_CASE(DartAPI_BooleanConstants) {
1211 Dart_Handle true_handle = Dart_True();
1212 EXPECT_VALID(true_handle);
1213 EXPECT(Dart_IsBoolean(true_handle));
1214
1215 bool value = false;
1216 Dart_Handle result = Dart_BooleanValue(true_handle, &value);
1217 EXPECT_VALID(result);
1218 EXPECT(value);
1219
1220 Dart_Handle false_handle = Dart_False();
1221 EXPECT_VALID(false_handle);
1222 EXPECT(Dart_IsBoolean(false_handle));
1223
1224 result = Dart_BooleanValue(false_handle, &value);
1225 EXPECT_VALID(result);
1226 EXPECT(!value);
1227}
1228
1229TEST_CASE(DartAPI_DoubleValues) {
1230 const double kDoubleVal1 = 201.29;
1231 const double kDoubleVal2 = 101.19;
1232 Dart_Handle val1 = Dart_NewDouble(kDoubleVal1);
1233 EXPECT(Dart_IsDouble(val1));
1234 Dart_Handle val2 = Dart_NewDouble(kDoubleVal2);
1235 EXPECT(Dart_IsDouble(val2));
1236 double out1, out2;
1237 Dart_Handle result = Dart_DoubleValue(val1, &out1);
1238 EXPECT_VALID(result);
1239 EXPECT_EQ(kDoubleVal1, out1);
1240 result = Dart_DoubleValue(val2, &out2);
1241 EXPECT_VALID(result);
1242 EXPECT_EQ(kDoubleVal2, out2);
1243}
1244
1245TEST_CASE(DartAPI_NumberValues) {
1246 // TODO(antonm): add various kinds of ints (smi, mint, bigint).
1247 const char* kScriptChars =
1248 "int getInt() { return 1; }\n"
1249 "double getDouble() { return 1.0; }\n"
1250 "bool getBool() { return false; }\n"
1251 "getNull() { return null; }\n";
1252 Dart_Handle result;
1253 // Create a test library and Load up a test script in it.
1254 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
1255
1256 // Check int case.
1257 result = Dart_Invoke(lib, NewString("getInt"), 0, NULL);
1258 EXPECT_VALID(result);
1259 EXPECT(Dart_IsNumber(result));
1260
1261 // Check double case.
1262 result = Dart_Invoke(lib, NewString("getDouble"), 0, NULL);
1263 EXPECT_VALID(result);
1264 EXPECT(Dart_IsNumber(result));
1265
1266 // Check bool case.
1267 result = Dart_Invoke(lib, NewString("getBool"), 0, NULL);
1268 EXPECT_VALID(result);
1269 EXPECT(!Dart_IsNumber(result));
1270
1271 // Check null case.
1272 result = Dart_Invoke(lib, NewString("getNull"), 0, NULL);
1273 EXPECT_VALID(result);
1274 EXPECT(!Dart_IsNumber(result));
1275}
1276
1277TEST_CASE(DartAPI_IntegerValues) {
1278 const int64_t kIntegerVal1 = 100;
1279 const int64_t kIntegerVal2 = 0xffffffff;
1280 const char* kIntegerVal3 = "0x123456789123456789123456789";
1281 const uint64_t kIntegerVal4 = 0xffffffffffffffff;
1282 const int64_t kIntegerVal5 = -0x7fffffffffffffff;
1283
1284 Dart_Handle val1 = Dart_NewInteger(kIntegerVal1);
1285 EXPECT(Dart_IsInteger(val1));
1286 bool fits = false;
1287 Dart_Handle result = Dart_IntegerFitsIntoInt64(val1, &fits);
1288 EXPECT_VALID(result);
1289 EXPECT(fits);
1290
1291 int64_t out = 0;
1292 result = Dart_IntegerToInt64(val1, &out);
1293 EXPECT_VALID(result);
1294 EXPECT_EQ(kIntegerVal1, out);
1295
1296 Dart_Handle val2 = Dart_NewInteger(kIntegerVal2);
1297 EXPECT(Dart_IsInteger(val2));
1298 result = Dart_IntegerFitsIntoInt64(val2, &fits);
1299 EXPECT_VALID(result);
1300 EXPECT(fits);
1301
1302 result = Dart_IntegerToInt64(val2, &out);
1303 EXPECT_VALID(result);
1304 EXPECT_EQ(kIntegerVal2, out);
1305
1306 Dart_Handle val3 = Dart_NewIntegerFromHexCString(kIntegerVal3);
1307 EXPECT(Dart_IsApiError(val3));
1308
1309 Dart_Handle val4 = Dart_NewIntegerFromUint64(kIntegerVal4);
1310 EXPECT(Dart_IsApiError(val4));
1311
1312 Dart_Handle val5 = Dart_NewInteger(-1);
1313 EXPECT_VALID(val5);
1314 uint64_t out5 = 0;
1315 result = Dart_IntegerToUint64(val5, &out5);
1316 EXPECT(Dart_IsError(result));
1317
1318 Dart_Handle val6 = Dart_NewInteger(kIntegerVal5);
1319 EXPECT_VALID(val6);
1320 uint64_t out6 = 0;
1321 result = Dart_IntegerToUint64(val6, &out6);
1322 EXPECT(Dart_IsError(result));
1323}
1324
1325TEST_CASE(DartAPI_IntegerToHexCString) {
1326 const struct {
1327 int64_t i;
1328 const char* s;
1329 } kIntTestCases[] = {
1330 {0, "0x0"},
1331 {1, "0x1"},
1332 {-1, "-0x1"},
1333 {0x123, "0x123"},
1334 {-0xABCDEF, "-0xABCDEF"},
1335 {DART_INT64_C(-0x7FFFFFFFFFFFFFFF), "-0x7FFFFFFFFFFFFFFF"},
1336 {kMaxInt64, "0x7FFFFFFFFFFFFFFF"},
1337 {kMinInt64, "-0x8000000000000000"},
1338 };
1339
1340 const size_t kNumberOfIntTestCases =
1341 sizeof(kIntTestCases) / sizeof(kIntTestCases[0]);
1342
1343 for (size_t i = 0; i < kNumberOfIntTestCases; ++i) {
1344 Dart_Handle val = Dart_NewInteger(kIntTestCases[i].i);
1345 EXPECT_VALID(val);
1346 const char* chars = NULL;
1347 Dart_Handle result = Dart_IntegerToHexCString(val, &chars);
1348 EXPECT_VALID(result);
1349 EXPECT_STREQ(kIntTestCases[i].s, chars);
1350 }
1351}
1352
1353TEST_CASE(DartAPI_IntegerFitsIntoInt64) {
1354 Dart_Handle max = Dart_NewInteger(kMaxInt64);
1355 EXPECT(Dart_IsInteger(max));
1356 bool fits = false;
1357 Dart_Handle result = Dart_IntegerFitsIntoInt64(max, &fits);
1358 EXPECT_VALID(result);
1359 EXPECT(fits);
1360
1361 Dart_Handle above_max = Dart_NewIntegerFromHexCString("0x10000000000000000");
1362 EXPECT(Dart_IsApiError(above_max));
1363
1364 Dart_Handle min = Dart_NewInteger(kMinInt64);
1365 EXPECT(Dart_IsInteger(min));
1366 fits = false;
1367 result = Dart_IntegerFitsIntoInt64(min, &fits);
1368 EXPECT_VALID(result);
1369 EXPECT(fits);
1370
1371 Dart_Handle below_min = Dart_NewIntegerFromHexCString("-0x10000000000000001");
1372 EXPECT(Dart_IsApiError(below_min));
1373}
1374
1375TEST_CASE(DartAPI_IntegerFitsIntoUint64) {
1376 Dart_Handle max = Dart_NewIntegerFromUint64(kMaxUint64);
1377 EXPECT(Dart_IsApiError(max));
1378
1379 Dart_Handle above_max = Dart_NewIntegerFromHexCString("0x10000000000000000");
1380 EXPECT(Dart_IsApiError(above_max));
1381
1382 Dart_Handle min = Dart_NewInteger(0);
1383 EXPECT(Dart_IsInteger(min));
1384 bool fits = false;
1385 Dart_Handle result = Dart_IntegerFitsIntoUint64(min, &fits);
1386 EXPECT_VALID(result);
1387 EXPECT(fits);
1388
1389 Dart_Handle below_min = Dart_NewIntegerFromHexCString("-1");
1390 EXPECT(Dart_IsInteger(below_min));
1391 fits = true;
1392 result = Dart_IntegerFitsIntoUint64(below_min, &fits);
1393 EXPECT_VALID(result);
1394 EXPECT(!fits);
1395}
1396
1397TEST_CASE(DartAPI_ArrayValues) {
1398 EXPECT(!Dart_IsList(Dart_Null()));
1399 const int kArrayLength = 10;
1400 Dart_Handle str = NewString("test");
1401 EXPECT(!Dart_IsList(str));
1402 Dart_Handle val = Dart_NewList(kArrayLength);
1403 EXPECT(Dart_IsList(val));
1404 intptr_t len = 0;
1405 Dart_Handle result = Dart_ListLength(val, &len);
1406 EXPECT_VALID(result);
1407 EXPECT_EQ(kArrayLength, len);
1408
1409 // Check invalid array access.
1410 result = Dart_ListSetAt(val, (kArrayLength + 10), Dart_NewInteger(10));
1411 EXPECT(Dart_IsError(result));
1412 result = Dart_ListSetAt(val, -10, Dart_NewInteger(10));
1413 EXPECT(Dart_IsError(result));
1414 result = Dart_ListGetAt(val, (kArrayLength + 10));
1415 EXPECT(Dart_IsError(result));
1416 result = Dart_ListGetAt(val, -10);
1417 EXPECT(Dart_IsError(result));
1418
1419 for (int i = 0; i < kArrayLength; i++) {
1420 result = Dart_ListSetAt(val, i, Dart_NewInteger(i));
1421 EXPECT_VALID(result);
1422 }
1423 for (int i = 0; i < kArrayLength; i++) {
1424 result = Dart_ListGetAt(val, i);
1425 EXPECT_VALID(result);
1426 int64_t value;
1427 result = Dart_IntegerToInt64(result, &value);
1428 EXPECT_VALID(result);
1429 EXPECT_EQ(i, value);
1430 }
1431}
1432
1433static void NoopFinalizer(void* isolate_callback_data,
1434 Dart_WeakPersistentHandle handle,
1435 void* peer) {}
1436
1437TEST_CASE(DartAPI_IsString) {
1438 uint8_t latin1[] = {'o', 'n', 'e', 0xC2, 0xA2};
1439
1440 Dart_Handle latin1str = Dart_NewStringFromUTF8(latin1, ARRAY_SIZE(latin1));
1441 EXPECT_VALID(latin1str);
1442 EXPECT(Dart_IsString(latin1str));
1443 EXPECT(Dart_IsStringLatin1(latin1str));
1444 EXPECT(!Dart_IsExternalString(latin1str));
1445 intptr_t len = -1;
1446 EXPECT_VALID(Dart_StringLength(latin1str, &len));
1447 EXPECT_EQ(4, len);
1448 intptr_t char_size;
1449 intptr_t str_len;
1450 void* peer;
1451 EXPECT_VALID(
1452 Dart_StringGetProperties(latin1str, &char_size, &str_len, &peer));
1453 EXPECT_EQ(1, char_size);
1454 EXPECT_EQ(4, str_len);
1455 EXPECT(!peer);
1456
1457 uint8_t data8[] = {'o', 'n', 'e', 0x7F};
1458
1459 Dart_Handle str8 = Dart_NewStringFromUTF8(data8, ARRAY_SIZE(data8));
1460 EXPECT_VALID(str8);
1461 EXPECT(Dart_IsString(str8));
1462 EXPECT(Dart_IsStringLatin1(str8));
1463 EXPECT(!Dart_IsExternalString(str8));
1464
1465 uint8_t latin1_array[] = {0, 0, 0, 0, 0};
1466 len = 5;
1467 Dart_Handle result = Dart_StringToLatin1(str8, latin1_array, &len);
1468 EXPECT_VALID(result);
1469 EXPECT_EQ(4, len);
1470 EXPECT(latin1_array != NULL);
1471 for (intptr_t i = 0; i < len; i++) {
1472 EXPECT_EQ(data8[i], latin1_array[i]);
1473 }
1474
1475 Dart_Handle ext8 = Dart_NewExternalLatin1String(
1476 data8, ARRAY_SIZE(data8), data8, sizeof(data8), NoopFinalizer);
1477 EXPECT_VALID(ext8);
1478 EXPECT(Dart_IsString(ext8));
1479 EXPECT(Dart_IsExternalString(ext8));
1480 EXPECT_VALID(Dart_StringGetProperties(ext8, &char_size, &str_len, &peer));
1481 EXPECT_EQ(1, char_size);
1482 EXPECT_EQ(4, str_len);
1483 EXPECT_EQ(data8, peer);
1484
1485 uint16_t data16[] = {'t', 'w', 'o', 0xFFFF};
1486
1487 Dart_Handle str16 = Dart_NewStringFromUTF16(data16, ARRAY_SIZE(data16));
1488 EXPECT_VALID(str16);
1489 EXPECT(Dart_IsString(str16));
1490 EXPECT(!Dart_IsStringLatin1(str16));
1491 EXPECT(!Dart_IsExternalString(str16));
1492 EXPECT_VALID(Dart_StringGetProperties(str16, &char_size, &str_len, &peer));
1493 EXPECT_EQ(2, char_size);
1494 EXPECT_EQ(4, str_len);
1495 EXPECT(!peer);
1496
1497 Dart_Handle ext16 = Dart_NewExternalUTF16String(
1498 data16, ARRAY_SIZE(data16), data16, sizeof(data16), NoopFinalizer);
1499 EXPECT_VALID(ext16);
1500 EXPECT(Dart_IsString(ext16));
1501 EXPECT(Dart_IsExternalString(ext16));
1502 EXPECT_VALID(Dart_StringGetProperties(ext16, &char_size, &str_len, &peer));
1503 EXPECT_EQ(2, char_size);
1504 EXPECT_EQ(4, str_len);
1505 EXPECT_EQ(data16, peer);
1506
1507 int32_t data32[] = {'f', 'o', 'u', 'r', 0x10FFFF};
1508
1509 Dart_Handle str32 = Dart_NewStringFromUTF32(data32, ARRAY_SIZE(data32));
1510 EXPECT_VALID(str32);
1511 EXPECT(Dart_IsString(str32));
1512 EXPECT(!Dart_IsExternalString(str32));
1513}
1514
1515TEST_CASE(DartAPI_NewString) {
1516 const char* ascii = "string";
1517 Dart_Handle ascii_str = NewString(ascii);
1518 EXPECT_VALID(ascii_str);
1519 EXPECT(Dart_IsString(ascii_str));
1520
1521 const char* null = NULL;
1522 Dart_Handle null_str = NewString(null);
1523 EXPECT(Dart_IsError(null_str));
1524
1525 uint8_t data[] = {0xE4, 0xBA, 0x8c}; // U+4E8C.
1526 Dart_Handle utf8_str = Dart_NewStringFromUTF8(data, ARRAY_SIZE(data));
1527 EXPECT_VALID(utf8_str);
1528 EXPECT(Dart_IsString(utf8_str));
1529
1530 uint8_t invalid[] = {0xE4, 0xBA}; // underflow.
1531 Dart_Handle invalid_str =
1532 Dart_NewStringFromUTF8(invalid, ARRAY_SIZE(invalid));
1533 EXPECT(Dart_IsError(invalid_str));
1534}
1535
1536TEST_CASE(DartAPI_MalformedStringToUTF8) {
1537 // 1D11E = treble clef
1538 // [0] should be high surrogate D834
1539 // [1] should be low surrogate DD1E
1540 // Strings are allowed to have individual or out of order surrogates, even
1541 // if that doesn't make sense as renderable characters.
1542 const char* kScriptChars =
1543 "String lowSurrogate() {"
1544 " return '\\u{1D11E}'[1];"
1545 "}"
1546 "String highSurrogate() {"
1547 " return '\\u{1D11E}'[0];"
1548 "}"
1549 "String reversed() => lowSurrogate() + highSurrogate();";
1550
1551 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
1552 Dart_Handle str1 = Dart_Invoke(lib, NewString("lowSurrogate"), 0, NULL);
1553 EXPECT_VALID(str1);
1554
1555 uint8_t* utf8_encoded = NULL;
1556 intptr_t utf8_length = 0;
1557 Dart_Handle result = Dart_StringToUTF8(str1, &utf8_encoded, &utf8_length);
1558 EXPECT_VALID(result);
1559 EXPECT_EQ(3, utf8_length);
1560 // Unpaired surrogate is encoded as replacement character.
1561 EXPECT_EQ(239, static_cast<intptr_t>(utf8_encoded[0]));
1562 EXPECT_EQ(191, static_cast<intptr_t>(utf8_encoded[1]));
1563 EXPECT_EQ(189, static_cast<intptr_t>(utf8_encoded[2]));
1564
1565 Dart_Handle str2 = Dart_NewStringFromUTF8(utf8_encoded, utf8_length);
1566 EXPECT_VALID(str2); // Replacement character, but still valid
1567
1568 Dart_Handle reversed = Dart_Invoke(lib, NewString("reversed"), 0, NULL);
1569 EXPECT_VALID(reversed); // This is also allowed.
1570 uint8_t* utf8_encoded_reversed = NULL;
1571 intptr_t utf8_length_reversed = 0;
1572 result = Dart_StringToUTF8(reversed, &utf8_encoded_reversed,
1573 &utf8_length_reversed);
1574 EXPECT_VALID(result);
1575 EXPECT_EQ(6, utf8_length_reversed);
1576 // Two unpaired surrogates are encoded as two replacement characters.
1577 uint8_t expected[6] = {239, 191, 189, 239, 191, 189};
1578 for (int i = 0; i < 6; i++) {
1579 EXPECT_EQ(expected[i], utf8_encoded_reversed[i]);
1580 }
1581}
1582
1583static void ExternalStringCallbackFinalizer(void* isolate_callback_data,
1584 Dart_WeakPersistentHandle handle,
1585 void* peer) {
1586 *static_cast<int*>(peer) *= 2;
1587}
1588
1589TEST_CASE(DartAPI_ExternalStringCallback) {
1590 int peer8 = 40;
1591 int peer16 = 41;
1592
1593 {
1594 Dart_EnterScope();
1595
1596 uint8_t data8[] = {'h', 'e', 'l', 'l', 'o'};
1597 Dart_Handle obj8 = Dart_NewExternalLatin1String(
1598 data8, ARRAY_SIZE(data8), &peer8, sizeof(data8),
1599 ExternalStringCallbackFinalizer);
1600 EXPECT_VALID(obj8);
1601
1602 uint16_t data16[] = {'h', 'e', 'l', 'l', 'o'};
1603 Dart_Handle obj16 = Dart_NewExternalUTF16String(
1604 data16, ARRAY_SIZE(data16), &peer16, sizeof(data16),
1605 ExternalStringCallbackFinalizer);
1606 EXPECT_VALID(obj16);
1607
1608 Dart_ExitScope();
1609 }
1610
1611 {
1612 TransitionNativeToVM transition(thread);
1613 EXPECT_EQ(40, peer8);
1614 EXPECT_EQ(41, peer16);
1615 GCTestHelper::CollectOldSpace();
1616 EXPECT_EQ(40, peer8);
1617 EXPECT_EQ(41, peer16);
1618 GCTestHelper::CollectNewSpace();
1619 EXPECT_EQ(80, peer8);
1620 EXPECT_EQ(82, peer16);
1621 }
1622}
1623
1624TEST_CASE(DartAPI_ExternalStringPretenure) {
1625 {
1626 Dart_EnterScope();
1627 static const uint8_t big_data8[16 * MB] = {
1628 0,
1629 };
1630 Dart_Handle big8 =
1631 Dart_NewExternalLatin1String(big_data8, ARRAY_SIZE(big_data8), NULL,
1632 sizeof(big_data8), NoopFinalizer);
1633 EXPECT_VALID(big8);
1634 static const uint16_t big_data16[16 * MB / 2] = {
1635 0,
1636 };
1637 Dart_Handle big16 =
1638 Dart_NewExternalUTF16String(big_data16, ARRAY_SIZE(big_data16), NULL,
1639 sizeof(big_data16), NoopFinalizer);
1640 static const uint8_t small_data8[] = {'f', 'o', 'o'};
1641 Dart_Handle small8 =
1642 Dart_NewExternalLatin1String(small_data8, ARRAY_SIZE(small_data8), NULL,
1643 sizeof(small_data8), NoopFinalizer);
1644 EXPECT_VALID(small8);
1645 static const uint16_t small_data16[] = {'b', 'a', 'r'};
1646 Dart_Handle small16 =
1647 Dart_NewExternalUTF16String(small_data16, ARRAY_SIZE(small_data16),
1648 NULL, sizeof(small_data16), NoopFinalizer);
1649 EXPECT_VALID(small16);
1650 {
1651 CHECK_API_SCOPE(thread);
1652 TransitionNativeToVM transition(thread);
1653 HANDLESCOPE(thread);
1654 String& handle = String::Handle();
1655 handle ^= Api::UnwrapHandle(big8);
1656 EXPECT(handle.IsOld());
1657 handle ^= Api::UnwrapHandle(big16);
1658 EXPECT(handle.IsOld());
1659 handle ^= Api::UnwrapHandle(small8);
1660 EXPECT(handle.IsNew());
1661 handle ^= Api::UnwrapHandle(small16);
1662 EXPECT(handle.IsNew());
1663 }
1664 Dart_ExitScope();
1665 }
1666}
1667
1668TEST_CASE(DartAPI_ExternalTypedDataPretenure) {
1669 {
1670 Dart_EnterScope();
1671 static const int kBigLength = 16 * MB / 8;
1672 int64_t* big_data = new int64_t[kBigLength]();
1673 Dart_Handle big =
1674 Dart_NewExternalTypedData(Dart_TypedData_kInt64, big_data, kBigLength);
1675 EXPECT_VALID(big);
1676 static const int kSmallLength = 16 * KB / 8;
1677 int64_t* small_data = new int64_t[kSmallLength]();
1678 Dart_Handle small = Dart_NewExternalTypedData(Dart_TypedData_kInt64,
1679 small_data, kSmallLength);
1680 EXPECT_VALID(small);
1681 {
1682 CHECK_API_SCOPE(thread);
1683 TransitionNativeToVM transition(thread);
1684 HANDLESCOPE(thread);
1685 ExternalTypedData& handle = ExternalTypedData::Handle();
1686 handle ^= Api::UnwrapHandle(big);
1687 EXPECT(handle.IsOld());
1688 handle ^= Api::UnwrapHandle(small);
1689 EXPECT(handle.IsNew());
1690 }
1691 Dart_ExitScope();
1692 delete[] big_data;
1693 delete[] small_data;
1694 }
1695}
1696
1697TEST_CASE(DartAPI_ListAccess) {
1698 const char* kScriptChars =
1699 "List testMain() {"
1700 " List a = List.empty(growable: true);"
1701 " a.add(10);"
1702 " a.add(20);"
1703 " a.add(30);"
1704 " return a;"
1705 "}"
1706 ""
1707 "List immutable() {"
1708 " return const [0, 1, 2];"
1709 "}";
1710 Dart_Handle result;
1711
1712 // Create a test library and Load up a test script in it.
1713 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
1714
1715 // Invoke a function which returns an object of type List.
1716 result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
1717 EXPECT_VALID(result);
1718
1719 // First ensure that the returned object is an array.
1720 Dart_Handle list_access_test_obj = result;
1721
1722 EXPECT(Dart_IsList(list_access_test_obj));
1723
1724 // Get length of array object.
1725 intptr_t len = 0;
1726 result = Dart_ListLength(list_access_test_obj, &len);
1727 EXPECT_VALID(result);
1728 EXPECT_EQ(3, len);
1729
1730 // Access elements in the array.
1731 int64_t value;
1732
1733 result = Dart_ListGetAt(list_access_test_obj, 0);
1734 EXPECT_VALID(result);
1735 result = Dart_IntegerToInt64(result, &value);
1736 EXPECT_VALID(result);
1737 EXPECT_EQ(10, value);
1738
1739 result = Dart_ListGetAt(list_access_test_obj, 1);
1740 EXPECT_VALID(result);
1741 result = Dart_IntegerToInt64(result, &value);
1742 EXPECT_VALID(result);
1743 EXPECT_EQ(20, value);
1744
1745 result = Dart_ListGetAt(list_access_test_obj, 2);
1746 EXPECT_VALID(result);
1747 result = Dart_IntegerToInt64(result, &value);
1748 EXPECT_VALID(result);
1749 EXPECT_EQ(30, value);
1750
1751 // Set some elements in the array.
1752 result = Dart_ListSetAt(list_access_test_obj, 0, Dart_NewInteger(0));
1753 EXPECT_VALID(result);
1754 result = Dart_ListSetAt(list_access_test_obj, 1, Dart_NewInteger(1));
1755 EXPECT_VALID(result);
1756 result = Dart_ListSetAt(list_access_test_obj, 2, Dart_NewInteger(2));
1757 EXPECT_VALID(result);
1758
1759 // Get length of array object.
1760 result = Dart_ListLength(list_access_test_obj, &len);
1761 EXPECT_VALID(result);
1762 EXPECT_EQ(3, len);
1763
1764 // Now try and access these elements in the array.
1765 result = Dart_ListGetAt(list_access_test_obj, 0);
1766 EXPECT_VALID(result);
1767 result = Dart_IntegerToInt64(result, &value);
1768 EXPECT_VALID(result);
1769 EXPECT_EQ(0, value);
1770
1771 result = Dart_ListGetAt(list_access_test_obj, 1);
1772 EXPECT_VALID(result);
1773 result = Dart_IntegerToInt64(result, &value);
1774 EXPECT_VALID(result);
1775 EXPECT_EQ(1, value);
1776
1777 result = Dart_ListGetAt(list_access_test_obj, 2);
1778 EXPECT_VALID(result);
1779 result = Dart_IntegerToInt64(result, &value);
1780 EXPECT_VALID(result);
1781 EXPECT_EQ(2, value);
1782
1783 uint8_t native_array[3];
1784 result = Dart_ListGetAsBytes(list_access_test_obj, 0, native_array, 3);
1785 EXPECT_VALID(result);
1786 EXPECT_EQ(0, native_array[0]);
1787 EXPECT_EQ(1, native_array[1]);
1788 EXPECT_EQ(2, native_array[2]);
1789
1790 native_array[0] = 10;
1791 native_array[1] = 20;
1792 native_array[2] = 30;
1793 result = Dart_ListSetAsBytes(list_access_test_obj, 0, native_array, 3);
1794 EXPECT_VALID(result);
1795 result = Dart_ListGetAsBytes(list_access_test_obj, 0, native_array, 3);
1796 EXPECT_VALID(result);
1797 EXPECT_EQ(10, native_array[0]);
1798 EXPECT_EQ(20, native_array[1]);
1799 EXPECT_EQ(30, native_array[2]);
1800 result = Dart_ListGetAt(list_access_test_obj, 2);
1801 EXPECT_VALID(result);
1802 result = Dart_IntegerToInt64(result, &value);
1803 EXPECT_VALID(result);
1804 EXPECT_EQ(30, value);
1805
1806 // Check if we get an exception when accessing beyond limit.
1807 result = Dart_ListGetAt(list_access_test_obj, 4);
1808 EXPECT(Dart_IsError(result));
1809
1810 // Check if we can get a range of values.
1811 result = Dart_ListGetRange(list_access_test_obj, 8, 4, NULL);
1812 EXPECT(Dart_IsError(result));
1813 const int kRangeOffset = 1;
1814 const int kRangeLength = 2;
1815 Dart_Handle values[kRangeLength];
1816
1817 result = Dart_ListGetRange(list_access_test_obj, 8, 4, values);
1818 EXPECT(Dart_IsError(result));
1819
1820 result = Dart_ListGetRange(list_access_test_obj, kRangeOffset, kRangeLength,
1821 values);
1822 EXPECT_VALID(result);
1823
1824 result = Dart_IntegerToInt64(values[0], &value);
1825 EXPECT_VALID(result);
1826 EXPECT_EQ(20, value);
1827
1828 result = Dart_IntegerToInt64(values[1], &value);
1829 EXPECT_VALID(result);
1830 EXPECT_EQ(30, value);
1831
1832 // Check that we get an exception (and not a fatal error) when
1833 // calling ListSetAt and ListSetAsBytes with an immutable list.
1834 list_access_test_obj = Dart_Invoke(lib, NewString("immutable"), 0, NULL);
1835 EXPECT_VALID(list_access_test_obj);
1836 EXPECT(Dart_IsList(list_access_test_obj));
1837
1838 result = Dart_ListSetAsBytes(list_access_test_obj, 0, native_array, 3);
1839 EXPECT(Dart_IsError(result));
1840 EXPECT(Dart_IsUnhandledExceptionError(result));
1841
1842 result = Dart_ListSetAt(list_access_test_obj, 0, Dart_NewInteger(42));
1843 EXPECT(Dart_IsError(result));
1844 EXPECT(Dart_IsUnhandledExceptionError(result));
1845}
1846
1847TEST_CASE(DartAPI_MapAccess) {
1848 EXPECT(!Dart_IsMap(Dart_Null()));
1849 const char* kScriptChars =
1850 "Map testMain() {"
1851 " return {"
1852 " 'a' : 1,"
1853 " 'b' : null,"
1854 " };"
1855 "}";
1856 Dart_Handle result;
1857
1858 // Create a test library and Load up a test script in it.
1859 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
1860
1861 // Invoke a function which returns an object of type Map.
1862 result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
1863 EXPECT_VALID(result);
1864
1865 // First ensure that the returned object is a map.
1866 Dart_Handle map = result;
1867 Dart_Handle a = NewString("a");
1868 Dart_Handle b = NewString("b");
1869 Dart_Handle c = NewString("c");
1870
1871 EXPECT(Dart_IsMap(map));
1872 EXPECT(!Dart_IsMap(a));
1873
1874 // Access values in the map.
1875 int64_t value;
1876 result = Dart_MapGetAt(map, a);
1877 EXPECT_VALID(result);
1878 result = Dart_IntegerToInt64(result, &value);
1879 EXPECT_VALID(result);
1880 EXPECT_EQ(value, 1);
1881
1882 result = Dart_MapGetAt(map, b);
1883 EXPECT(Dart_IsNull(result));
1884
1885 result = Dart_MapGetAt(map, c);
1886 EXPECT(Dart_IsNull(result));
1887
1888 EXPECT(Dart_IsError(Dart_MapGetAt(a, a)));
1889
1890 // Test for presence of keys.
1891 bool contains = false;
1892 result = Dart_MapContainsKey(map, a);
1893 EXPECT_VALID(result);
1894 result = Dart_BooleanValue(result, &contains);
1895 EXPECT_VALID(result);
1896 EXPECT(contains);
1897
1898 contains = false;
1899 result = Dart_MapContainsKey(map, NewString("b"));
1900 EXPECT_VALID(result);
1901 result = Dart_BooleanValue(result, &contains);
1902 EXPECT_VALID(result);
1903 EXPECT(contains);
1904
1905 contains = true;
1906 result = Dart_MapContainsKey(map, NewString("c"));
1907 EXPECT_VALID(result);
1908 result = Dart_BooleanValue(result, &contains);
1909 EXPECT_VALID(result);
1910 EXPECT(!contains);
1911
1912 EXPECT(Dart_IsError(Dart_MapContainsKey(a, a)));
1913
1914 // Enumerate keys. (Note literal maps guarantee key order.)
1915 Dart_Handle keys = Dart_MapKeys(map);
1916 EXPECT_VALID(keys);
1917
1918 intptr_t len = 0;
1919 bool equals;
1920 result = Dart_ListLength(keys, &len);
1921 EXPECT_VALID(result);
1922 EXPECT_EQ(2, len);
1923
1924 result = Dart_ListGetAt(keys, 0);
1925 EXPECT(Dart_IsString(result));
1926 equals = false;
1927 EXPECT_VALID(Dart_ObjectEquals(result, a, &equals));
1928 EXPECT(equals);
1929
1930 result = Dart_ListGetAt(keys, 1);
1931 EXPECT(Dart_IsString(result));
1932 equals = false;
1933 EXPECT_VALID(Dart_ObjectEquals(result, b, &equals));
1934 EXPECT(equals);
1935
1936 EXPECT(Dart_IsError(Dart_MapKeys(a)));
1937}
1938
1939TEST_CASE(DartAPI_IsFuture) {
1940 const char* kScriptChars =
1941 "import 'dart:async';"
1942 "Future testMain() {"
1943 " return new Completer().future;"
1944 "}";
1945 Dart_Handle result;
1946
1947 // Create a test library and Load up a test script in it.
1948 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
1949
1950 // Invoke a function which returns an object of type Future.
1951 result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
1952 EXPECT_VALID(result);
1953 EXPECT(Dart_IsFuture(result));
1954
1955 EXPECT(!Dart_IsFuture(lib)); // Non-instance.
1956 Dart_Handle anInteger = Dart_NewInteger(0);
1957 EXPECT(!Dart_IsFuture(anInteger));
1958 Dart_Handle aString = NewString("I am not a Future");
1959 EXPECT(!Dart_IsFuture(aString));
1960 Dart_Handle null = Dart_Null();
1961 EXPECT(!Dart_IsFuture(null));
1962}
1963
1964TEST_CASE(DartAPI_TypedDataViewListGetAsBytes) {
1965 const int kSize = 1000;
1966
1967 const char* kScriptChars =
1968 "import 'dart:typed_data';\n"
1969 "List main(int size) {\n"
1970 " var a = new Int8List(size);\n"
1971 " var view = new Int8List.view(a.buffer, 0, size);\n"
1972 " return view;\n"
1973 "}\n";
1974 // Create a test library and Load up a test script in it.
1975 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
1976
1977 // Test with a typed data view object.
1978 Dart_Handle dart_args[1];
1979 dart_args[0] = Dart_NewInteger(kSize);
1980 Dart_Handle view_obj = Dart_Invoke(lib, NewString("main"), 1, dart_args);
1981 EXPECT_VALID(view_obj);
1982 for (intptr_t i = 0; i < kSize; ++i) {
1983 EXPECT_VALID(Dart_ListSetAt(view_obj, i, Dart_NewInteger(i & 0xff)));
1984 }
1985 uint8_t* data = new uint8_t[kSize];
1986 EXPECT_VALID(Dart_ListGetAsBytes(view_obj, 0, data, kSize));
1987 for (intptr_t i = 0; i < kSize; ++i) {
1988 EXPECT_EQ(i & 0xff, data[i]);
1989 }
1990
1991 Dart_Handle result = Dart_ListGetAsBytes(view_obj, 0, data, kSize + 1);
1992 EXPECT(Dart_IsError(result));
1993 delete[] data;
1994}
1995
1996TEST_CASE(DartAPI_TypedDataViewListIsTypedData) {
1997 const int kSize = 1000;
1998
1999 const char* kScriptChars =
2000 "import 'dart:typed_data';\n"
2001 "List main(int size) {\n"
2002 " var a = new Int8List(size);\n"
2003 " var view = new Int8List.view(a.buffer, 0, size);\n"
2004 " return view;\n"
2005 "}\n";
2006 // Create a test library and Load up a test script in it.
2007 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
2008
2009 // Create a typed data view object.
2010 Dart_Handle dart_args[1];
2011 dart_args[0] = Dart_NewInteger(kSize);
2012 Dart_Handle view_obj = Dart_Invoke(lib, NewString("main"), 1, dart_args);
2013 EXPECT_VALID(view_obj);
2014 // Test that the API considers it a TypedData object.
2015 EXPECT(Dart_IsTypedData(view_obj));
2016}
2017
2018TEST_CASE(DartAPI_TypedDataAccess) {
2019 EXPECT_EQ(Dart_TypedData_kInvalid, Dart_GetTypeOfTypedData(Dart_True()));
2020 EXPECT_EQ(Dart_TypedData_kInvalid,
2021 Dart_GetTypeOfExternalTypedData(Dart_False()));
2022 Dart_Handle byte_array1 = Dart_NewTypedData(Dart_TypedData_kUint8, 10);
2023 EXPECT_VALID(byte_array1);
2024 EXPECT_EQ(Dart_TypedData_kUint8, Dart_GetTypeOfTypedData(byte_array1));
2025 EXPECT_EQ(Dart_TypedData_kInvalid,
2026 Dart_GetTypeOfExternalTypedData(byte_array1));
2027 EXPECT(Dart_IsList(byte_array1));
2028 EXPECT(!Dart_IsTypedData(Dart_True()));
2029 EXPECT(Dart_IsTypedData(byte_array1));
2030 EXPECT(!Dart_IsByteBuffer(byte_array1));
2031
2032 intptr_t length = 0;
2033 Dart_Handle result = Dart_ListLength(byte_array1, &length);
2034 EXPECT_VALID(result);
2035 EXPECT_EQ(10, length);
2036
2037 result = Dart_ListSetAt(byte_array1, -1, Dart_NewInteger(1));
2038 EXPECT(Dart_IsError(result));
2039
2040 result = Dart_ListSetAt(byte_array1, 10, Dart_NewInteger(1));
2041 EXPECT(Dart_IsError(result));
2042
2043 // Set through the List API.
2044 for (intptr_t i = 0; i < 10; ++i) {
2045 EXPECT_VALID(Dart_ListSetAt(byte_array1, i, Dart_NewInteger(i + 1)));
2046 }
2047 for (intptr_t i = 0; i < 10; ++i) {
2048 // Get through the List API.
2049 Dart_Handle integer_obj = Dart_ListGetAt(byte_array1, i);
2050 EXPECT_VALID(integer_obj);
2051 int64_t int64_t_value = -1;
2052 EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
2053 EXPECT_EQ(i + 1, int64_t_value);
2054 }
2055
2056 Dart_Handle byte_array2 = Dart_NewTypedData(Dart_TypedData_kUint8, 10);
2057 bool is_equal = false;
2058 Dart_ObjectEquals(byte_array1, byte_array2, &is_equal);
2059 EXPECT(!is_equal);
2060
2061 // Set through the List API.
2062 for (intptr_t i = 0; i < 10; ++i) {
2063 result = Dart_ListSetAt(byte_array1, i, Dart_NewInteger(i + 2));
2064 EXPECT_VALID(result);
2065 result = Dart_ListSetAt(byte_array2, i, Dart_NewInteger(i + 2));
2066 EXPECT_VALID(result);
2067 }
2068 for (intptr_t i = 0; i < 10; ++i) {
2069 // Get through the List API.
2070 Dart_Handle e1 = Dart_ListGetAt(byte_array1, i);
2071 Dart_Handle e2 = Dart_ListGetAt(byte_array2, i);
2072 is_equal = false;
2073 Dart_ObjectEquals(e1, e2, &is_equal);
2074 EXPECT(is_equal);
2075 }
2076
2077 uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
2078 for (intptr_t i = 0; i < 10; ++i) {
2079 EXPECT_VALID(Dart_ListSetAt(byte_array1, i, Dart_NewInteger(10 - i)));
2080 }
2081 Dart_ListGetAsBytes(byte_array1, 0, data, 10);
2082 for (intptr_t i = 0; i < 10; ++i) {
2083 Dart_Handle integer_obj = Dart_ListGetAt(byte_array1, i);
2084 EXPECT_VALID(integer_obj);
2085 int64_t int64_t_value = -1;
2086 EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
2087 EXPECT_EQ(10 - i, int64_t_value);
2088 }
2089}
2090
2091TEST_CASE(DartAPI_ByteBufferAccess) {
2092 EXPECT(!Dart_IsByteBuffer(Dart_True()));
2093 Dart_Handle byte_array = Dart_NewTypedData(Dart_TypedData_kUint8, 10);
2094 EXPECT_VALID(byte_array);
2095 // Set through the List API.
2096 for (intptr_t i = 0; i < 10; ++i) {
2097 EXPECT_VALID(Dart_ListSetAt(byte_array, i, Dart_NewInteger(i + 1)));
2098 }
2099 Dart_Handle byte_buffer = Dart_NewByteBuffer(byte_array);
2100 EXPECT_VALID(byte_buffer);
2101 EXPECT(Dart_IsByteBuffer(byte_buffer));
2102 EXPECT(!Dart_IsTypedData(byte_buffer));
2103
2104 Dart_Handle byte_buffer_data = Dart_GetDataFromByteBuffer(byte_buffer);
2105 EXPECT_VALID(byte_buffer_data);
2106 EXPECT(!Dart_IsByteBuffer(byte_buffer_data));
2107 EXPECT(Dart_IsTypedData(byte_buffer_data));
2108
2109 intptr_t length = 0;
2110 Dart_Handle result = Dart_ListLength(byte_buffer_data, &length);
2111 EXPECT_VALID(result);
2112 EXPECT_EQ(10, length);
2113
2114 for (intptr_t i = 0; i < 10; ++i) {
2115 // Get through the List API.
2116 Dart_Handle integer_obj = Dart_ListGetAt(byte_buffer_data, i);
2117 EXPECT_VALID(integer_obj);
2118 int64_t int64_t_value = -1;
2119 EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
2120 EXPECT_EQ(i + 1, int64_t_value);
2121 }
2122
2123 // Some negative tests.
2124 result = Dart_NewByteBuffer(Dart_True());
2125 EXPECT(Dart_IsError(result));
2126 result = Dart_NewByteBuffer(byte_buffer);
2127 EXPECT(Dart_IsError(result));
2128 result = Dart_GetDataFromByteBuffer(Dart_False());
2129 EXPECT(Dart_IsError(result));
2130 result = Dart_GetDataFromByteBuffer(byte_array);
2131 EXPECT(Dart_IsError(result));
2132}
2133
2134static int kLength = 16;
2135
2136static void ByteDataNativeFunction(Dart_NativeArguments args) {
2137 Dart_EnterScope();
2138 Dart_Handle byte_data = Dart_NewTypedData(Dart_TypedData_kByteData, kLength);
2139 EXPECT_VALID(byte_data);
2140 EXPECT_EQ(Dart_TypedData_kByteData, Dart_GetTypeOfTypedData(byte_data));
2141 Dart_SetReturnValue(args, byte_data);
2142 Dart_ExitScope();
2143}
2144
2145static Dart_NativeFunction ByteDataNativeResolver(Dart_Handle name,
2146 int arg_count,
2147 bool* auto_setup_scope) {
2148 ASSERT(auto_setup_scope != NULL);
2149 *auto_setup_scope = true;
2150 return &ByteDataNativeFunction;
2151}
2152
2153TEST_CASE(DartAPI_ByteDataAccess) {
2154 const char* kScriptChars =
2155 "import 'dart:typed_data';\n"
2156 "class Expect {\n"
2157 " static equals(a, b) {\n"
2158 " if (a != b) {\n"
2159 " throw 'not equal. expected: $a, got: $b';\n"
2160 " }\n"
2161 " }\n"
2162 "}\n"
2163 "ByteData createByteData() native 'CreateByteData';"
2164 "ByteData main() {"
2165 " var length = 16;"
2166 " var a = createByteData();"
2167 " Expect.equals(length, a.lengthInBytes);"
2168 " for (int i = 0; i < length; i+=1) {"
2169 " a.setInt8(i, 0x42);"
2170 " }"
2171 " for (int i = 0; i < length; i+=2) {"
2172 " Expect.equals(0x4242, a.getInt16(i));"
2173 " }"
2174 " return a;"
2175 "}\n";
2176 // Create a test library and Load up a test script in it.
2177 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
2178
2179 Dart_Handle result =
2180 Dart_SetNativeResolver(lib, &ByteDataNativeResolver, NULL);
2181 EXPECT_VALID(result);
2182
2183 // Invoke 'main' function.
2184 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
2185 EXPECT_VALID(result);
2186}
2187
2188static const intptr_t kExtLength = 16;
2189static int8_t data[kExtLength] = {
2190 0x41, 0x42, 0x41, 0x42, 0x41, 0x42, 0x41, 0x42,
2191 0x41, 0x42, 0x41, 0x42, 0x41, 0x42, 0x41, 0x42,
2192};
2193
2194static void ExternalByteDataNativeFunction(Dart_NativeArguments args) {
2195 Dart_EnterScope();
2196 Dart_Handle external_byte_data =
2197 Dart_NewExternalTypedData(Dart_TypedData_kByteData, data, 16);
2198 EXPECT_VALID(external_byte_data);
2199 EXPECT_EQ(Dart_TypedData_kByteData,
2200 Dart_GetTypeOfTypedData(external_byte_data));
2201 Dart_SetReturnValue(args, external_byte_data);
2202 Dart_ExitScope();
2203}
2204
2205static Dart_NativeFunction ExternalByteDataNativeResolver(
2206 Dart_Handle name,
2207 int arg_count,
2208 bool* auto_setup_scope) {
2209 ASSERT(auto_setup_scope != NULL);
2210 *auto_setup_scope = true;
2211 return &ExternalByteDataNativeFunction;
2212}
2213
2214TEST_CASE(DartAPI_ExternalByteDataAccess) {
2215 // TODO(asiva): Once we have getInt16LE and getInt16BE support use the
2216 // appropriate getter instead of the host endian format used now.
2217 const char* kScriptChars =
2218 "import 'dart:typed_data';\n"
2219 "class Expect {\n"
2220 " static equals(a, b) {\n"
2221 " if (a != b) {\n"
2222 " throw 'not equal. expected: $a, got: $b';\n"
2223 " }\n"
2224 " }\n"
2225 "}\n"
2226 "ByteData createExternalByteData() native 'CreateExternalByteData';"
2227 "ByteData main() {"
2228 " var length = 16;"
2229 " var a = createExternalByteData();"
2230 " Expect.equals(length, a.lengthInBytes);"
2231 " for (int i = 0; i < length; i+=2) {"
2232 " Expect.equals(0x4241, a.getInt16(i, Endian.little));"
2233 " }"
2234 " for (int i = 0; i < length; i+=2) {"
2235 " a.setInt8(i, 0x24);"
2236 " a.setInt8(i + 1, 0x28);"
2237 " }"
2238 " for (int i = 0; i < length; i+=2) {"
2239 " Expect.equals(0x2824, a.getInt16(i, Endian.little));"
2240 " }"
2241 " return a;"
2242 "}\n";
2243 // Create a test library and Load up a test script in it.
2244 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
2245
2246 Dart_Handle result =
2247 Dart_SetNativeResolver(lib, &ExternalByteDataNativeResolver, NULL);
2248 EXPECT_VALID(result);
2249
2250 // Invoke 'main' function.
2251 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
2252 EXPECT_VALID(result);
2253
2254 for (intptr_t i = 0; i < kExtLength; i += 2) {
2255 EXPECT_EQ(0x24, data[i]);
2256 EXPECT_EQ(0x28, data[i + 1]);
2257 }
2258}
2259
2260static bool byte_data_finalizer_run = false;
2261void ByteDataFinalizer(void* isolate_data,
2262 Dart_WeakPersistentHandle handle,
2263 void* peer) {
2264 ASSERT(!byte_data_finalizer_run);
2265 free(peer);
2266 byte_data_finalizer_run = true;
2267}
2268
2269TEST_CASE(DartAPI_ExternalByteDataFinalizer) {
2270 // Check finalizer associated with the underlying array instead of the
2271 // wrapper.
2272 const char* kScriptChars =
2273 "var array;\n"
2274 "extractAndSaveArray(byteData) {\n"
2275 " array = byteData.buffer.asUint8List();\n"
2276 "}\n"
2277 "releaseArray() {\n"
2278 " array = null;\n"
2279 "}\n";
2280 // Create a test library and Load up a test script in it.
2281 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
2282
2283 {
2284 Dart_EnterScope();
2285
2286 const intptr_t kBufferSize = 100;
2287 void* buffer = malloc(kBufferSize);
2288 // The buffer becomes readable by Dart, so ensure it is initialized to
2289 // satisfy our eager MSAN check.
2290 memset(buffer, 0, kBufferSize);
2291 Dart_Handle byte_data = Dart_NewExternalTypedDataWithFinalizer(
2292 Dart_TypedData_kByteData, buffer, kBufferSize, buffer, kBufferSize,
2293 ByteDataFinalizer);
2294
2295 Dart_Handle result =
2296 Dart_Invoke(lib, NewString("extractAndSaveArray"), 1, &byte_data);
2297 EXPECT_VALID(result);
2298
2299 // ByteData wrapper is still reachable from the scoped handle.
2300 EXPECT(!byte_data_finalizer_run);
2301
2302 // The ByteData wrapper is now unreachable, but the underlying
2303 // ExternalUint8List is still alive.
2304 Dart_ExitScope();
2305 }
2306
2307 {
2308 TransitionNativeToVM transition(Thread::Current());
2309 GCTestHelper::CollectAllGarbage();
2310 }
2311
2312 EXPECT(!byte_data_finalizer_run);
2313
2314 Dart_Handle result = Dart_Invoke(lib, NewString("releaseArray"), 0, NULL);
2315 EXPECT_VALID(result);
2316
2317 {
2318 TransitionNativeToVM transition(Thread::Current());
2319 GCTestHelper::CollectAllGarbage();
2320 }
2321
2322 EXPECT(byte_data_finalizer_run);
2323}
2324
2325#ifndef PRODUCT
2326
2327static const intptr_t kOptExtLength = 16;
2328static int8_t opt_data[kOptExtLength] = {
2329 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
2330 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
2331};
2332
2333static void OptExternalByteDataNativeFunction(Dart_NativeArguments args) {
2334 Dart_EnterScope();
2335 Dart_Handle external_byte_data =
2336 Dart_NewExternalTypedData(Dart_TypedData_kByteData, opt_data, 16);
2337 EXPECT_VALID(external_byte_data);
2338 EXPECT_EQ(Dart_TypedData_kByteData,
2339 Dart_GetTypeOfTypedData(external_byte_data));
2340 Dart_SetReturnValue(args, external_byte_data);
2341 Dart_ExitScope();
2342}
2343
2344static Dart_NativeFunction OptExternalByteDataNativeResolver(
2345 Dart_Handle name,
2346 int arg_count,
2347 bool* auto_setup_scope) {
2348 ASSERT(auto_setup_scope != NULL);
2349 *auto_setup_scope = true;
2350 return &OptExternalByteDataNativeFunction;
2351}
2352
2353TEST_CASE(DartAPI_OptimizedExternalByteDataAccess) {
2354 const char* kScriptChars =
2355 "import 'dart:typed_data';\n"
2356 "class Expect {\n"
2357 " static equals(a, b) {\n"
2358 " if (a != b) {\n"
2359 " throw 'not equal. expected: $a, got: $b';\n"
2360 " }\n"
2361 " }\n"
2362 "}\n"
2363 "ByteData createExternalByteData() native 'CreateExternalByteData';"
2364 "access(ByteData a) {"
2365 " Expect.equals(0x04030201, a.getUint32(0, Endian.little));"
2366 " Expect.equals(0x08070605, a.getUint32(4, Endian.little));"
2367 " Expect.equals(0x0c0b0a09, a.getUint32(8, Endian.little));"
2368 " Expect.equals(0x100f0e0d, a.getUint32(12, Endian.little));"
2369 "}"
2370 "ByteData main() {"
2371 " var length = 16;"
2372 " var a = createExternalByteData();"
2373 " Expect.equals(length, a.lengthInBytes);"
2374 " for (int i = 0; i < 20; i++) {"
2375 " access(a);"
2376 " }"
2377 " return a;"
2378 "}\n";
2379 // Create a test library and Load up a test script in it.
2380 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
2381
2382 Dart_Handle result =
2383 Dart_SetNativeResolver(lib, &OptExternalByteDataNativeResolver, NULL);
2384 EXPECT_VALID(result);
2385
2386 // Invoke 'main' function.
2387 int old_oct = FLAG_optimization_counter_threshold;
2388 FLAG_optimization_counter_threshold = 5;
2389 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
2390 EXPECT_VALID(result);
2391 FLAG_optimization_counter_threshold = old_oct;
2392}
2393
2394#endif // !PRODUCT
2395
2396static void TestTypedDataDirectAccess() {
2397 Dart_Handle str = Dart_NewStringFromCString("junk");
2398 Dart_Handle byte_array = Dart_NewTypedData(Dart_TypedData_kUint8, 10);
2399 EXPECT_VALID(byte_array);
2400 Dart_Handle result;
2401 result = Dart_TypedDataAcquireData(byte_array, NULL, NULL, NULL);
2402 EXPECT_ERROR(result,
2403 "Dart_TypedDataAcquireData expects argument 'type'"
2404 " to be non-null.");
2405 Dart_TypedData_Type type;
2406 result = Dart_TypedDataAcquireData(byte_array, &type, NULL, NULL);
2407 EXPECT_ERROR(result,
2408 "Dart_TypedDataAcquireData expects argument 'data'"
2409 " to be non-null.");
2410 void* data;
2411 result = Dart_TypedDataAcquireData(byte_array, &type, &data, NULL);
2412 EXPECT_ERROR(result,
2413 "Dart_TypedDataAcquireData expects argument 'len'"
2414 " to be non-null.");
2415 intptr_t len;
2416 result = Dart_TypedDataAcquireData(Dart_Null(), &type, &data, &len);
2417 EXPECT_ERROR(result,
2418 "Dart_TypedDataAcquireData expects argument 'object'"
2419 " to be non-null.");
2420 result = Dart_TypedDataAcquireData(str, &type, &data, &len);
2421 EXPECT_ERROR(result,
2422 "Dart_TypedDataAcquireData expects argument 'object'"
2423 " to be of type 'TypedData'.");
2424
2425 result = Dart_TypedDataReleaseData(Dart_Null());
2426 EXPECT_ERROR(result,
2427 "Dart_TypedDataReleaseData expects argument 'object'"
2428 " to be non-null.");
2429 result = Dart_TypedDataReleaseData(str);
2430 EXPECT_ERROR(result,
2431 "Dart_TypedDataReleaseData expects argument 'object'"
2432 " to be of type 'TypedData'.");
2433}
2434
2435TEST_CASE(DartAPI_TypedDataDirectAccessUnverified) {
2436 FLAG_verify_acquired_data = false;
2437 TestTypedDataDirectAccess();
2438}
2439
2440TEST_CASE(DartAPI_TypedDataDirectAccessVerified) {
2441 FLAG_verify_acquired_data = true;
2442 TestTypedDataDirectAccess();
2443}
2444
2445static void TestDirectAccess(Dart_Handle lib,
2446 Dart_Handle array,
2447 Dart_TypedData_Type expected_type,
2448 bool is_external) {
2449 Dart_Handle result;
2450
2451 // Invoke the dart function that sets initial values.
2452 Dart_Handle dart_args[1];
2453 dart_args[0] = array;
2454 result = Dart_Invoke(lib, NewString("setMain"), 1, dart_args);
2455 EXPECT_VALID(result);
2456
2457 // Now Get a direct access to this typed data object and check it's contents.
2458 const int kLength = 10;
2459 Dart_TypedData_Type type;
2460 void* data;
2461 intptr_t len;
2462 result = Dart_TypedDataAcquireData(array, &type, &data, &len);
2463 EXPECT(!Thread::Current()->IsAtSafepoint());
2464 EXPECT_VALID(result);
2465 EXPECT_EQ(expected_type, type);
2466 EXPECT_EQ(kLength, len);
2467 int8_t* dataP = reinterpret_cast<int8_t*>(data);
2468 for (int i = 0; i < kLength; i++) {
2469 EXPECT_EQ(i, dataP[i]);
2470 }
2471
2472 // Now try allocating a string with outstanding Acquires and it should
2473 // return an error.
2474 result = NewString("We expect an error here");
2475 EXPECT_ERROR(result,
2476 "Internal Dart data pointers have been acquired, "
2477 "please release them using Dart_TypedDataReleaseData.");
2478
2479 // Now modify the values in the directly accessible array and then check
2480 // it we see the changes back in dart.
2481 for (int i = 0; i < kLength; i++) {
2482 dataP[i] += 10;
2483 }
2484
2485 // Release direct access to the typed data object.
2486 EXPECT(!Thread::Current()->IsAtSafepoint());
2487 result = Dart_TypedDataReleaseData(array);
2488 EXPECT_VALID(result);
2489
2490 // Invoke the dart function in order to check the modified values.
2491 result = Dart_Invoke(lib, NewString("testMain"), 1, dart_args);
2492 EXPECT_VALID(result);
2493}
2494
2495class BackgroundGCTask : public ThreadPool::Task {
2496 public:
2497 BackgroundGCTask(Isolate* isolate, Monitor* monitor, bool* done)
2498 : isolate_(isolate), monitor_(monitor), done_(done) {}
2499 virtual void Run() {
2500 Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
2501 for (intptr_t i = 0; i < 10; i++) {
2502 GCTestHelper::CollectAllGarbage();
2503 }
2504 Thread::ExitIsolateAsHelper();
2505 {
2506 MonitorLocker ml(monitor_);
2507 *done_ = true;
2508 ml.Notify();
2509 }
2510 }
2511
2512 private:
2513 Isolate* isolate_;
2514 Monitor* monitor_;
2515 bool* done_;
2516};
2517
2518static void TestTypedDataDirectAccess1() {
2519 const char* kScriptChars =
2520 "import 'dart:typed_data';\n"
2521 "class Expect {\n"
2522 " static equals(a, b) {\n"
2523 " if (a != b) {\n"
2524 " throw new Exception('not equal. expected: $a, got: $b');\n"
2525 " }\n"
2526 " }\n"
2527 "}\n"
2528 "void setMain(var a) {"
2529 " for (var i = 0; i < 10; i++) {"
2530 " a[i] = i;"
2531 " }"
2532 "}\n"
2533 "bool testMain(var list) {"
2534 " for (var i = 0; i < 10; i++) {"
2535 " Expect.equals((10 + i), list[i]);"
2536 " }\n"
2537 " return true;"
2538 "}\n"
2539 "List main() {"
2540 " var a = new Int8List(10);"
2541 " return a;"
2542 "}\n";
2543 // Create a test library and Load up a test script in it.
2544 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
2545
2546 Monitor monitor;
2547 bool done = false;
2548 Dart::thread_pool()->Run<BackgroundGCTask>(Isolate::Current(), &monitor,
2549 &done);
2550
2551 for (intptr_t i = 0; i < 10; i++) {
2552 // Test with an regular typed data object.
2553 Dart_Handle list_access_test_obj;
2554 list_access_test_obj = Dart_Invoke(lib, NewString("main"), 0, NULL);
2555 EXPECT_VALID(list_access_test_obj);
2556 TestDirectAccess(lib, list_access_test_obj, Dart_TypedData_kInt8, false);
2557
2558 // Test with an external typed data object.
2559 uint8_t data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2560 intptr_t data_length = ARRAY_SIZE(data);
2561 Dart_Handle ext_list_access_test_obj;
2562 ext_list_access_test_obj =
2563 Dart_NewExternalTypedData(Dart_TypedData_kUint8, data, data_length);
2564 EXPECT_VALID(ext_list_access_test_obj);
2565 TestDirectAccess(lib, ext_list_access_test_obj, Dart_TypedData_kUint8,
2566 true);
2567 }
2568
2569 {
2570 MonitorLocker ml(&monitor);
2571 while (!done) {
2572 ml.Wait();
2573 }
2574 }
2575}
2576
2577TEST_CASE(DartAPI_TypedDataDirectAccess1Unverified) {
2578 FLAG_verify_acquired_data = false;
2579 TestTypedDataDirectAccess1();
2580}
2581
2582TEST_CASE(DartAPI_TypedDataDirectAccess1Verified) {
2583 FLAG_verify_acquired_data = true;
2584 TestTypedDataDirectAccess1();
2585}
2586
2587static void TestTypedDataViewDirectAccess() {
2588 const char* kScriptChars =
2589 "import 'dart:typed_data';\n"
2590 "class Expect {\n"
2591 " static equals(a, b) {\n"
2592 " if (a != b) {\n"
2593 " throw 'not equal. expected: $a, got: $b';\n"
2594 " }\n"
2595 " }\n"
2596 "}\n"
2597 "void setMain(var list) {"
2598 " Expect.equals(10, list.length);"
2599 " for (var i = 0; i < 10; i++) {"
2600 " list[i] = i;"
2601 " }"
2602 "}\n"
2603 "bool testMain(var list) {"
2604 " Expect.equals(10, list.length);"
2605 " for (var i = 0; i < 10; i++) {"
2606 " Expect.equals((10 + i), list[i]);"
2607 " }"
2608 " return true;"
2609 "}\n"
2610 "List main() {"
2611 " var a = new Int8List(100);"
2612 " var view = new Int8List.view(a.buffer, 50, 10);"
2613 " return view;"
2614 "}\n";
2615 // Create a test library and Load up a test script in it.
2616 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
2617
2618 // Test with a typed data view object.
2619 Dart_Handle list_access_test_obj;
2620 list_access_test_obj = Dart_Invoke(lib, NewString("main"), 0, NULL);
2621 EXPECT_VALID(list_access_test_obj);
2622 TestDirectAccess(lib, list_access_test_obj, Dart_TypedData_kInt8, false);
2623}
2624
2625TEST_CASE(DartAPI_TypedDataViewDirectAccessUnverified) {
2626 FLAG_verify_acquired_data = false;
2627 TestTypedDataViewDirectAccess();
2628}
2629
2630TEST_CASE(DartAPI_TypedDataViewDirectAccessVerified) {
2631 FLAG_verify_acquired_data = true;
2632 TestTypedDataViewDirectAccess();
2633}
2634
2635static void TestByteDataDirectAccess() {
2636 const char* kScriptChars =
2637 "import 'dart:typed_data';\n"
2638 "class Expect {\n"
2639 " static equals(a, b) {\n"
2640 " if (a != b) {\n"
2641 " throw 'not equal. expected: $a, got: $b';\n"
2642 " }\n"
2643 " }\n"
2644 "}\n"
2645 "void setMain(var list) {"
2646 " Expect.equals(10, list.length);"
2647 " for (var i = 0; i < 10; i++) {"
2648 " list.setInt8(i, i);"
2649 " }"
2650 "}\n"
2651 "bool testMain(var list) {"
2652 " Expect.equals(10, list.length);"
2653 " for (var i = 0; i < 10; i++) {"
2654 " Expect.equals((10 + i), list.getInt8(i));"
2655 " }"
2656 " return true;"
2657 "}\n"
2658 "ByteData main() {"
2659 " var a = new Int8List(100);"
2660 " var view = new ByteData.view(a.buffer, 50, 10);"
2661 " return view;"
2662 "}\n";
2663 // Create a test library and Load up a test script in it.
2664 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
2665
2666 // Test with a typed data view object.
2667 Dart_Handle list_access_test_obj;
2668 list_access_test_obj = Dart_Invoke(lib, NewString("main"), 0, NULL);
2669 EXPECT_VALID(list_access_test_obj);
2670 TestDirectAccess(lib, list_access_test_obj, Dart_TypedData_kByteData, false);
2671}
2672
2673TEST_CASE(DartAPI_ByteDataDirectAccessUnverified) {
2674 FLAG_verify_acquired_data = false;
2675 TestByteDataDirectAccess();
2676}
2677
2678TEST_CASE(DartAPI_ByteDataDirectAccessVerified) {
2679 FLAG_verify_acquired_data = true;
2680 TestByteDataDirectAccess();
2681}
2682
2683static void ExternalTypedDataAccessTests(Dart_Handle obj,
2684 Dart_TypedData_Type expected_type,
2685 uint8_t data[],
2686 intptr_t data_length) {
2687 EXPECT_VALID(obj);
2688 EXPECT_EQ(expected_type, Dart_GetTypeOfExternalTypedData(obj));
2689 EXPECT(Dart_IsList(obj));
2690
2691 void* raw_data = NULL;
2692 intptr_t len;
2693 Dart_TypedData_Type type;
2694 EXPECT_VALID(Dart_TypedDataAcquireData(obj, &type, &raw_data, &len));
2695 EXPECT(raw_data == data);
2696 EXPECT_EQ(data_length, len);
2697 EXPECT_EQ(expected_type, type);
2698 EXPECT_VALID(Dart_TypedDataReleaseData(obj));
2699
2700 intptr_t list_length = 0;
2701 EXPECT_VALID(Dart_ListLength(obj, &list_length));
2702 EXPECT_EQ(data_length, list_length);
2703
2704 // Load and check values from underlying array and API.
2705 for (intptr_t i = 0; i < list_length; ++i) {
2706 EXPECT_EQ(11 * i, data[i]);
2707 Dart_Handle elt = Dart_ListGetAt(obj, i);
2708 EXPECT_VALID(elt);
2709 int64_t value = 0;
2710 EXPECT_VALID(Dart_IntegerToInt64(elt, &value));
2711 EXPECT_EQ(data[i], value);
2712 }
2713
2714 // Write values through the underlying array.
2715 for (intptr_t i = 0; i < data_length; ++i) {
2716 data[i] *= 2;
2717 }
2718 // Read them back through the API.
2719 for (intptr_t i = 0; i < list_length; ++i) {
2720 Dart_Handle elt = Dart_ListGetAt(obj, i);
2721 EXPECT_VALID(elt);
2722 int64_t value = 0;
2723 EXPECT_VALID(Dart_IntegerToInt64(elt, &value));
2724 EXPECT_EQ(22 * i, value);
2725 }
2726
2727 // Write values through the API.
2728 for (intptr_t i = 0; i < list_length; ++i) {
2729 Dart_Handle value = Dart_NewInteger(33 * i);
2730 EXPECT_VALID(value);
2731 EXPECT_VALID(Dart_ListSetAt(obj, i, value));
2732 }
2733 // Read them back through the underlying array.
2734 for (intptr_t i = 0; i < data_length; ++i) {
2735 EXPECT_EQ(33 * i, data[i]);
2736 }
2737}
2738
2739TEST_CASE(DartAPI_ExternalTypedDataAccess) {
2740 uint8_t data[] = {0, 11, 22, 33, 44, 55, 66, 77};
2741 intptr_t data_length = ARRAY_SIZE(data);
2742
2743 Dart_Handle obj =
2744 Dart_NewExternalTypedData(Dart_TypedData_kUint8, data, data_length);
2745 ExternalTypedDataAccessTests(obj, Dart_TypedData_kUint8, data, data_length);
2746}
2747
2748TEST_CASE(DartAPI_ExternalClampedTypedDataAccess) {
2749 uint8_t data[] = {0, 11, 22, 33, 44, 55, 66, 77};
2750 intptr_t data_length = ARRAY_SIZE(data);
2751
2752 Dart_Handle obj = Dart_NewExternalTypedData(Dart_TypedData_kUint8Clamped,
2753 data, data_length);
2754 ExternalTypedDataAccessTests(obj, Dart_TypedData_kUint8Clamped, data,
2755 data_length);
2756}
2757
2758TEST_CASE(DartAPI_ExternalUint8ClampedArrayAccess) {
2759 const char* kScriptChars =
2760 "testClamped(List a) {\n"
2761 " if (a[1] != 11) return false;\n"
2762 " a[1] = 3;\n"
2763 " if (a[1] != 3) return false;\n"
2764 " a[1] = -12;\n"
2765 " if (a[1] != 0) return false;\n"
2766 " a[1] = 1200;\n"
2767 " if (a[1] != 255) return false;\n"
2768 " return true;\n"
2769 "}\n";
2770
2771 uint8_t data[] = {0, 11, 22, 33, 44, 55, 66, 77};
2772 intptr_t data_length = ARRAY_SIZE(data);
2773 Dart_Handle obj = Dart_NewExternalTypedData(Dart_TypedData_kUint8Clamped,
2774 data, data_length);
2775 EXPECT_VALID(obj);
2776 Dart_Handle result;
2777 // Create a test library and Load up a test script in it.
2778 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
2779 Dart_Handle args[1];
2780 args[0] = obj;
2781 result = Dart_Invoke(lib, NewString("testClamped"), 1, args);
2782
2783 // Check that result is true.
2784 EXPECT_VALID(result);
2785 EXPECT(Dart_IsBoolean(result));
2786 bool value = false;
2787 result = Dart_BooleanValue(result, &value);
2788 EXPECT_VALID(result);
2789 EXPECT(value);
2790}
2791
2792static void NopCallback(void* isolate_callback_data,
2793 Dart_WeakPersistentHandle handle,
2794 void* peer) {}
2795static void NopCallback(void* isolate_callback_data, void* peer) {}
2796
2797static void UnreachedCallback(void* isolate_callback_data,
2798 Dart_WeakPersistentHandle handle,
2799 void* peer) {
2800 UNREACHABLE();
2801}
2802static void UnreachedCallback(void* isolate_callback_data, void* peer) {
2803 UNREACHABLE();
2804}
2805
2806static void ExternalTypedDataFinalizer(void* isolate_callback_data,
2807 Dart_WeakPersistentHandle handle,
2808 void* peer) {
2809 *static_cast<int*>(peer) = 42;
2810}
2811
2812TEST_CASE(DartAPI_ExternalTypedDataCallback) {
2813 int peer = 0;
2814 {
2815 Dart_EnterScope();
2816 uint8_t data[] = {1, 2, 3, 4};
2817 Dart_Handle obj = Dart_NewExternalTypedDataWithFinalizer(
2818 Dart_TypedData_kUint8, data, ARRAY_SIZE(data), &peer, sizeof(data),
2819 ExternalTypedDataFinalizer);
2820 EXPECT_VALID(obj);
2821 Dart_ExitScope();
2822 }
2823 {
2824 TransitionNativeToVM transition(thread);
2825 EXPECT(peer == 0);
2826 GCTestHelper::CollectOldSpace();
2827 EXPECT(peer == 0);
2828 GCTestHelper::CollectNewSpace();
2829 EXPECT(peer == 42);
2830 }
2831}
2832
2833static void SlowFinalizer(void* isolate_callback_data, void* peer) {
2834 OS::Sleep(10);
2835 intptr_t* count = reinterpret_cast<intptr_t*>(peer);
2836 (*count)++;
2837}
2838
2839TEST_CASE(DartAPI_SlowFinalizer) {
2840 intptr_t count = 0;
2841 for (intptr_t i = 0; i < 10; i++) {
2842 Dart_EnterScope();
2843 Dart_Handle str1 = Dart_NewStringFromCString("Live fast");
2844 Dart_NewFinalizableHandle(str1, &count, 0, SlowFinalizer);
2845 Dart_Handle str2 = Dart_NewStringFromCString("Die young");
2846 Dart_NewFinalizableHandle(str2, &count, 0, SlowFinalizer);
2847 Dart_ExitScope();
2848
2849 {
2850 TransitionNativeToVM transition(thread);
2851 GCTestHelper::CollectAllGarbage();
2852 }
2853 }
2854
2855 EXPECT_EQ(20, count);
2856}
2857
2858static void SlowWeakPersistentHandle(void* isolate_callback_data,
2859 Dart_WeakPersistentHandle handle,
2860 void* peer) {
2861 OS::Sleep(10);
2862 intptr_t* count = reinterpret_cast<intptr_t*>(peer);
2863 (*count)++;
2864}
2865
2866TEST_CASE(DartAPI_SlowWeakPersistenhandle) {
2867 intptr_t count = 0;
2868 for (intptr_t i = 0; i < 10; i++) {
2869 Dart_EnterScope();
2870 Dart_Handle str1 = Dart_NewStringFromCString("Live fast");
2871 Dart_NewWeakPersistentHandle(str1, &count, 0, SlowWeakPersistentHandle);
2872 Dart_Handle str2 = Dart_NewStringFromCString("Die young");
2873 Dart_NewWeakPersistentHandle(str2, &count, 0, SlowWeakPersistentHandle);
2874 Dart_ExitScope();
2875
2876 {
2877 TransitionNativeToVM transition(thread);
2878 GCTestHelper::CollectAllGarbage();
2879 }
2880 }
2881
2882 EXPECT_EQ(20, count);
2883}
2884
2885static void CheckFloat32x4Data(Dart_Handle obj) {
2886 void* raw_data = NULL;
2887 intptr_t len;
2888 Dart_TypedData_Type type;
2889 EXPECT_VALID(Dart_TypedDataAcquireData(obj, &type, &raw_data, &len));
2890 EXPECT_EQ(Dart_TypedData_kFloat32x4, type);
2891 EXPECT_EQ(len, 10);
2892 float* float_data = reinterpret_cast<float*>(raw_data);
2893 for (int i = 0; i < len * 4; i++) {
2894 EXPECT_EQ(0.0, float_data[i]);
2895 }
2896 EXPECT_VALID(Dart_TypedDataReleaseData(obj));
2897}
2898
2899TEST_CASE(DartAPI_Float32x4List) {
2900 const char* kScriptChars =
2901 "import 'dart:typed_data';\n"
2902 "Float32x4List float32x4() {\n"
2903 " return new Float32x4List(10);\n"
2904 "}\n";
2905 // Create a test library and Load up a test script in it.
2906 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
2907
2908 Dart_Handle obj = Dart_Invoke(lib, NewString("float32x4"), 0, NULL);
2909 EXPECT_VALID(obj);
2910 CheckFloat32x4Data(obj);
2911
2912 obj = Dart_NewTypedData(Dart_TypedData_kFloat32x4, 10);
2913 EXPECT_VALID(obj);
2914 CheckFloat32x4Data(obj);
2915
2916 int peer = 0;
2917 float data[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
2918 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
2919 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
2920 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
2921 // Push a scope so that we can collect the local handle created as part of
2922 // Dart_NewExternalTypedData.
2923 Dart_EnterScope();
2924 {
2925 Dart_Handle lcl = Dart_NewExternalTypedDataWithFinalizer(
2926 Dart_TypedData_kFloat32x4, data, 10, &peer, sizeof(data),
2927 ExternalTypedDataFinalizer);
2928 CheckFloat32x4Data(lcl);
2929 }
2930 Dart_ExitScope();
2931 {
2932 TransitionNativeToVM transition(thread);
2933 GCTestHelper::CollectNewSpace();
2934 EXPECT(peer == 42);
2935 }
2936}
2937
2938// Unit test for entering a scope, creating a local handle and exiting
2939// the scope.
2940VM_UNIT_TEST_CASE(DartAPI_EnterExitScope) {
2941 TestIsolateScope __test_isolate__;
2942
2943 Thread* thread = Thread::Current();
2944 EXPECT(thread != NULL);
2945 ApiLocalScope* scope = thread->api_top_scope();
2946 Dart_EnterScope();
2947 {
2948 EXPECT(thread->api_top_scope() != NULL);
2949 TransitionNativeToVM transition(thread);
2950 HANDLESCOPE(thread);
2951 String& str1 = String::Handle();
2952 str1 = String::New("Test String");
2953 Dart_Handle ref = Api::NewHandle(thread, str1.raw());
2954 String& str2 = String::Handle();
2955 str2 ^= Api::UnwrapHandle(ref);
2956 EXPECT(str1.Equals(str2));
2957 }
2958 Dart_ExitScope();
2959 EXPECT(scope == thread->api_top_scope());
2960}
2961
2962// Unit test for creating and deleting persistent handles.
2963VM_UNIT_TEST_CASE(DartAPI_PersistentHandles) {
2964 const char* kTestString1 = "Test String1";
2965 const char* kTestString2 = "Test String2";
2966 TestCase::CreateTestIsolate();
2967 Thread* thread = Thread::Current();
2968 Isolate* isolate = thread->isolate();
2969 EXPECT(isolate != NULL);
2970 ApiState* state = isolate->group()->api_state();
2971 EXPECT(state != NULL);
2972 ApiLocalScope* scope = thread->api_top_scope();
2973
2974 const intptr_t handle_count_start = state->CountPersistentHandles();
2975
2976 Dart_PersistentHandle handles[2000];
2977 Dart_EnterScope();
2978 {
2979 CHECK_API_SCOPE(thread);
2980 Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
2981 for (int i = 0; i < 1000; i++) {
2982 handles[i] = Dart_NewPersistentHandle(ref1);
2983 }
2984 Dart_EnterScope();
2985 Dart_Handle ref2 = Dart_NewStringFromCString(kTestString2);
2986 for (int i = 1000; i < 2000; i++) {
2987 handles[i] = Dart_NewPersistentHandle(ref2);
2988 }
2989 for (int i = 500; i < 1500; i++) {
2990 Dart_DeletePersistentHandle(handles[i]);
2991 }
2992 for (int i = 500; i < 1000; i++) {
2993 handles[i] = Dart_NewPersistentHandle(ref2);
2994 }
2995 for (int i = 1000; i < 1500; i++) {
2996 handles[i] = Dart_NewPersistentHandle(ref1);
2997 }
2998 Dart_ExitScope();
2999 }
3000 Dart_ExitScope();
3001 {
3002 TransitionNativeToVM transition(thread);
3003 StackZone zone(thread);
3004 HANDLESCOPE(thread);
3005 for (int i = 0; i < 500; i++) {
3006 String& str = String::Handle();
3007 str ^= PersistentHandle::Cast(handles[i])->raw();
3008 EXPECT(str.Equals(kTestString1));
3009 }
3010 for (int i = 500; i < 1000; i++) {
3011 String& str = String::Handle();
3012 str ^= PersistentHandle::Cast(handles[i])->raw();
3013 EXPECT(str.Equals(kTestString2));
3014 }
3015 for (int i = 1000; i < 1500; i++) {
3016 String& str = String::Handle();
3017 str ^= PersistentHandle::Cast(handles[i])->raw();
3018 EXPECT(str.Equals(kTestString1));
3019 }
3020 for (int i = 1500; i < 2000; i++) {
3021 String& str = String::Handle();
3022 str ^= PersistentHandle::Cast(handles[i])->raw();
3023 EXPECT(str.Equals(kTestString2));
3024 }
3025 }
3026 EXPECT(scope == thread->api_top_scope());
3027 EXPECT_EQ(handle_count_start + 2000, state->CountPersistentHandles());
3028 Dart_ShutdownIsolate();
3029}
3030
3031// Test that we are able to create a persistent handle from a
3032// persistent handle.
3033VM_UNIT_TEST_CASE(DartAPI_NewPersistentHandle_FromPersistentHandle) {
3034 TestIsolateScope __test_isolate__;
3035
3036 Isolate* isolate = Isolate::Current();
3037 EXPECT(isolate != NULL);
3038 ApiState* state = isolate->group()->api_state();
3039 EXPECT(state != NULL);
3040 Thread* thread = Thread::Current();
3041 CHECK_API_SCOPE(thread);
3042
3043 // Start with a known persistent handle.
3044 Dart_PersistentHandle obj1 = Dart_NewPersistentHandle(Dart_True());
3045 EXPECT(state->IsValidPersistentHandle(obj1));
3046
3047 // And use it to allocate a second persistent handle.
3048 Dart_Handle obj2 = Dart_HandleFromPersistent(obj1);
3049 Dart_PersistentHandle obj3 = Dart_NewPersistentHandle(obj2);
3050 EXPECT(state->IsValidPersistentHandle(obj3));
3051
3052 // Make sure that the value transferred.
3053 Dart_Handle obj4 = Dart_HandleFromPersistent(obj3);
3054 EXPECT(Dart_IsBoolean(obj4));
3055 bool value = false;
3056 Dart_Handle result = Dart_BooleanValue(obj4, &value);
3057 EXPECT_VALID(result);
3058 EXPECT(value);
3059}
3060
3061// Test that we can assign to a persistent handle.
3062VM_UNIT_TEST_CASE(DartAPI_AssignToPersistentHandle) {
3063 const char* kTestString1 = "Test String1";
3064 const char* kTestString2 = "Test String2";
3065 TestIsolateScope __test_isolate__;
3066
3067 Thread* T = Thread::Current();
3068 CHECK_API_SCOPE(T);
3069 Isolate* isolate = T->isolate();
3070 EXPECT(isolate != NULL);
3071 ApiState* state = isolate->group()->api_state();
3072 EXPECT(state != NULL);
3073
3074 // Start with a known persistent handle.
3075 Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
3076 Dart_PersistentHandle obj = Dart_NewPersistentHandle(ref1);
3077 EXPECT(state->IsValidPersistentHandle(obj));
3078 {
3079 TransitionNativeToVM transition(T);
3080 HANDLESCOPE(T);
3081 String& str = String::Handle();
3082 str ^= PersistentHandle::Cast(obj)->raw();
3083 EXPECT(str.Equals(kTestString1));
3084 }
3085
3086 // Now create another local handle and assign it to the persistent handle.
3087 Dart_Handle ref2 = Dart_NewStringFromCString(kTestString2);
3088 Dart_SetPersistentHandle(obj, ref2);
3089 {
3090 TransitionNativeToVM transition(T);
3091 HANDLESCOPE(T);
3092 String& str = String::Handle();
3093 str ^= PersistentHandle::Cast(obj)->raw();
3094 EXPECT(str.Equals(kTestString2));
3095 }
3096
3097 // Now assign Null to the persistent handle and check.
3098 Dart_SetPersistentHandle(obj, Dart_Null());
3099 EXPECT(Dart_IsNull(obj));
3100}
3101
3102static Dart_Handle AllocateNewString(const char* c_str) {
3103 Thread* thread = Thread::Current();
3104 TransitionNativeToVM transition(thread);
3105 return Api::NewHandle(thread, String::New(c_str, Heap::kNew));
3106}
3107
3108static Dart_Handle AllocateOldString(const char* c_str) {
3109 Thread* thread = Thread::Current();
3110 TransitionNativeToVM transition(thread);
3111 return Api::NewHandle(thread, String::New(c_str, Heap::kOld));
3112}
3113
3114static Dart_Handle AsHandle(Dart_PersistentHandle weak) {
3115 return Dart_HandleFromPersistent(weak);
3116}
3117
3118static Dart_Handle AsHandle(Dart_WeakPersistentHandle weak) {
3119 return Dart_HandleFromWeakPersistent(weak);
3120}
3121
3122static Dart_WeakPersistentHandle weak_new_ref = NULL;
3123static Dart_WeakPersistentHandle weak_old_ref = NULL;
3124
3125static void WeakPersistentHandleCallback(void* isolate_callback_data,
3126 Dart_WeakPersistentHandle handle,
3127 void* peer) {
3128 if (handle == weak_new_ref) {
3129 weak_new_ref = NULL;
3130 } else if (handle == weak_old_ref) {
3131 weak_old_ref = NULL;
3132 }
3133}
3134
3135TEST_CASE(DartAPI_WeakPersistentHandle) {
3136 // GCs due to allocations or weak handle creation can cause early promotion
3137 // and interfer with the scenario this test is verifying.
3138 NoHeapGrowthControlScope force_growth;
3139
3140 Dart_Handle local_new_ref = Dart_Null();
3141 weak_new_ref = Dart_NewWeakPersistentHandle(local_new_ref, NULL, 0,
3142 WeakPersistentHandleCallback);
3143
3144 Dart_Handle local_old_ref = Dart_Null();
3145 weak_old_ref = Dart_NewWeakPersistentHandle(local_old_ref, NULL, 0,
3146 WeakPersistentHandleCallback);
3147
3148 {
3149 Dart_EnterScope();
3150
3151 // Create an object in new space.
3152 Dart_Handle new_ref = AllocateNewString("new string");
3153 EXPECT_VALID(new_ref);
3154
3155 // Create an object in old space.
3156 Dart_Handle old_ref = AllocateOldString("old string");
3157 EXPECT_VALID(old_ref);
3158
3159 // Create a weak ref to the new space object.
3160 weak_new_ref = Dart_NewWeakPersistentHandle(new_ref, NULL, 0,
3161 WeakPersistentHandleCallback);
3162 EXPECT_VALID(AsHandle(weak_new_ref));
3163 EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
3164
3165 // Create a weak ref to the old space object.
3166 weak_old_ref = Dart_NewWeakPersistentHandle(old_ref, NULL, 0,
3167 WeakPersistentHandleCallback);
3168 EXPECT_VALID(AsHandle(weak_old_ref));
3169 EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
3170
3171 {
3172 TransitionNativeToVM transition(thread);
3173 // Garbage collect new space.
3174 GCTestHelper::CollectNewSpace();
3175 }
3176
3177 // Nothing should be invalidated or cleared.
3178 EXPECT_VALID(new_ref);
3179 EXPECT(!Dart_IsNull(new_ref));
3180 EXPECT_VALID(old_ref);
3181 EXPECT(!Dart_IsNull(old_ref));
3182
3183 EXPECT_VALID(AsHandle(weak_new_ref));
3184 EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
3185 EXPECT(Dart_IdentityEquals(new_ref, AsHandle(weak_new_ref)));
3186
3187 EXPECT_VALID(AsHandle(weak_old_ref));
3188 EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
3189 EXPECT(Dart_IdentityEquals(old_ref, AsHandle(weak_old_ref)));
3190
3191 {
3192 TransitionNativeToVM transition(thread);
3193 // Garbage collect old space.
3194 GCTestHelper::CollectOldSpace();
3195 }
3196
3197 // Nothing should be invalidated or cleared.
3198 EXPECT_VALID(new_ref);
3199 EXPECT(!Dart_IsNull(new_ref));
3200 EXPECT_VALID(old_ref);
3201 EXPECT(!Dart_IsNull(old_ref));
3202
3203 EXPECT_VALID(AsHandle(weak_new_ref));
3204 EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
3205 EXPECT(Dart_IdentityEquals(new_ref, AsHandle(weak_new_ref)));
3206
3207 EXPECT_VALID(AsHandle(weak_old_ref));
3208 EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
3209 EXPECT(Dart_IdentityEquals(old_ref, AsHandle(weak_old_ref)));
3210
3211 // Delete local (strong) references.
3212 Dart_ExitScope();
3213 }
3214
3215 {
3216 TransitionNativeToVM transition(thread);
3217 // Garbage collect new space again.
3218 GCTestHelper::CollectNewSpace();
3219 }
3220
3221 {
3222 Dart_EnterScope();
3223 // Weak ref to new space object should now be cleared.
3224 EXPECT(weak_new_ref == NULL);
3225 EXPECT_VALID(AsHandle(weak_old_ref));
3226 EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
3227 Dart_ExitScope();
3228 }
3229
3230 {
3231 TransitionNativeToVM transition(thread);
3232 // Garbage collect old space again.
3233 GCTestHelper::CollectOldSpace();
3234 }
3235
3236 {
3237 Dart_EnterScope();
3238 // Weak ref to old space object should now be cleared.
3239 EXPECT(weak_new_ref == NULL);
3240 EXPECT(weak_old_ref == NULL);
3241 Dart_ExitScope();
3242 }
3243
3244 {
3245 TransitionNativeToVM transition(thread);
3246 // Garbage collect one last time to revisit deleted handles.
3247 GCTestHelper::CollectAllGarbage();
3248 }
3249}
3250
3251static Dart_FinalizableHandle finalizable_new_ref = nullptr;
3252static void* finalizable_new_ref_peer = 0;
3253static Dart_FinalizableHandle finalizable_old_ref = nullptr;
3254static void* finalizable_old_ref_peer = 0;
3255
3256static void FinalizableHandleCallback(void* isolate_callback_data, void* peer) {
3257 if (peer == finalizable_new_ref_peer) {
3258 finalizable_new_ref_peer = 0;
3259 finalizable_new_ref = nullptr;
3260 } else if (peer == finalizable_old_ref_peer) {
3261 finalizable_old_ref_peer = 0;
3262 finalizable_old_ref = nullptr;
3263 }
3264}
3265
3266TEST_CASE(DartAPI_FinalizableHandle) {
3267 // GCs due to allocations or weak handle creation can cause early promotion
3268 // and interfer with the scenario this test is verifying.
3269 NoHeapGrowthControlScope force_growth;
3270
3271 void* peer = reinterpret_cast<void*>(0);
3272 Dart_Handle local_new_ref = Dart_Null();
3273 finalizable_new_ref = Dart_NewFinalizableHandle(local_new_ref, peer, 0,
3274 FinalizableHandleCallback);
3275 finalizable_new_ref_peer = peer;
3276
3277 peer = reinterpret_cast<void*>(1);
3278 Dart_Handle local_old_ref = Dart_Null();
3279 finalizable_old_ref = Dart_NewFinalizableHandle(local_old_ref, peer, 0,
3280 FinalizableHandleCallback);
3281 finalizable_old_ref_peer = peer;
3282
3283 {
3284 Dart_EnterScope();
3285
3286 // Create an object in new space.
3287 Dart_Handle new_ref = AllocateNewString("new string");
3288 EXPECT_VALID(new_ref);
3289
3290 // Create an object in old space.
3291 Dart_Handle old_ref = AllocateOldString("old string");
3292 EXPECT_VALID(old_ref);
3293
3294 // Create a weak ref to the new space object.
3295 peer = reinterpret_cast<void*>(2);
3296 finalizable_new_ref =
3297 Dart_NewFinalizableHandle(new_ref, peer, 0, FinalizableHandleCallback);
3298 finalizable_new_ref_peer = peer;
3299
3300 // Create a weak ref to the old space object.
3301 peer = reinterpret_cast<void*>(3);
3302 finalizable_old_ref =
3303 Dart_NewFinalizableHandle(old_ref, peer, 0, FinalizableHandleCallback);
3304 finalizable_old_ref_peer = peer;
3305
3306 {
3307 TransitionNativeToVM transition(thread);
3308 // Garbage collect new space.
3309 GCTestHelper::CollectNewSpace();
3310 }
3311
3312 // Nothing should be invalidated or cleared.
3313 EXPECT_VALID(new_ref);
3314 EXPECT(!Dart_IsNull(new_ref));
3315 EXPECT_VALID(old_ref);
3316 EXPECT(!Dart_IsNull(old_ref));
3317
3318 {
3319 TransitionNativeToVM transition(thread);
3320 // Garbage collect old space.
3321 GCTestHelper::CollectOldSpace();
3322 }
3323
3324 // Nothing should be invalidated or cleared.
3325 EXPECT_VALID(new_ref);
3326 EXPECT(!Dart_IsNull(new_ref));
3327 EXPECT_VALID(old_ref);
3328 EXPECT(!Dart_IsNull(old_ref));
3329
3330 // Delete local (strong) references.
3331 Dart_ExitScope();
3332 }
3333
3334 {
3335 TransitionNativeToVM transition(thread);
3336 // Garbage collect new space again.
3337 GCTestHelper::CollectNewSpace();
3338 }
3339
3340 {
3341 Dart_EnterScope();
3342 // Weak ref to new space object should now be cleared.
3343 EXPECT(finalizable_new_ref == nullptr);
3344 Dart_ExitScope();
3345 }
3346
3347 {
3348 TransitionNativeToVM transition(thread);
3349 // Garbage collect old space again.
3350 GCTestHelper::CollectOldSpace();
3351 }
3352
3353 {
3354 Dart_EnterScope();
3355 // Weak ref to old space object should now be cleared.
3356 EXPECT(finalizable_new_ref == nullptr);
3357 EXPECT(finalizable_old_ref == nullptr);
3358 Dart_ExitScope();
3359 }
3360
3361 {
3362 TransitionNativeToVM transition(thread);
3363 GCTestHelper::CollectAllGarbage();
3364 }
3365}
3366
3367TEST_CASE(DartAPI_WeakPersistentHandleErrors) {
3368 Dart_EnterScope();
3369
3370 // NULL callback.
3371 Dart_Handle obj1 = NewString("new string");
3372 EXPECT_VALID(obj1);
3373 Dart_WeakPersistentHandle ref1 =
3374 Dart_NewWeakPersistentHandle(obj1, NULL, 0, NULL);
3375 EXPECT_EQ(ref1, static_cast<void*>(NULL));
3376
3377 // Immediate object.
3378 Dart_Handle obj2 = Dart_NewInteger(0);
3379 EXPECT_VALID(obj2);
3380 Dart_WeakPersistentHandle ref2 =
3381 Dart_NewWeakPersistentHandle(obj2, NULL, 0, WeakPersistentHandleCallback);
3382 EXPECT_EQ(ref2, static_cast<void*>(NULL));
3383
3384 Dart_ExitScope();
3385}
3386
3387TEST_CASE(DartAPI_FinalizableHandleErrors) {
3388 Dart_EnterScope();
3389
3390 // NULL callback.
3391 Dart_Handle obj1 = NewString("new string");
3392 EXPECT_VALID(obj1);
3393 Dart_FinalizableHandle ref1 =
3394 Dart_NewFinalizableHandle(obj1, nullptr, 0, nullptr);
3395 EXPECT_EQ(ref1, static_cast<void*>(nullptr));
3396
3397 // Immediate object.
3398 Dart_Handle obj2 = Dart_NewInteger(0);
3399 EXPECT_VALID(obj2);
3400 Dart_FinalizableHandle ref2 =
3401 Dart_NewFinalizableHandle(obj2, nullptr, 0, FinalizableHandleCallback);
3402 EXPECT_EQ(ref2, static_cast<void*>(nullptr));
3403
3404 Dart_ExitScope();
3405}
3406
3407static Dart_PersistentHandle persistent_handle1;
3408static Dart_WeakPersistentHandle weak_persistent_handle2;
3409static Dart_WeakPersistentHandle weak_persistent_handle3;
3410
3411static void WeakPersistentHandlePeerCleanupFinalizer(
3412 void* isolate_callback_data,
3413 Dart_WeakPersistentHandle handle,
3414 void* peer) {
3415 Dart_DeletePersistentHandle(persistent_handle1);
3416 Dart_DeleteWeakPersistentHandle(weak_persistent_handle2);
3417 *static_cast<int*>(peer) = 42;
3418}
3419
3420static void WeakPersistentHandleNoopCallback(void* isolate_callback_data,
3421 Dart_WeakPersistentHandle handle,
3422 void* peer) {}
3423
3424TEST_CASE(DartAPI_WeakPersistentHandleCleanupFinalizer) {
3425 Heap* heap = Isolate::Current()->heap();
3426
3427 const char* kTestString1 = "Test String1";
3428 Dart_EnterScope();
3429 CHECK_API_SCOPE(thread);
3430 Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
3431 persistent_handle1 = Dart_NewPersistentHandle(ref1);
3432 Dart_Handle ref2 = Dart_NewStringFromCString(kTestString1);
3433 int peer2 = 0;
3434 weak_persistent_handle2 = Dart_NewWeakPersistentHandle(
3435 ref2, &peer2, 0, WeakPersistentHandleNoopCallback);
3436 int peer3 = 0;
3437 {
3438 Dart_EnterScope();
3439 Dart_Handle ref3 = Dart_NewStringFromCString(kTestString1);
3440 weak_persistent_handle3 = Dart_NewWeakPersistentHandle(
3441 ref3, &peer3, 0, WeakPersistentHandlePeerCleanupFinalizer);
3442 Dart_ExitScope();
3443 }
3444 {
3445 TransitionNativeToVM transition(thread);
3446 GCTestHelper::CollectAllGarbage();
3447 EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
3448 EXPECT(peer3 == 42);
3449 }
3450 Dart_ExitScope();
3451}
3452
3453static Dart_FinalizableHandle finalizable_handle3;
3454
3455static void FinalizableHandlePeerCleanupFinalizer(void* isolate_callback_data,
3456 void* peer) {
3457 Dart_DeletePersistentHandle(persistent_handle1);
3458 Dart_DeleteWeakPersistentHandle(weak_persistent_handle2);
3459 *static_cast<int*>(peer) = 42;
3460}
3461
3462TEST_CASE(DartAPI_FinalizableHandleCleanupFinalizer) {
3463 Heap* heap = Isolate::Current()->heap();
3464
3465 const char* kTestString1 = "Test String1";
3466 Dart_EnterScope();
3467 CHECK_API_SCOPE(thread);
3468 Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
3469 persistent_handle1 = Dart_NewPersistentHandle(ref1);
3470 Dart_Handle ref2 = Dart_NewStringFromCString(kTestString1);
3471 int peer2 = 0;
3472 weak_persistent_handle2 =
3473 Dart_NewWeakPersistentHandle(ref2, &peer2, 0, NopCallback);
3474 int peer3 = 0;
3475 {
3476 Dart_EnterScope();
3477 Dart_Handle ref3 = Dart_NewStringFromCString(kTestString1);
3478 finalizable_handle3 = Dart_NewFinalizableHandle(
3479 ref3, &peer3, 0, FinalizableHandlePeerCleanupFinalizer);
3480 Dart_ExitScope();
3481 }
3482 {
3483 TransitionNativeToVM transition(thread);
3484 GCTestHelper::CollectAllGarbage();
3485 EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
3486 EXPECT(peer3 == 42);
3487 }
3488 Dart_ExitScope();
3489}
3490
3491static void WeakPersistentHandlePeerFinalizer(void* isolate_callback_data,
3492 Dart_WeakPersistentHandle handle,
3493 void* peer) {
3494 *static_cast<int*>(peer) = 42;
3495}
3496
3497TEST_CASE(DartAPI_WeakPersistentHandleCallback) {
3498 Dart_WeakPersistentHandle weak_ref = NULL;
3499 int peer = 0;
3500 {
3501 Dart_EnterScope();
3502 Dart_Handle obj = NewString("new string");
3503 EXPECT_VALID(obj);
3504 weak_ref = Dart_NewWeakPersistentHandle(obj, &peer, 0,
3505 WeakPersistentHandlePeerFinalizer);
3506 EXPECT_VALID(AsHandle(weak_ref));
3507 EXPECT(peer == 0);
3508 Dart_ExitScope();
3509 }
3510 {
3511 TransitionNativeToVM transition(thread);
3512 GCTestHelper::CollectOldSpace();
3513 EXPECT(peer == 0);
3514 GCTestHelper::CollectNewSpace();
3515 EXPECT(peer == 42);
3516 }
3517}
3518
3519static void FinalizableHandlePeerFinalizer(void* isolate_callback_data,
3520 void* peer) {
3521 *static_cast<int*>(peer) = 42;
3522}
3523
3524TEST_CASE(DartAPI_FinalizableHandleCallback) {
3525 Dart_FinalizableHandle weak_ref = nullptr;
3526 int peer = 0;
3527 {
3528 Dart_EnterScope();
3529 Dart_Handle obj = NewString("new string");
3530 EXPECT_VALID(obj);
3531 weak_ref = Dart_NewFinalizableHandle(obj, &peer, 0,
3532 FinalizableHandlePeerFinalizer);
3533 EXPECT(peer == 0);
3534 Dart_ExitScope();
3535 }
3536 {
3537 TransitionNativeToVM transition(thread);
3538 GCTestHelper::CollectOldSpace();
3539 EXPECT(peer == 0);
3540 GCTestHelper::CollectNewSpace();
3541 EXPECT(peer == 42);
3542 }
3543}
3544
3545TEST_CASE(DartAPI_WeakPersistentHandleNoCallback) {
3546 Dart_WeakPersistentHandle weak_ref = NULL;
3547 int peer = 0;
3548 {
3549 Dart_EnterScope();
3550 Dart_Handle obj = NewString("new string");
3551 EXPECT_VALID(obj);
3552 weak_ref = Dart_NewWeakPersistentHandle(obj, &peer, 0,
3553 WeakPersistentHandlePeerFinalizer);
3554 Dart_ExitScope();
3555 }
3556 // A finalizer is not invoked on a deleted handle. Therefore, the
3557 // peer value should not change after the referent is collected.
3558 Dart_DeleteWeakPersistentHandle(weak_ref);
3559 EXPECT(peer == 0);
3560 {
3561 TransitionNativeToVM transition(thread);
3562 GCTestHelper::CollectOldSpace();
3563 EXPECT(peer == 0);
3564 GCTestHelper::CollectNewSpace();
3565 EXPECT(peer == 0);
3566 }
3567}
3568
3569TEST_CASE(DartAPI_FinalizableHandleNoCallback) {
3570 Dart_FinalizableHandle weak_ref = nullptr;
3571 Dart_PersistentHandle strong_ref = nullptr;
3572 int peer = 0;
3573 {
3574 Dart_EnterScope();
3575 Dart_Handle obj = NewString("new string");
3576 EXPECT_VALID(obj);
3577 weak_ref = Dart_NewFinalizableHandle(obj, &peer, 0,
3578 FinalizableHandlePeerFinalizer);
3579 strong_ref = Dart_NewPersistentHandle(obj);
3580 Dart_ExitScope();
3581 }
3582 // A finalizer is not invoked on a deleted handle. Therefore, the
3583 // peer value should not change after the referent is collected.
3584 Dart_DeleteFinalizableHandle(weak_ref, strong_ref);
3585 Dart_DeletePersistentHandle(strong_ref);
3586 EXPECT(peer == 0);
3587 {
3588 TransitionNativeToVM transition(thread);
3589 GCTestHelper::CollectOldSpace();
3590 EXPECT(peer == 0);
3591 GCTestHelper::CollectNewSpace();
3592 EXPECT(peer == 0);
3593 }
3594}
3595
3596Dart_WeakPersistentHandle delete_on_finalization;
3597
3598VM_UNIT_TEST_CASE(DartAPI_WeakPersistentHandlesCallbackShutdown) {
3599 TestCase::CreateTestIsolate();
3600 Dart_EnterScope();
3601 Dart_Handle ref = Dart_True();
3602 int peer = 1234;
3603 Dart_NewWeakPersistentHandle(ref, &peer, 0,
3604 WeakPersistentHandlePeerFinalizer);
3605 Dart_ExitScope();
3606 Dart_ShutdownIsolate();
3607 EXPECT(peer == 42);
3608}
3609
3610VM_UNIT_TEST_CASE(DartAPI_FinalizableHandlesCallbackShutdown) {
3611 TestCase::CreateTestIsolate();
3612 Dart_EnterScope();
3613 Dart_Handle ref = Dart_True();
3614 int peer = 1234;
3615 Dart_NewFinalizableHandle(ref, &peer, 0, FinalizableHandlePeerFinalizer);
3616 Dart_ExitScope();
3617 Dart_ShutdownIsolate();
3618 EXPECT(peer == 42);
3619}
3620
3621TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSize) {
3622 Heap* heap = Isolate::Current()->heap();
3623 EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
3624 EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
3625 Dart_WeakPersistentHandle weak1 = NULL;
3626 static const intptr_t kWeak1ExternalSize = 1 * KB;
3627 {
3628 Dart_EnterScope();
3629 Dart_Handle obj = NewString("weakly referenced string");
3630 EXPECT_VALID(obj);
3631 weak1 = Dart_NewWeakPersistentHandle(obj, NULL, kWeak1ExternalSize,
3632 NopCallback);
3633 EXPECT_VALID(AsHandle(weak1));
3634 Dart_ExitScope();
3635 }
3636 Dart_PersistentHandle strong_ref = NULL;
3637 Dart_WeakPersistentHandle weak2 = NULL;
3638 static const intptr_t kWeak2ExternalSize = 2 * KB;
3639 {
3640 Dart_EnterScope();
3641 Dart_Handle obj = NewString("strongly referenced string");
3642 EXPECT_VALID(obj);
3643 strong_ref = Dart_NewPersistentHandle(obj);
3644 weak2 = Dart_NewWeakPersistentHandle(obj, NULL, kWeak2ExternalSize,
3645 NopCallback);
3646 EXPECT_VALID(AsHandle(strong_ref));
3647 EXPECT_VALID(AsHandle(weak2));
3648 Dart_ExitScope();
3649 }
3650 {
3651 TransitionNativeToVM transition(thread);
3652 GCTestHelper::CollectOldSpace();
3653 EXPECT(heap->ExternalInWords(Heap::kNew) ==
3654 (kWeak1ExternalSize + kWeak2ExternalSize) / kWordSize);
3655 // Collect weakly referenced string, and promote strongly referenced string.
3656 GCTestHelper::CollectNewSpace();
3657 GCTestHelper::CollectNewSpace();
3658 EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
3659 EXPECT(heap->ExternalInWords(Heap::kOld) == kWeak2ExternalSize / kWordSize);
3660 }
3661 Dart_DeletePersistentHandle(strong_ref);
3662 {
3663 TransitionNativeToVM transition(thread);
3664 GCTestHelper::CollectOldSpace();
3665 EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
3666 }
3667}
3668
3669TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSize) {
3670 Heap* heap = Isolate::Current()->heap();
3671 EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
3672 EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
3673 Dart_FinalizableHandle weak1 = nullptr;
3674 static const intptr_t kWeak1ExternalSize = 1 * KB;
3675 {
3676 Dart_EnterScope();
3677 Dart_Handle obj = NewString("weakly referenced string");
3678 EXPECT_VALID(obj);
3679 weak1 = Dart_NewFinalizableHandle(obj, nullptr, kWeak1ExternalSize,
3680 NopCallback);
3681 Dart_ExitScope();
3682 }
3683 Dart_PersistentHandle strong_ref = nullptr;
3684 Dart_FinalizableHandle weak2 = nullptr;
3685 static const intptr_t kWeak2ExternalSize = 2 * KB;
3686 {
3687 Dart_EnterScope();
3688 Dart_Handle obj = NewString("strongly referenced string");
3689 EXPECT_VALID(obj);
3690 strong_ref = Dart_NewPersistentHandle(obj);
3691 weak2 = Dart_NewFinalizableHandle(obj, nullptr, kWeak2ExternalSize,
3692 NopCallback);
3693 EXPECT_VALID(AsHandle(strong_ref));
3694 Dart_ExitScope();
3695 }
3696 {
3697 TransitionNativeToVM transition(thread);
3698 GCTestHelper::CollectOldSpace();
3699 EXPECT(heap->ExternalInWords(Heap::kNew) ==
3700 (kWeak1ExternalSize + kWeak2ExternalSize) / kWordSize);
3701 // Collect weakly referenced string, and promote strongly referenced string.
3702 GCTestHelper::CollectNewSpace();
3703 GCTestHelper::CollectNewSpace();
3704 EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
3705 EXPECT(heap->ExternalInWords(Heap::kOld) == kWeak2ExternalSize / kWordSize);
3706 }
3707 Dart_DeletePersistentHandle(strong_ref);
3708 {
3709 TransitionNativeToVM transition(thread);
3710 GCTestHelper::CollectOldSpace();
3711 EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
3712 }
3713}
3714
3715TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSizeNewspaceGC) {
3716 Heap* heap = Isolate::Current()->heap();
3717 Dart_WeakPersistentHandle weak1 = NULL;
3718 // Large enough to exceed any new space limit. Not actually allocated.
3719 const intptr_t kWeak1ExternalSize = 500 * MB;
3720 {
3721 Dart_EnterScope();
3722 Dart_Handle obj = NewString("weakly referenced string");
3723 EXPECT_VALID(obj);
3724 // Triggers a scavenge immediately, since kWeak1ExternalSize is above limit.
3725 weak1 = Dart_NewWeakPersistentHandle(obj, NULL, kWeak1ExternalSize,
3726 NopCallback);
3727 EXPECT_VALID(AsHandle(weak1));
3728 // ... but the object is still alive and not yet promoted, so external size
3729 // in new space is still above the limit. Thus, even the following tiny
3730 // external allocation will trigger another scavenge.
3731 Dart_WeakPersistentHandle trigger =
3732 Dart_NewWeakPersistentHandle(obj, NULL, 1, NopCallback);
3733 EXPECT_VALID(AsHandle(trigger));
3734 Dart_DeleteWeakPersistentHandle(trigger);
3735 // After the two scavenges above, 'obj' should now be promoted, hence its
3736 // external size charged to old space.
3737 {
3738 CHECK_API_SCOPE(thread);
3739 TransitionNativeToVM transition(thread);
3740 HANDLESCOPE(thread);
3741 String& handle = String::Handle(thread->zone());
3742 handle ^= Api::UnwrapHandle(obj);
3743 EXPECT(handle.IsOld());
3744 }
3745 EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
3746 EXPECT(heap->ExternalInWords(Heap::kOld) == kWeak1ExternalSize / kWordSize);
3747 Dart_ExitScope();
3748 }
3749 Dart_DeleteWeakPersistentHandle(weak1);
3750 {
3751 TransitionNativeToVM transition(thread);
3752 GCTestHelper::CollectOldSpace();
3753 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
3754 }
3755}
3756
3757TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSizeNewspaceGC) {
3758 Heap* heap = Isolate::Current()->heap();
3759 Dart_FinalizableHandle weak1 = nullptr;
3760 Dart_PersistentHandle strong1 = nullptr;
3761 // Large enough to exceed any new space limit. Not actually allocated.
3762 const intptr_t kWeak1ExternalSize = 500 * MB;
3763 {
3764 Dart_EnterScope();
3765 Dart_Handle obj = NewString("weakly referenced string");
3766 EXPECT_VALID(obj);
3767 // Triggers a scavenge immediately, since kWeak1ExternalSize is above limit.
3768 weak1 = Dart_NewFinalizableHandle(obj, nullptr, kWeak1ExternalSize,
3769 NopCallback);
3770 strong1 = Dart_NewPersistentHandle(obj);
3771 // ... but the object is still alive and not yet promoted, so external size
3772 // in new space is still above the limit. Thus, even the following tiny
3773 // external allocation will trigger another scavenge.
3774 Dart_FinalizableHandle trigger =
3775 Dart_NewFinalizableHandle(obj, nullptr, 1, NopCallback);
3776 Dart_DeleteFinalizableHandle(trigger, obj);
3777 // After the two scavenges above, 'obj' should now be promoted, hence its
3778 // external size charged to old space.
3779 {
3780 CHECK_API_SCOPE(thread);
3781 TransitionNativeToVM transition(thread);
3782 HANDLESCOPE(thread);
3783 String& handle = String::Handle(thread->zone());
3784 handle ^= Api::UnwrapHandle(obj);
3785 EXPECT(handle.IsOld());
3786 }
3787 EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
3788 EXPECT(heap->ExternalInWords(Heap::kOld) == kWeak1ExternalSize / kWordSize);
3789 Dart_ExitScope();
3790 }
3791 Dart_DeleteFinalizableHandle(weak1, strong1);
3792 Dart_DeletePersistentHandle(strong1);
3793 {
3794 TransitionNativeToVM transition(thread);
3795 GCTestHelper::CollectOldSpace();
3796 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
3797 }
3798}
3799
3800TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSizeOldspaceGC) {
3801 // Check that external allocation in old space can trigger GC.
3802 Isolate* isolate = Isolate::Current();
3803 Dart_EnterScope();
3804 Dart_Handle live = AllocateOldString("live");
3805 EXPECT_VALID(live);
3806 Dart_WeakPersistentHandle weak = NULL;
3807 Dart_WeakPersistentHandle weak2 = NULL;
3808 {
3809 TransitionNativeToVM transition(thread);
3810 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
3811 EXPECT_EQ(0, isolate->heap()->ExternalInWords(Heap::kOld));
3812 }
3813 const intptr_t kSmallExternalSize = 1 * KB;
3814 {
3815 Dart_EnterScope();
3816 Dart_Handle dead = AllocateOldString("dead");
3817 EXPECT_VALID(dead);
3818 weak = Dart_NewWeakPersistentHandle(dead, NULL, kSmallExternalSize,
3819 NopCallback);
3820 EXPECT_VALID(AsHandle(weak));
3821 Dart_ExitScope();
3822 }
3823 {
3824 TransitionNativeToVM transition(thread);
3825 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
3826 EXPECT_EQ(kSmallExternalSize,
3827 isolate->heap()->ExternalInWords(Heap::kOld) * kWordSize);
3828 }
3829 // Large enough to trigger GC in old space. Not actually allocated.
3830 const intptr_t kHugeExternalSize = (kWordSize == 4) ? 513 * MB : 1025 * MB;
3831 weak2 =
3832 Dart_NewWeakPersistentHandle(live, NULL, kHugeExternalSize, NopCallback);
3833 {
3834 TransitionNativeToVM transition(thread);
3835 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
3836 // Expect small garbage to be collected.
3837 EXPECT_EQ(kHugeExternalSize,
3838 isolate->heap()->ExternalInWords(Heap::kOld) * kWordSize);
3839 }
3840 Dart_ExitScope();
3841}
3842
3843TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSizeOldspaceGC) {
3844 // Check that external allocation in old space can trigger GC.
3845 Isolate* isolate = Isolate::Current();
3846 Dart_EnterScope();
3847 Dart_Handle live = AllocateOldString("live");
3848 EXPECT_VALID(live);
3849 Dart_FinalizableHandle weak = NULL;
3850 {
3851 TransitionNativeToVM transition(thread);
3852 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
3853 EXPECT_EQ(0, isolate->heap()->ExternalInWords(Heap::kOld));
3854 }
3855 const intptr_t kSmallExternalSize = 1 * KB;
3856 {
3857 Dart_EnterScope();
3858 Dart_Handle dead = AllocateOldString("dead");
3859 EXPECT_VALID(dead);
3860 weak = Dart_NewFinalizableHandle(dead, nullptr, kSmallExternalSize,
3861 NopCallback);
3862 Dart_ExitScope();
3863 }
3864 {
3865 TransitionNativeToVM transition(thread);
3866 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
3867 EXPECT_EQ(kSmallExternalSize,
3868 isolate->heap()->ExternalInWords(Heap::kOld) * kWordSize);
3869 }
3870 // Large enough to trigger GC in old space. Not actually allocated.
3871 const intptr_t kHugeExternalSize = (kWordSize == 4) ? 513 * MB : 1025 * MB;
3872 Dart_NewFinalizableHandle(live, nullptr, kHugeExternalSize, NopCallback);
3873 {
3874 TransitionNativeToVM transition(thread);
3875 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
3876 // Expect small garbage to be collected.
3877 EXPECT_EQ(kHugeExternalSize,
3878 isolate->heap()->ExternalInWords(Heap::kOld) * kWordSize);
3879 }
3880 Dart_ExitScope();
3881}
3882
3883TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSizeOddReferents) {
3884 Heap* heap = Isolate::Current()->heap();
3885 Dart_WeakPersistentHandle weak1 = NULL;
3886 static const intptr_t kWeak1ExternalSize = 1 * KB;
3887 Dart_WeakPersistentHandle weak2 = NULL;
3888 static const intptr_t kWeak2ExternalSize = 2 * KB;
3889 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
3890 {
3891 Dart_EnterScope();
3892 Dart_Handle dart_true = Dart_True(); // VM heap object.
3893 EXPECT_VALID(dart_true);
3894 weak1 = Dart_NewWeakPersistentHandle(dart_true, NULL, kWeak1ExternalSize,
3895 UnreachedCallback);
3896 EXPECT_VALID(AsHandle(weak1));
3897 Dart_Handle zero = Dart_False(); // VM heap object.
3898 EXPECT_VALID(zero);
3899 weak2 = Dart_NewWeakPersistentHandle(zero, NULL, kWeak2ExternalSize,
3900 UnreachedCallback);
3901 EXPECT_VALID(AsHandle(weak2));
3902 // Both should be charged to old space.
3903 EXPECT(heap->ExternalInWords(Heap::kOld) ==
3904 (kWeak1ExternalSize + kWeak2ExternalSize) / kWordSize);
3905 Dart_ExitScope();
3906 }
3907 Dart_DeleteWeakPersistentHandle(weak1);
3908 Dart_DeleteWeakPersistentHandle(weak2);
3909 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
3910 {
3911 TransitionNativeToVM transition(thread);
3912 GCTestHelper::CollectOldSpace();
3913 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
3914 }
3915}
3916
3917TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSizeOddReferents) {
3918 Heap* heap = Isolate::Current()->heap();
3919 Dart_FinalizableHandle weak1 = nullptr;
3920 Dart_PersistentHandle strong1 = nullptr;
3921 static const intptr_t kWeak1ExternalSize = 1 * KB;
3922 Dart_FinalizableHandle weak2 = nullptr;
3923 Dart_PersistentHandle strong2 = nullptr;
3924 static const intptr_t kWeak2ExternalSize = 2 * KB;
3925 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
3926 {
3927 Dart_EnterScope();
3928 Dart_Handle dart_true = Dart_True(); // VM heap object.
3929 EXPECT_VALID(dart_true);
3930 weak1 = Dart_NewFinalizableHandle(dart_true, nullptr, kWeak1ExternalSize,
3931 UnreachedCallback);
3932 strong1 = Dart_NewPersistentHandle(dart_true);
3933 Dart_Handle zero = Dart_False(); // VM heap object.
3934 EXPECT_VALID(zero);
3935 weak2 = Dart_NewFinalizableHandle(zero, nullptr, kWeak2ExternalSize,
3936 UnreachedCallback);
3937 strong2 = Dart_NewPersistentHandle(zero);
3938 // Both should be charged to old space.
3939 EXPECT(heap->ExternalInWords(Heap::kOld) ==
3940 (kWeak1ExternalSize + kWeak2ExternalSize) / kWordSize);
3941 Dart_ExitScope();
3942 }
3943 Dart_DeleteFinalizableHandle(weak1, strong1);
3944 Dart_DeletePersistentHandle(strong1);
3945 Dart_DeleteFinalizableHandle(weak2, strong2);
3946 Dart_DeletePersistentHandle(strong2);
3947 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
3948 {
3949 TransitionNativeToVM transition(thread);
3950 GCTestHelper::CollectOldSpace();
3951 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
3952 }
3953}
3954
3955#define EXAMPLE_RESOURCE_NATIVE_LIST(V) \
3956 V(ExampleResource_Allocate, 1) \
3957 V(ExampleResource_Use, 1) \
3958 V(ExampleResource_Dispose, 1)
3959
3960EXAMPLE_RESOURCE_NATIVE_LIST(DECLARE_FUNCTION);
3961
3962static struct NativeEntries {
3963 const char* name_;
3964 Dart_NativeFunction function_;
3965 int argument_count_;
3966} ExampleResourceEntries[] = {EXAMPLE_RESOURCE_NATIVE_LIST(REGISTER_FUNCTION)};
3967
3968static Dart_NativeFunction ExampleResourceNativeResolver(
3969 Dart_Handle name,
3970 int argument_count,
3971 bool* auto_setup_scope) {
3972 const char* function_name = nullptr;
3973 Dart_Handle result = Dart_StringToCString(name, &function_name);
3974 ASSERT(!Dart_IsError(result));
3975 ASSERT(function_name != nullptr);
3976 ASSERT(auto_setup_scope != nullptr);
3977 *auto_setup_scope = true;
3978 int num_entries =
3979 sizeof(ExampleResourceEntries) / sizeof(struct NativeEntries);
3980 for (int i = 0; i < num_entries; i++) {
3981 struct NativeEntries* entry = &(ExampleResourceEntries[i]);
3982 if ((strcmp(function_name, entry->name_) == 0) &&
3983 (entry->argument_count_ == argument_count)) {
3984 return reinterpret_cast<Dart_NativeFunction>(entry->function_);
3985 }
3986 }
3987 return nullptr;
3988}
3989
3990struct ExampleResource {
3991 Dart_WeakPersistentHandle self;
3992 void* lots_of_memory;
3993};
3994
3995void ExampleResourceFinalizer(void* isolate_peer,
3996 Dart_WeakPersistentHandle handle,
3997 void* peer) {
3998 ExampleResource* resource = reinterpret_cast<ExampleResource*>(peer);
3999 free(resource->lots_of_memory);
4000 delete resource;
4001}
4002
4003void FUNCTION_NAME(ExampleResource_Allocate)(Dart_NativeArguments native_args) {
4004 Dart_Handle receiver = Dart_GetNativeArgument(native_args, 0);
4005 intptr_t external_size = 10 * MB;
4006 ExampleResource* resource = new ExampleResource();
4007 resource->lots_of_memory = malloc(external_size);
4008 resource->self = Dart_NewWeakPersistentHandle(
4009 receiver, resource, external_size, ExampleResourceFinalizer);
4010 EXPECT_VALID(Dart_SetNativeInstanceField(
4011 receiver, 0, reinterpret_cast<intptr_t>(resource)));
4012 // Some pretend resource initialization.
4013 *reinterpret_cast<uint8_t*>(resource->lots_of_memory) = 123;
4014}
4015
4016void FUNCTION_NAME(ExampleResource_Use)(Dart_NativeArguments native_args) {
4017 Dart_Handle receiver = Dart_GetNativeArgument(native_args, 0);
4018 intptr_t native_field = 0;
4019 EXPECT_VALID(Dart_GetNativeInstanceField(receiver, 0, &native_field));
4020 ExampleResource* resource = reinterpret_cast<ExampleResource*>(native_field);
4021 if (resource->lots_of_memory == nullptr) {
4022 Dart_ThrowException(Dart_NewStringFromCString(
4023 "Attempt to use a disposed ExampleResource!"));
4024 UNREACHABLE();
4025 } else {
4026 // Some pretend resource use.
4027 EXPECT_EQ(123, *reinterpret_cast<uint8_t*>(resource->lots_of_memory));
4028 }
4029}
4030
4031void FUNCTION_NAME(ExampleResource_Dispose)(Dart_NativeArguments native_args) {
4032 Dart_Handle receiver = Dart_GetNativeArgument(native_args, 0);
4033 intptr_t native_field = 0;
4034 EXPECT_VALID(Dart_GetNativeInstanceField(receiver, 0, &native_field));
4035 ExampleResource* resource = reinterpret_cast<ExampleResource*>(native_field);
4036 if (resource->lots_of_memory != nullptr) {
4037 free(resource->lots_of_memory);
4038 resource->lots_of_memory = nullptr;
4039 Dart_UpdateExternalSize(resource->self, 0);
4040 }
4041}
4042
4043TEST_CASE(DartAPI_WeakPersistentHandleUpdateSize) {
4044 const char* kScriptChars = R"(
4045 import "dart:nativewrappers";
4046 class ExampleResource extends NativeFieldWrapperClass1 {
4047 ExampleResource() { _allocate(); }
4048 void _allocate() native "ExampleResource_Allocate";
4049 void use() native "ExampleResource_Use";
4050 void dispose() native "ExampleResource_Dispose";
4051 }
4052 main() {
4053 var res = new ExampleResource();
4054 res.use();
4055 res.dispose();
4056 res.dispose(); // Idempotent
4057 bool threw = false;
4058 try {
4059 res.use();
4060 } catch (_) {
4061 threw = true;
4062 }
4063 if (!threw) {
4064 throw "Exception expected";
4065 }
4066 }
4067 )";
4068
4069 Dart_Handle lib =
4070 TestCase::LoadTestScript(kScriptChars, ExampleResourceNativeResolver);
4071 EXPECT_VALID(Dart_Invoke(lib, NewString("main"), 0, NULL));
4072}
4073
4074static Dart_WeakPersistentHandle weak1 = NULL;
4075static Dart_WeakPersistentHandle weak2 = NULL;
4076static Dart_WeakPersistentHandle weak3 = NULL;
4077
4078static void ImplicitReferencesCallback(void* isolate_callback_data,
4079 Dart_WeakPersistentHandle handle,
4080 void* peer) {
4081 if (handle == weak1) {
4082 weak1 = NULL;
4083 } else if (handle == weak2) {
4084 weak2 = NULL;
4085 } else if (handle == weak3) {
4086 weak3 = NULL;
4087 }
4088}
4089
4090TEST_CASE(DartAPI_ImplicitReferencesOldSpace) {
4091 Dart_PersistentHandle strong = NULL;
4092 Dart_WeakPersistentHandle strong_weak = NULL;
4093
4094 Dart_EnterScope();
4095 {
4096 CHECK_API_SCOPE(thread);
4097
4098 Dart_Handle local = AllocateOldString("strongly reachable");
4099 strong = Dart_NewPersistentHandle(local);
4100 strong_weak = Dart_NewWeakPersistentHandle(local, NULL, 0, NopCallback);
4101
4102 EXPECT(!Dart_IsNull(AsHandle(strong)));
4103 EXPECT_VALID(AsHandle(strong));
4104 EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
4105 EXPECT_VALID(AsHandle(strong_weak));
4106 EXPECT(Dart_IdentityEquals(AsHandle(strong), AsHandle(strong_weak)))
4107
4108 weak1 =
4109 Dart_NewWeakPersistentHandle(AllocateOldString("weakly reachable 1"),
4110 NULL, 0, ImplicitReferencesCallback);
4111 EXPECT(!Dart_IsNull(AsHandle(weak1)));
4112 EXPECT_VALID(AsHandle(weak1));
4113
4114 weak2 =
4115 Dart_NewWeakPersistentHandle(AllocateOldString("weakly reachable 2"),
4116 NULL, 0, ImplicitReferencesCallback);
4117 EXPECT(!Dart_IsNull(AsHandle(weak2)));
4118 EXPECT_VALID(AsHandle(weak2));
4119
4120 weak3 =
4121 Dart_NewWeakPersistentHandle(AllocateOldString("weakly reachable 3"),
4122 NULL, 0, ImplicitReferencesCallback);
4123 EXPECT(!Dart_IsNull(AsHandle(weak3)));
4124 EXPECT_VALID(AsHandle(weak3));
4125 }
4126 Dart_ExitScope();
4127
4128 {
4129 Dart_EnterScope();
4130 EXPECT_VALID(AsHandle(strong_weak));
4131 EXPECT_VALID(AsHandle(weak1));
4132 EXPECT_VALID(AsHandle(weak2));
4133 EXPECT_VALID(AsHandle(weak3));
4134 Dart_ExitScope();
4135 }
4136
4137 {
4138 TransitionNativeToVM transition(thread);
4139 GCTestHelper::CollectNewSpace();
4140 }
4141
4142 {
4143 Dart_EnterScope();
4144 // New space collection should not affect old space objects
4145 EXPECT_VALID(AsHandle(strong_weak));
4146 EXPECT(!Dart_IsNull(AsHandle(weak1)));
4147 EXPECT(!Dart_IsNull(AsHandle(weak2)));
4148 EXPECT(!Dart_IsNull(AsHandle(weak3)));
4149 Dart_ExitScope();
4150 }
4151}
4152
4153TEST_CASE(DartAPI_ImplicitReferencesNewSpace) {
4154 Dart_PersistentHandle strong = NULL;
4155 Dart_WeakPersistentHandle strong_weak = NULL;
4156
4157 Dart_EnterScope();
4158 {
4159 CHECK_API_SCOPE(thread);
4160
4161 Dart_Handle local = AllocateOldString("strongly reachable");
4162 strong = Dart_NewPersistentHandle(local);
4163 strong_weak = Dart_NewWeakPersistentHandle(local, NULL, 0, NopCallback);
4164
4165 EXPECT(!Dart_IsNull(AsHandle(strong)));
4166 EXPECT_VALID(AsHandle(strong));
4167 EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
4168 EXPECT_VALID(AsHandle(strong_weak));
4169 EXPECT(Dart_IdentityEquals(AsHandle(strong), AsHandle(strong_weak)))
4170
4171 weak1 =
4172 Dart_NewWeakPersistentHandle(AllocateNewString("weakly reachable 1"),
4173 NULL, 0, ImplicitReferencesCallback);
4174 EXPECT(!Dart_IsNull(AsHandle(weak1)));
4175 EXPECT_VALID(AsHandle(weak1));
4176
4177 weak2 =
4178 Dart_NewWeakPersistentHandle(AllocateNewString("weakly reachable 2"),
4179 NULL, 0, ImplicitReferencesCallback);
4180 EXPECT(!Dart_IsNull(AsHandle(weak2)));
4181 EXPECT_VALID(AsHandle(weak2));
4182
4183 weak3 =
4184 Dart_NewWeakPersistentHandle(AllocateNewString("weakly reachable 3"),
4185 NULL, 0, ImplicitReferencesCallback);
4186 EXPECT(!Dart_IsNull(AsHandle(weak3)));
4187 EXPECT_VALID(AsHandle(weak3));
4188 }
4189 Dart_ExitScope();
4190
4191 {
4192 Dart_EnterScope();
4193 EXPECT_VALID(AsHandle(strong_weak));
4194 EXPECT_VALID(AsHandle(weak1));
4195 EXPECT_VALID(AsHandle(weak2));
4196 EXPECT_VALID(AsHandle(weak3));
4197 Dart_ExitScope();
4198 }
4199
4200 {
4201 TransitionNativeToVM transition(thread);
4202 GCTestHelper::CollectOldSpace();
4203 }
4204
4205 {
4206 Dart_EnterScope();
4207 // Old space collection should not affect old space objects.
4208 EXPECT(!Dart_IsNull(AsHandle(weak1)));
4209 EXPECT(!Dart_IsNull(AsHandle(weak2)));
4210 EXPECT(!Dart_IsNull(AsHandle(weak3)));
4211 Dart_ExitScope();
4212 }
4213}
4214
4215// Unit test for creating multiple scopes and local handles within them.
4216// Ensure that the local handles get all cleaned out when exiting the
4217// scope.
4218VM_UNIT_TEST_CASE(DartAPI_LocalHandles) {
4219 TestCase::CreateTestIsolate();
4220 Thread* thread = Thread::Current();
4221 Isolate* isolate = thread->isolate();
4222 EXPECT(isolate != NULL);
4223 ApiLocalScope* scope = thread->api_top_scope();
4224 Dart_Handle handles[300];
4225 {
4226 TransitionNativeToVM transition1(thread);
4227 StackZone zone(thread);
4228 HANDLESCOPE(thread);
4229 Smi& val = Smi::Handle();
4230 TransitionVMToNative transition2(thread);
4231
4232 // Start a new scope and allocate some local handles.
4233 Dart_EnterScope();
4234 {
4235 TransitionNativeToVM transition3(thread);
4236 for (int i = 0; i < 100; i++) {
4237 handles[i] = Api::NewHandle(thread, Smi::New(i));
4238 }
4239 EXPECT_EQ(100, thread->CountLocalHandles());
4240 for (int i = 0; i < 100; i++) {
4241 val ^= Api::UnwrapHandle(handles[i]);
4242 EXPECT_EQ(i, val.Value());
4243 }
4244 }
4245 // Start another scope and allocate some more local handles.
4246 {
4247 Dart_EnterScope();
4248 {
4249 TransitionNativeToVM transition3(thread);
4250 for (int i = 100; i < 200; i++) {
4251 handles[i] = Api::NewHandle(thread, Smi::New(i));
4252 }
4253 EXPECT_EQ(200, thread->CountLocalHandles());
4254 for (int i = 100; i < 200; i++) {
4255 val ^= Api::UnwrapHandle(handles[i]);
4256 EXPECT_EQ(i, val.Value());
4257 }
4258 }
4259
4260 // Start another scope and allocate some more local handles.
4261 {
4262 Dart_EnterScope();
4263 {
4264 TransitionNativeToVM transition3(thread);
4265 for (int i = 200; i < 300; i++) {
4266 handles[i] = Api::NewHandle(thread, Smi::New(i));
4267 }
4268 EXPECT_EQ(300, thread->CountLocalHandles());
4269 for (int i = 200; i < 300; i++) {
4270 val ^= Api::UnwrapHandle(handles[i]);
4271 EXPECT_EQ(i, val.Value());
4272 }
4273 EXPECT_EQ(300, thread->CountLocalHandles());
4274 }
4275 Dart_ExitScope();
4276 }
4277 EXPECT_EQ(200, thread->CountLocalHandles());
4278 Dart_ExitScope();
4279 }
4280 EXPECT_EQ(100, thread->CountLocalHandles());
4281 Dart_ExitScope();
4282 }
4283 EXPECT_EQ(0, thread->CountLocalHandles());
4284 EXPECT(scope == thread->api_top_scope());
4285 Dart_ShutdownIsolate();
4286}
4287
4288// Unit test for creating multiple scopes and allocating objects in the
4289// zone for the scope. Ensure that the memory is freed when the scope
4290// exits.
4291VM_UNIT_TEST_CASE(DartAPI_LocalZoneMemory) {
4292 TestCase::CreateTestIsolate();
4293 Thread* thread = Thread::Current();
4294 EXPECT(thread != NULL);
4295 ApiLocalScope* scope = thread->api_top_scope();
4296 {
4297 // Start a new scope and allocate some memory.
4298 Dart_EnterScope();
4299 for (int i = 0; i < 100; i++) {
4300 Dart_ScopeAllocate(16);
4301 }
4302 EXPECT_EQ(1600, thread->ZoneSizeInBytes());
4303 // Start another scope and allocate some more memory.
4304 {
4305 Dart_EnterScope();
4306 for (int i = 0; i < 100; i++) {
4307 Dart_ScopeAllocate(16);
4308 }
4309 EXPECT_EQ(3200, thread->ZoneSizeInBytes());
4310 {
4311 // Start another scope and allocate some more memory.
4312 {
4313 Dart_EnterScope();
4314 for (int i = 0; i < 200; i++) {
4315 Dart_ScopeAllocate(16);
4316 }
4317 EXPECT_EQ(6400, thread->ZoneSizeInBytes());
4318 Dart_ExitScope();
4319 }
4320 }
4321 EXPECT_EQ(3200, thread->ZoneSizeInBytes());
4322 Dart_ExitScope();
4323 }
4324 EXPECT_EQ(1600, thread->ZoneSizeInBytes());
4325 Dart_ExitScope();
4326 }
4327 EXPECT_EQ(0, thread->ZoneSizeInBytes());
4328 EXPECT(scope == thread->api_top_scope());
4329 Dart_ShutdownIsolate();
4330}
4331
4332VM_UNIT_TEST_CASE(DartAPI_Isolates) {
4333 // This test currently assumes that the Dart_Isolate type is an opaque
4334 // representation of Isolate*.
4335 Dart_Isolate iso_1 = TestCase::CreateTestIsolate();
4336 EXPECT_EQ(iso_1, Api::CastIsolate(Isolate::Current()));
4337 Dart_Isolate isolate = Dart_CurrentIsolate();
4338 EXPECT_EQ(iso_1, isolate);
4339 Dart_ExitIsolate();
4340 EXPECT_NULLPTR(Dart_CurrentIsolate());
4341 Dart_Isolate iso_2 = TestCase::CreateTestIsolate();
4342 EXPECT_EQ(iso_2, Dart_CurrentIsolate());
4343 Dart_ExitIsolate();
4344 EXPECT_NULLPTR(Dart_CurrentIsolate());
4345 Dart_EnterIsolate(iso_2);
4346 EXPECT_EQ(iso_2, Dart_CurrentIsolate());
4347 Dart_ShutdownIsolate();
4348 EXPECT_NULLPTR(Dart_CurrentIsolate());
4349 Dart_EnterIsolate(iso_1);
4350 EXPECT_EQ(iso_1, Dart_CurrentIsolate());
4351 Dart_ShutdownIsolate();
4352 EXPECT_NULLPTR(Dart_CurrentIsolate());
4353}
4354
4355VM_UNIT_TEST_CASE(DartAPI_IsolateGroups) {
4356 Dart_Isolate iso_1 = TestCase::CreateTestIsolate();
4357 EXPECT_NOTNULL(Dart_CurrentIsolateGroup());
4358 Dart_ExitIsolate();
4359 EXPECT_NULLPTR(Dart_CurrentIsolateGroup());
4360 Dart_Isolate iso_2 = TestCase::CreateTestIsolate();
4361 EXPECT_NOTNULL(Dart_CurrentIsolateGroup());
4362 Dart_ExitIsolate();
4363 EXPECT_NULLPTR(Dart_CurrentIsolateGroup());
4364 Dart_EnterIsolate(iso_2);
4365 EXPECT_NOTNULL(Dart_CurrentIsolateGroup());
4366 Dart_ShutdownIsolate();
4367 EXPECT_NULLPTR(Dart_CurrentIsolateGroup());
4368 Dart_EnterIsolate(iso_1);
4369 EXPECT_NOTNULL(Dart_CurrentIsolateGroup());
4370 Dart_ShutdownIsolate();
4371 EXPECT_NULLPTR(Dart_CurrentIsolateGroup());
4372}
4373
4374VM_UNIT_TEST_CASE(DartAPI_CurrentIsolateData) {
4375 Dart_IsolateShutdownCallback saved_shutdown = Isolate::ShutdownCallback();
4376 Dart_IsolateGroupCleanupCallback saved_cleanup =
4377 Isolate::GroupCleanupCallback();
4378 Isolate::SetShutdownCallback(NULL);
4379 Isolate::SetGroupCleanupCallback(NULL);
4380
4381 intptr_t mydata = 12345;
4382 Dart_Isolate isolate =
4383 TestCase::CreateTestIsolate(NULL, reinterpret_cast<void*>(mydata));
4384 EXPECT(isolate != NULL);
4385 EXPECT_EQ(mydata, reinterpret_cast<intptr_t>(Dart_CurrentIsolateGroupData()));
4386 EXPECT_EQ(mydata, reinterpret_cast<intptr_t>(Dart_IsolateGroupData(isolate)));
4387 Dart_ShutdownIsolate();
4388
4389 Isolate::SetShutdownCallback(saved_shutdown);
4390 Isolate::SetGroupCleanupCallback(saved_cleanup);
4391}
4392
4393static Dart_Handle LoadScript(const char* url_str, const char* source) {
4394 const uint8_t* kernel_buffer = NULL;
4395 intptr_t kernel_buffer_size = 0;
4396 char* error = TestCase::CompileTestScriptWithDFE(
4397 url_str, source, &kernel_buffer, &kernel_buffer_size);
4398 if (error != NULL) {
4399 return Dart_NewApiError(error);
4400 }
4401 TestCaseBase::AddToKernelBuffers(kernel_buffer);
4402 return Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
4403}
4404
4405TEST_CASE(DartAPI_DebugName) {
4406 Dart_Handle debug_name = Dart_DebugName();
4407 EXPECT_VALID(debug_name);
4408 EXPECT(Dart_IsString(debug_name));
4409}
4410
4411TEST_CASE(DartAPI_IsolateServiceID) {
4412 Dart_Isolate isolate = Dart_CurrentIsolate();
4413 const char* id = Dart_IsolateServiceId(isolate);
4414 EXPECT(id != NULL);
4415 int64_t main_port = Dart_GetMainPortId();
4416 EXPECT_STREQ(ZONE_STR("isolates/%" Pd64, main_port), id);
4417 free(const_cast<char*>(id));
4418}
4419
4420static void MyMessageNotifyCallback(Dart_Isolate dest_isolate) {}
4421
4422VM_UNIT_TEST_CASE(DartAPI_SetMessageCallbacks) {
4423 Dart_Isolate dart_isolate = TestCase::CreateTestIsolate();
4424 Dart_SetMessageNotifyCallback(&MyMessageNotifyCallback);
4425 Isolate* isolate = reinterpret_cast<Isolate*>(dart_isolate);
4426 EXPECT_EQ(&MyMessageNotifyCallback, isolate->message_notify_callback());
4427 Dart_ShutdownIsolate();
4428}
4429
4430TEST_CASE(DartAPI_SetStickyError) {
4431 const char* kScriptChars = "main() => throw 'HI';";
4432 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
4433 Dart_Handle retobj = Dart_Invoke(lib, NewString("main"), 0, NULL);
4434 EXPECT(Dart_IsError(retobj));
4435 EXPECT(Dart_IsUnhandledExceptionError(retobj));
4436 EXPECT(!Dart_HasStickyError());
4437 EXPECT(Dart_GetStickyError() == Dart_Null());
4438 Dart_SetStickyError(retobj);
4439 EXPECT(Dart_HasStickyError());
4440 EXPECT(Dart_GetStickyError() != Dart_Null());
4441 Dart_SetStickyError(Dart_Null());
4442 EXPECT(!Dart_HasStickyError());
4443 EXPECT(Dart_GetStickyError() == Dart_Null());
4444}
4445
4446TEST_CASE(DartAPI_TypeGetNonParamtericTypes) {
4447 const char* kScriptChars =
4448 "class MyClass0 {\n"
4449 "}\n"
4450 "\n"
4451 "class MyClass1 implements MyInterface1 {\n"
4452 "}\n"
4453 "\n"
4454 "class MyClass2 implements MyInterface0, MyInterface1 {\n"
4455 "}\n"
4456 "\n"
4457 "abstract class MyInterface0 {\n"
4458 "}\n"
4459 "\n"
4460 "abstract class MyInterface1 implements MyInterface0 {\n"
4461 "}\n"
4462 "MyClass0 getMyClass0() { return new MyClass0(); }\n"
4463 "MyClass1 getMyClass1() { return new MyClass1(); }\n"
4464 "MyClass2 getMyClass2() { return new MyClass2(); }\n"
4465 "Type getMyClass0Type() { return new MyClass0().runtimeType; }\n"
4466 "Type getMyClass1Type() { return new MyClass1().runtimeType; }\n"
4467 "Type getMyClass2Type() { return new MyClass2().runtimeType; }\n";
4468 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
4469 bool instanceOf = false;
4470
4471 // First get the type objects of these non parameterized types.
4472 Dart_Handle type0 =
4473 Dart_GetNonNullableType(lib, NewString("MyClass0"), 0, NULL);
4474 EXPECT_VALID(type0);
4475 Dart_Handle type1 =
4476 Dart_GetNonNullableType(lib, NewString("MyClass1"), 0, NULL);
4477 EXPECT_VALID(type1);
4478 Dart_Handle type2 =
4479 Dart_GetNonNullableType(lib, NewString("MyClass2"), 0, NULL);
4480 EXPECT_VALID(type2);
4481 Dart_Handle type3 =
4482 Dart_GetNonNullableType(lib, NewString("MyInterface0"), 0, NULL);
4483 EXPECT_VALID(type3);
4484 Dart_Handle type4 =
4485 Dart_GetNonNullableType(lib, NewString("MyInterface1"), 0, NULL);
4486 EXPECT_VALID(type4);
4487
4488 // Now create objects of these non parameterized types and check
4489 // that the validity of the type of the created object.
4490 // MyClass0 type.
4491 Dart_Handle type0_obj = Dart_Invoke(lib, NewString("getMyClass0"), 0, NULL);
4492 EXPECT_VALID(type0_obj);
4493 EXPECT_VALID(Dart_ObjectIsType(type0_obj, type0, &instanceOf));
4494 EXPECT(instanceOf);
4495 EXPECT_VALID(Dart_ObjectIsType(type0_obj, type1, &instanceOf));
4496 EXPECT(!instanceOf);
4497 EXPECT_VALID(Dart_ObjectIsType(type0_obj, type2, &instanceOf));
4498 EXPECT(!instanceOf);
4499 EXPECT_VALID(Dart_ObjectIsType(type0_obj, type3, &instanceOf));
4500 EXPECT(!instanceOf);
4501 EXPECT_VALID(Dart_ObjectIsType(type0_obj, type4, &instanceOf));
4502 EXPECT(!instanceOf);
4503 type0_obj = Dart_Invoke(lib, NewString("getMyClass0Type"), 0, NULL);
4504 EXPECT_VALID(type0_obj);
4505 EXPECT(Dart_IdentityEquals(type0, type0_obj));
4506
4507 // MyClass1 type.
4508 Dart_Handle type1_obj = Dart_Invoke(lib, NewString("getMyClass1"), 0, NULL);
4509 EXPECT_VALID(type1_obj);
4510 EXPECT_VALID(Dart_ObjectIsType(type1_obj, type1, &instanceOf));
4511 EXPECT(instanceOf);
4512 EXPECT_VALID(Dart_ObjectIsType(type1_obj, type0, &instanceOf));
4513 EXPECT(!instanceOf);
4514 EXPECT_VALID(Dart_ObjectIsType(type1_obj, type2, &instanceOf));
4515 EXPECT(!instanceOf);
4516 EXPECT_VALID(Dart_ObjectIsType(type1_obj, type3, &instanceOf));
4517 EXPECT(instanceOf);
4518 EXPECT_VALID(Dart_ObjectIsType(type1_obj, type4, &instanceOf));
4519 EXPECT(instanceOf);
4520 type1_obj = Dart_Invoke(lib, NewString("getMyClass1Type"), 0, NULL);
4521 EXPECT_VALID(type1_obj);
4522 EXPECT(Dart_IdentityEquals(type1, type1_obj));
4523
4524 // MyClass2 type.
4525 Dart_Handle type2_obj = Dart_Invoke(lib, NewString("getMyClass2"), 0, NULL);
4526 EXPECT_VALID(type2_obj);
4527 EXPECT_VALID(Dart_ObjectIsType(type2_obj, type2, &instanceOf));
4528 EXPECT(instanceOf);
4529 EXPECT_VALID(Dart_ObjectIsType(type2_obj, type0, &instanceOf));
4530 EXPECT(!instanceOf);
4531 EXPECT_VALID(Dart_ObjectIsType(type2_obj, type1, &instanceOf));
4532 EXPECT(!instanceOf);
4533 EXPECT_VALID(Dart_ObjectIsType(type2_obj, type3, &instanceOf));
4534 EXPECT(instanceOf);
4535 EXPECT_VALID(Dart_ObjectIsType(type2_obj, type4, &instanceOf));
4536 EXPECT(instanceOf);
4537 type2_obj = Dart_Invoke(lib, NewString("getMyClass2Type"), 0, NULL);
4538 EXPECT_VALID(type2_obj);
4539 EXPECT(Dart_IdentityEquals(type2, type2_obj));
4540}
4541
4542TEST_CASE(DartAPI_TypeGetParameterizedTypes) {
4543 // TODO(dartbug.com/40176): Clean up this test once the API supports NNBD.
4544 const char* kScriptChars =
4545 "class MyClass0<A, B> {\n"
4546 "}\n"
4547 "\n"
4548 "class MyClass1<A, C> {\n"
4549 "}\n"
4550 "Type type<T>() => T;"
4551 "MyClass0 getMyClass0() {\n"
4552 " return new MyClass0<int, double>();\n"
4553 "}\n"
4554 "Type getMyClass0Type() {\n"
4555 " return type<MyClass0<int, double>>();\n"
4556 "}\n"
4557 "MyClass1 getMyClass1() {\n"
4558 " return new MyClass1<List<int>, List>();\n"
4559 "}\n"
4560 "Type getMyClass1Type() {\n"
4561 " return type<MyClass1<List<int>, List>>();\n"
4562 "}\n"
4563 "MyClass0 getMyClass0_1() {\n"
4564 " return new MyClass0<double, int>();\n"
4565 "}\n"
4566 "Type getMyClass0_1Type() {\n"
4567 " return type<MyClass0<double, int>>();\n"
4568 "}\n"
4569 "MyClass1 getMyClass1_1() {\n"
4570 " return new MyClass1<List<int>, List<double>>();\n"
4571 "}\n"
4572 "Type getMyClass1_1Type() {\n"
4573 " return type<MyClass1<List<int>, List<double>>>();\n"
4574 "}\n"
4575 "Type getIntType() { return int; }\n"
4576 "Type getDoubleType() { return double; }\n"
4577 "Type getListIntType() { return type<List<int>>(); }\n"
4578 "Type getListType() { return List; }\n";
4579
4580 Dart_Handle corelib = Dart_LookupLibrary(NewString("dart:core"));
4581 EXPECT_VALID(corelib);
4582
4583 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
4584
4585 // Now instantiate MyClass0 and MyClass1 types with the same type arguments
4586 // used in the code above.
4587 Dart_Handle type_args = Dart_NewList(2);
4588 Dart_Handle int_type = Dart_Invoke(lib, NewString("getIntType"), 0, NULL);
4589 EXPECT_VALID(int_type);
4590 EXPECT_VALID(Dart_ListSetAt(type_args, 0, int_type));
4591 Dart_Handle double_type =
4592 Dart_Invoke(lib, NewString("getDoubleType"), 0, NULL);
4593 EXPECT_VALID(double_type);
4594 EXPECT_VALID(Dart_ListSetAt(type_args, 1, double_type));
4595 Dart_Handle myclass0_type =
4596 TestCase::IsNNBD()
4597 ? Dart_GetNonNullableType(lib, NewString("MyClass0"), 2, &type_args)
4598 : Dart_GetType(lib, NewString("MyClass0"), 2, &type_args);
4599 EXPECT_VALID(myclass0_type);
4600
4601 type_args = Dart_NewList(2);
4602 Dart_Handle list_int_type =
4603 Dart_Invoke(lib, NewString("getListIntType"), 0, NULL);
4604 EXPECT_VALID(list_int_type);
4605 EXPECT_VALID(Dart_ListSetAt(type_args, 0, list_int_type));
4606 Dart_Handle list_type = Dart_Invoke(lib, NewString("getListType"), 0, NULL);
4607 EXPECT_VALID(list_type);
4608 EXPECT_VALID(Dart_ListSetAt(type_args, 1, list_type));
4609 Dart_Handle myclass1_type =
4610 TestCase::IsNNBD()
4611 ? Dart_GetNonNullableType(lib, NewString("MyClass1"), 2, &type_args)
4612 : Dart_GetType(lib, NewString("MyClass1"), 2, &type_args);
4613 EXPECT_VALID(myclass1_type);
4614
4615 // Now create objects of the type and validate the object type matches
4616 // the one returned above. Also get the runtime type of the object and
4617 // verify that it matches the type returned above.
4618 // MyClass0<int, double> type.
4619 Dart_Handle type0_obj = Dart_Invoke(lib, NewString("getMyClass0"), 0, NULL);
4620 EXPECT_VALID(type0_obj);
4621 bool instanceOf = false;
4622 EXPECT_VALID(Dart_ObjectIsType(type0_obj, myclass0_type, &instanceOf));
4623 EXPECT(instanceOf);
4624 type0_obj = Dart_Invoke(lib, NewString("getMyClass0Type"), 0, NULL);
4625 EXPECT_VALID(type0_obj);
4626 EXPECT(Dart_IdentityEquals(type0_obj, myclass0_type));
4627
4628 // MyClass1<List<int>, List> type.
4629 Dart_Handle type1_obj = Dart_Invoke(lib, NewString("getMyClass1"), 0, NULL);
4630 EXPECT_VALID(type1_obj);
4631 EXPECT_VALID(Dart_ObjectIsType(type1_obj, myclass1_type, &instanceOf));
4632 EXPECT(instanceOf);
4633 type1_obj = Dart_Invoke(lib, NewString("getMyClass1Type"), 0, NULL);
4634 EXPECT_VALID(type1_obj);
4635 EXPECT(Dart_IdentityEquals(type1_obj, myclass1_type));
4636
4637 // MyClass0<double, int> type.
4638 type0_obj = Dart_Invoke(lib, NewString("getMyClass0_1"), 0, NULL);
4639 EXPECT_VALID(type0_obj);
4640 EXPECT_VALID(Dart_ObjectIsType(type0_obj, myclass0_type, &instanceOf));
4641 EXPECT(!instanceOf);
4642 type0_obj = Dart_Invoke(lib, NewString("getMyClass0_1Type"), 0, NULL);
4643 EXPECT_VALID(type0_obj);
4644 EXPECT(!Dart_IdentityEquals(type0_obj, myclass0_type));
4645
4646 // MyClass1<List<int>, List<double>> type.
4647 type1_obj = Dart_Invoke(lib, NewString("getMyClass1_1"), 0, NULL);
4648 EXPECT_VALID(type1_obj);
4649 EXPECT_VALID(Dart_ObjectIsType(type1_obj, myclass1_type, &instanceOf));
4650 EXPECT(instanceOf);
4651 type1_obj = Dart_Invoke(lib, NewString("getMyClass1_1Type"), 0, NULL);
4652 EXPECT_VALID(type1_obj);
4653 EXPECT(!Dart_IdentityEquals(type1_obj, myclass1_type));
4654}
4655
4656static void TestFieldOk(Dart_Handle container,
4657 Dart_Handle name,
4658 bool final,
4659 const char* initial_value) {
4660 Dart_Handle result;
4661
4662 // Make sure we have the right initial value.
4663 result = Dart_GetField(container, name);
4664 EXPECT_VALID(result);
4665 const char* value = "";
4666 EXPECT_VALID(Dart_StringToCString(result, &value));
4667 EXPECT_STREQ(initial_value, value);
4668
4669 // Use a unique expected value.
4670 static int counter = 0;
4671 char buffer[256];
4672 Utils::SNPrint(buffer, 256, "Expected%d", ++counter);
4673
4674 // Try to change the field value.
4675 result = Dart_SetField(container, name, NewString(buffer));
4676 if (final) {
4677 EXPECT(Dart_IsError(result));
4678 } else {
4679 EXPECT_VALID(result);
4680 }
4681
4682 // Make sure we have the right final value.
4683 result = Dart_GetField(container, name);
4684 EXPECT_VALID(result);
4685 EXPECT_VALID(Dart_StringToCString(result, &value));
4686 if (final) {
4687 EXPECT_STREQ(initial_value, value);
4688 } else {
4689 EXPECT_STREQ(buffer, value);
4690 }
4691}
4692
4693static void TestFieldNotFound(Dart_Handle container, Dart_Handle name) {
4694 EXPECT_ERROR(Dart_GetField(container, name), "NoSuchMethodError");
4695 EXPECT_ERROR(Dart_SetField(container, name, Dart_Null()),
4696 "NoSuchMethodError");
4697}
4698
4699TEST_CASE(DartAPI_FieldAccess) {
4700 const char* kScriptChars =
4701 "class BaseFields {\n"
4702 " BaseFields()\n"
4703 " : this.inherited_fld = 'inherited' {\n"
4704 " }\n"
4705 " var inherited_fld;\n"
4706 " static var non_inherited_fld;\n"
4707 "}\n"
4708 "\n"
4709 "class Fields extends BaseFields {\n"
4710 " Fields()\n"
4711 " : this.instance_fld = 'instance',\n"
4712 " this._instance_fld = 'hidden instance',\n"
4713 " this.final_instance_fld = 'final instance',\n"
4714 " this._final_instance_fld = 'hidden final instance' {\n"
4715 " instance_getset_fld = 'instance getset';\n"
4716 " _instance_getset_fld = 'hidden instance getset';\n"
4717 " }\n"
4718 "\n"
4719 " static Init() {\n"
4720 " static_fld = 'static';\n"
4721 " _static_fld = 'hidden static';\n"
4722 " static_getset_fld = 'static getset';\n"
4723 " _static_getset_fld = 'hidden static getset';\n"
4724 " }\n"
4725 "\n"
4726 " var instance_fld;\n"
4727 " var _instance_fld;\n"
4728 " final final_instance_fld;\n"
4729 " final _final_instance_fld;\n"
4730 " static var static_fld;\n"
4731 " static var _static_fld;\n"
4732 " static const const_static_fld = 'const static';\n"
4733 " static const _const_static_fld = 'hidden const static';\n"
4734 "\n"
4735 " get instance_getset_fld { return _gs_fld1; }\n"
4736 " void set instance_getset_fld(var value) { _gs_fld1 = value; }\n"
4737 " get _instance_getset_fld { return _gs_fld2; }\n"
4738 " void set _instance_getset_fld(var value) { _gs_fld2 = value; }\n"
4739 " var _gs_fld1;\n"
4740 " var _gs_fld2;\n"
4741 "\n"
4742 " static get static_getset_fld { return _gs_fld3; }\n"
4743 " static void set static_getset_fld(var value) { _gs_fld3 = value; }\n"
4744 " static get _static_getset_fld { return _gs_fld4; }\n"
4745 " static void set _static_getset_fld(var value) { _gs_fld4 = value; }\n"
4746 " static var _gs_fld3;\n"
4747 " static var _gs_fld4;\n"
4748 "}\n"
4749 "var top_fld;\n"
4750 "var _top_fld;\n"
4751 "const const_top_fld = 'const top';\n"
4752 "const _const_top_fld = 'hidden const top';\n"
4753 "\n"
4754 "get top_getset_fld { return _gs_fld5; }\n"
4755 "void set top_getset_fld(var value) { _gs_fld5 = value; }\n"
4756 "get _top_getset_fld { return _gs_fld6; }\n"
4757 "void set _top_getset_fld(var value) { _gs_fld6 = value; }\n"
4758 "var _gs_fld5;\n"
4759 "var _gs_fld6;\n"
4760 "\n"
4761 "Fields test() {\n"
4762 " Fields.Init();\n"
4763 " top_fld = 'top';\n"
4764 " _top_fld = 'hidden top';\n"
4765 " top_getset_fld = 'top getset';\n"
4766 " _top_getset_fld = 'hidden top getset';\n"
4767 " return new Fields();\n"
4768 "}\n";
4769 const char* kImportedScriptChars =
4770 "library library_name;\n"
4771 "var imported_fld = 'imported';\n"
4772 "var _imported_fld = 'hidden imported';\n"
4773 "get imported_getset_fld { return _gs_fld1; }\n"
4774 "void set imported_getset_fld(var value) { _gs_fld1 = value; }\n"
4775 "get _imported_getset_fld { return _gs_fld2; }\n"
4776 "void set _imported_getset_fld(var value) { _gs_fld2 = value; }\n"
4777 "var _gs_fld1;\n"
4778 "var _gs_fld2;\n"
4779 "void test2() {\n"
4780 " imported_getset_fld = 'imported getset';\n"
4781 " _imported_getset_fld = 'hidden imported getset';\n"
4782 "}\n";
4783
4784 // Shared setup.
4785 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
4786 Dart_Handle type = Dart_GetNonNullableType(lib, NewString("Fields"), 0, NULL);
4787 EXPECT_VALID(type);
4788 Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, NULL);
4789 EXPECT_VALID(instance);
4790 Dart_Handle name;
4791
4792 // Load imported lib.
4793 Dart_Handle imported_lib =
4794 TestCase::LoadTestLibrary("library_url", kImportedScriptChars);
4795 EXPECT_VALID(imported_lib);
4796 Dart_Handle result = Dart_FinalizeLoading(false);
4797 EXPECT_VALID(result);
4798 result = Dart_Invoke(imported_lib, NewString("test2"), 0, NULL);
4799 EXPECT_VALID(result);
4800
4801 // Instance field.
4802 name = NewString("instance_fld");
4803 TestFieldNotFound(lib, name);
4804 TestFieldNotFound(type, name);
4805 TestFieldOk(instance, name, false, "instance");
4806
4807 // Hidden instance field.
4808 name = NewString("_instance_fld");
4809 TestFieldNotFound(lib, name);
4810 TestFieldNotFound(type, name);
4811 TestFieldOk(instance, name, false, "hidden instance");
4812
4813 // Final instance field.
4814 name = NewString("final_instance_fld");
4815 TestFieldNotFound(lib, name);
4816 TestFieldNotFound(type, name);
4817 TestFieldOk(instance, name, true, "final instance");
4818
4819 // Hidden final instance field.
4820 name = NewString("_final_instance_fld");
4821 TestFieldNotFound(lib, name);
4822 TestFieldNotFound(type, name);
4823 TestFieldOk(instance, name, true, "hidden final instance");
4824
4825 // Inherited field.
4826 name = NewString("inherited_fld");
4827 TestFieldNotFound(lib, name);
4828 TestFieldNotFound(type, name);
4829 TestFieldOk(instance, name, false, "inherited");
4830
4831 // Instance get/set field.
4832 name = NewString("instance_getset_fld");
4833 TestFieldNotFound(lib, name);
4834 TestFieldNotFound(type, name);
4835 TestFieldOk(instance, name, false, "instance getset");
4836
4837 // Hidden instance get/set field.
4838 name = NewString("_instance_getset_fld");
4839 TestFieldNotFound(lib, name);
4840 TestFieldNotFound(type, name);
4841 TestFieldOk(instance, name, false, "hidden instance getset");
4842
4843 // Static field.
4844 name = NewString("static_fld");
4845 TestFieldNotFound(lib, name);
4846 TestFieldNotFound(instance, name);
4847 TestFieldOk(type, name, false, "static");
4848
4849 // Hidden static field.
4850 name = NewString("_static_fld");
4851 TestFieldNotFound(lib, name);
4852 TestFieldNotFound(instance, name);
4853 TestFieldOk(type, name, false, "hidden static");
4854
4855 // Static final field.
4856 name = NewString("const_static_fld");
4857 TestFieldNotFound(lib, name);
4858 TestFieldNotFound(instance, name);
4859 TestFieldOk(type, name, true, "const static");
4860
4861 // Hidden static const field.
4862 name = NewString("_const_static_fld");
4863 TestFieldNotFound(lib, name);
4864 TestFieldNotFound(instance, name);
4865 TestFieldOk(type, name, true, "hidden const static");
4866
4867 // Static non-inherited field. Not found at any level.
4868 name = NewString("non_inherited_fld");
4869 TestFieldNotFound(lib, name);
4870 TestFieldNotFound(instance, name);
4871 TestFieldNotFound(type, name);
4872
4873 // Static get/set field.
4874 name = NewString("static_getset_fld");
4875 TestFieldNotFound(lib, name);
4876 TestFieldNotFound(instance, name);
4877 TestFieldOk(type, name, false, "static getset");
4878
4879 // Hidden static get/set field.
4880 name = NewString("_static_getset_fld");
4881 TestFieldNotFound(lib, name);
4882 TestFieldNotFound(instance, name);
4883 TestFieldOk(type, name, false, "hidden static getset");
4884
4885 // Top-Level field.
4886 name = NewString("top_fld");
4887 TestFieldNotFound(type, name);
4888 TestFieldNotFound(instance, name);
4889 TestFieldOk(lib, name, false, "top");
4890
4891 // Hidden top-level field.
4892 name = NewString("_top_fld");
4893 TestFieldNotFound(type, name);
4894 TestFieldNotFound(instance, name);
4895 TestFieldOk(lib, name, false, "hidden top");
4896
4897 // Top-Level final field.
4898 name = NewString("const_top_fld");
4899 TestFieldNotFound(type, name);
4900 TestFieldNotFound(instance, name);
4901 TestFieldOk(lib, name, true, "const top");
4902
4903 // Hidden top-level final field.
4904 name = NewString("_const_top_fld");
4905 TestFieldNotFound(type, name);
4906 TestFieldNotFound(instance, name);
4907 TestFieldOk(lib, name, true, "hidden const top");
4908
4909 // Top-Level get/set field.
4910 name = NewString("top_getset_fld");
4911 TestFieldNotFound(type, name);
4912 TestFieldNotFound(instance, name);
4913 TestFieldOk(lib, name, false, "top getset");
4914
4915 // Hidden top-level get/set field.
4916 name = NewString("_top_getset_fld");
4917 TestFieldNotFound(type, name);
4918 TestFieldNotFound(instance, name);
4919 TestFieldOk(lib, name, false, "hidden top getset");
4920
4921 // Imported top-Level field.
4922 name = NewString("imported_fld");
4923 TestFieldNotFound(type, name);
4924 TestFieldNotFound(instance, name);
4925 TestFieldNotFound(lib, name);
4926
4927 // Hidden imported top-level field. Not found at any level.
4928 name = NewString("_imported_fld");
4929 TestFieldNotFound(type, name);
4930 TestFieldNotFound(instance, name);
4931 TestFieldNotFound(lib, name);
4932
4933 // Imported top-Level get/set field.
4934 name = NewString("imported_getset_fld");
4935 TestFieldNotFound(type, name);
4936 TestFieldNotFound(instance, name);
4937 TestFieldNotFound(lib, name);
4938
4939 // Hidden imported top-level get/set field. Not found at any level.
4940 name = NewString("_imported_getset_fld");
4941 TestFieldNotFound(type, name);
4942 TestFieldNotFound(instance, name);
4943 TestFieldNotFound(lib, name);
4944}
4945
4946TEST_CASE(DartAPI_SetField_FunnyValue) {
4947 const char* kScriptChars = "var top;\n";
4948
4949 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
4950 Dart_Handle name = NewString("top");
4951 bool value;
4952
4953 // Test that you can set the field to a good value.
4954 EXPECT_VALID(Dart_SetField(lib, name, Dart_True()));
4955 Dart_Handle result = Dart_GetField(lib, name);
4956 EXPECT_VALID(result);
4957 EXPECT(Dart_IsBoolean(result));
4958 EXPECT_VALID(Dart_BooleanValue(result, &value));
4959 EXPECT(value);
4960
4961 // Test that you can set the field to null
4962 EXPECT_VALID(Dart_SetField(lib, name, Dart_Null()));
4963 result = Dart_GetField(lib, name);
4964 EXPECT_VALID(result);
4965 EXPECT(Dart_IsNull(result));
4966
4967 // Pass a non-instance handle.
4968 result = Dart_SetField(lib, name, lib);
4969 EXPECT_ERROR(
4970 result, "Dart_SetField expects argument 'value' to be of type Instance.");
4971
4972 // Pass an error handle. The error is contagious.
4973 result = Dart_SetField(lib, name, Api::NewError("myerror"));
4974 EXPECT(Dart_IsError(result));
4975 EXPECT_STREQ("myerror", Dart_GetError(result));
4976}
4977
4978TEST_CASE(DartAPI_SetField_BadType) {
4979 const char* kScriptChars =
4980 TestCase::IsNNBD() ? "late int foo;\n" : "int foo;\n";
4981 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
4982 Dart_Handle name = NewString("foo");
4983 Dart_Handle result = Dart_SetField(lib, name, Dart_True());
4984 EXPECT(Dart_IsError(result));
4985 EXPECT_SUBSTRING("type 'bool' is not a subtype of type 'int' of 'foo'",
4986 Dart_GetError(result));
4987}
4988
4989void NativeFieldLookup(Dart_NativeArguments args) {
4990 UNREACHABLE();
4991}
4992
4993static Dart_NativeFunction native_field_lookup(Dart_Handle name,
4994 int argument_count,
4995 bool* auto_setup_scope) {
4996 ASSERT(auto_setup_scope != NULL);
4997 *auto_setup_scope = false;
4998 return reinterpret_cast<Dart_NativeFunction>(&NativeFieldLookup);
4999}
5000
5001TEST_CASE(DartAPI_InjectNativeFields2) {
5002 // clang-format off
5003 auto kScriptChars = Utils::CStringUniquePtr(
5004 OS::SCreate(nullptr,
5005 "class NativeFields extends NativeFieldsWrapper {\n"
5006 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5007 " int fld1;\n"
5008 " final int fld;\n"
5009 " static int%s fld3;\n"
5010 " static const int fld4 = 10;\n"
5011 "}\n"
5012 "NativeFields testMain() {\n"
5013 " NativeFields obj = new NativeFields(10, 20);\n"
5014 " return obj;\n"
5015 "}\n",
5016 TestCase::NullableTag()), std::free);
5017 // clang-format on
5018
5019 Dart_Handle result;
5020 // Create a test library and Load up a test script in it.
5021 Dart_Handle lib =
5022 TestCase::LoadTestScript(kScriptChars.get(), NULL, USER_TEST_URI, false);
5023
5024 // Invoke a function which returns an object of type NativeFields.
5025 result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
5026
5027 // We expect this to fail as class "NativeFields" extends
5028 // "NativeFieldsWrapper" and there is no definition of it either
5029 // in the dart code or through the native field injection mechanism.
5030 EXPECT(Dart_IsError(result));
5031}
5032
5033TEST_CASE(DartAPI_InjectNativeFields3) {
5034 // clang-format off
5035 auto kScriptChars = Utils::CStringUniquePtr(
5036 OS::SCreate(nullptr,
5037 "import 'dart:nativewrappers';"
5038 "class NativeFields extends NativeFieldWrapperClass2 {\n"
5039 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5040 " int fld1;\n"
5041 " final int fld2;\n"
5042 " static int%s fld3;\n"
5043 " static const int fld4 = 10;\n"
5044 "}\n"
5045 "NativeFields testMain() {\n"
5046 " NativeFields obj = new NativeFields(10, 20);\n"
5047 " return obj;\n"
5048 "}\n",
5049 TestCase::NullableTag()), std::free);
5050 // clang-format on
5051 Dart_Handle result;
5052 const int kNumNativeFields = 2;
5053
5054 // Load up a test script in the test library.
5055 Dart_Handle lib =
5056 TestCase::LoadTestScript(kScriptChars.get(), native_field_lookup);
5057
5058 // Invoke a function which returns an object of type NativeFields.
5059 result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
5060 EXPECT_VALID(result);
5061 CHECK_API_SCOPE(thread);
5062 TransitionNativeToVM transition(thread);
5063 HANDLESCOPE(thread);
5064 Instance& obj = Instance::Handle();
5065 obj ^= Api::UnwrapHandle(result);
5066 const Class& cls = Class::Handle(obj.clazz());
5067 // We expect the newly created "NativeFields" object to have
5068 // 2 dart instance fields (fld1, fld2) and a reference to the native fields.
5069 // Hence the size of an instance of "NativeFields" should be
5070 // (1 + 2) * kWordSize + size of object header.
5071 // We check to make sure the instance size computed by the VM matches
5072 // our expectations.
5073 intptr_t header_size = sizeof(ObjectLayout);
5074 EXPECT_EQ(
5075 Utils::RoundUp(((1 + 2) * kWordSize) + header_size, kObjectAlignment),
5076 cls.host_instance_size());
5077 EXPECT_EQ(kNumNativeFields, cls.num_native_fields());
5078}
5079
5080TEST_CASE(DartAPI_InjectNativeFields4) {
5081 // clang-format off
5082 auto kScriptChars = Utils::CStringUniquePtr(
5083 OS::SCreate(nullptr,
5084 "class NativeFields extends NativeFieldsWrapperClass2 {\n"
5085 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5086 " int fld1;\n"
5087 " final int fld;\n"
5088 " static int%s fld3;\n"
5089 " static const int fld4 = 10;\n"
5090 "}\n"
5091 "NativeFields testMain() {\n"
5092 " NativeFields obj = new NativeFields(10, 20);\n"
5093 " return obj;\n"
5094 "}\n",
5095 TestCase::NullableTag()), std::free);
5096 // clang-format on
5097 Dart_Handle result;
5098 // Load up a test script in the test library.
5099 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(), NULL);
5100
5101 // Invoke a function which returns an object of type NativeFields.
5102 result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
5103
5104 USE(result);
5105#if 0
5106 // TODO(12455) Need better validation.
5107 // We expect the test script to fail finalization with the error below:
5108 EXPECT(Dart_IsError(result));
5109 Dart_Handle expected_error = DartUtils::NewError(
5110 "'dart:test-lib': Error: line 1 pos 36: "
5111 "class 'NativeFields' is trying to extend a native fields class, "
5112 "but library '%s' has no native resolvers",
5113 TestCase::url());
5114 EXPECT_SUBSTRING(Dart_GetError(expected_error), Dart_GetError(result));
5115#endif
5116}
5117
5118static const int kTestNumNativeFields = 2;
5119static const intptr_t kNativeField1Value = 30;
5120static const intptr_t kNativeField2Value = 40;
5121
5122void TestNativeFieldsAccess_init(Dart_NativeArguments args) {
5123 Dart_Handle receiver = Dart_GetNativeArgument(args, 0);
5124 Dart_SetNativeInstanceField(receiver, 0, kNativeField1Value);
5125 Dart_SetNativeInstanceField(receiver, 1, kNativeField2Value);
5126}
5127
5128void TestNativeFieldsAccess_access(Dart_NativeArguments args) {
5129 intptr_t field_values[kTestNumNativeFields];
5130 Dart_Handle result = Dart_GetNativeFieldsOfArgument(
5131 args, 0, kTestNumNativeFields, field_values);
5132 EXPECT_VALID(result);
5133 EXPECT_EQ(kNativeField1Value, field_values[0]);
5134 EXPECT_EQ(kNativeField2Value, field_values[1]);
5135 result = Dart_GetNativeFieldsOfArgument(args, 1, kTestNumNativeFields,
5136 field_values);
5137 EXPECT_VALID(result);
5138 EXPECT_EQ(0, field_values[0]);
5139 EXPECT_EQ(0, field_values[1]);
5140}
5141
5142static Dart_NativeFunction TestNativeFieldsAccess_lookup(Dart_Handle name,
5143 int argument_count,
5144 bool* auto_scope) {
5145 ASSERT(auto_scope != NULL);
5146 *auto_scope = true;
5147 TransitionNativeToVM transition(Thread::Current());
5148 const Object& obj = Object::Handle(Api::UnwrapHandle(name));
5149 if (!obj.IsString()) {
5150 return NULL;
5151 }
5152 const char* function_name = obj.ToCString();
5153 ASSERT(function_name != NULL);
5154 if (strcmp(function_name, "TestNativeFieldsAccess_init") == 0) {
5155 return reinterpret_cast<Dart_NativeFunction>(&TestNativeFieldsAccess_init);
5156 } else if (strcmp(function_name, "TestNativeFieldsAccess_access") == 0) {
5157 return reinterpret_cast<Dart_NativeFunction>(
5158 &TestNativeFieldsAccess_access);
5159 } else {
5160 return NULL;
5161 }
5162}
5163
5164TEST_CASE(DartAPI_TestNativeFieldsAccess) {
5165 const char* nullable_tag = TestCase::NullableTag();
5166 // clang-format off
5167 auto kScriptChars = Utils::CStringUniquePtr(
5168 OS::SCreate(
5169 nullptr,
5170 "import 'dart:nativewrappers';"
5171 "class NativeFields extends NativeFieldWrapperClass2 {\n"
5172 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5173 " int fld1;\n"
5174 " final int fld2;\n"
5175 " static int%s fld3;\n"
5176 " static const int fld4 = 10;\n"
5177 " int%s initNativeFlds() native 'TestNativeFieldsAccess_init';\n"
5178 " int%s accessNativeFlds(int%s i) native "
5179 "'TestNativeFieldsAccess_access';\n"
5180 "}\n"
5181 "NativeFields testMain() {\n"
5182 " NativeFields obj = new NativeFields(10, 20);\n"
5183 " obj.initNativeFlds();\n"
5184 " obj.accessNativeFlds(null);\n"
5185 " return obj;\n"
5186 "}\n",
5187 nullable_tag, nullable_tag, nullable_tag, nullable_tag),
5188 std::free);
5189 // clang-format on
5190
5191 // Load up a test script in the test library.
5192 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(),
5193 TestNativeFieldsAccess_lookup);
5194
5195 // Invoke a function which returns an object of type NativeFields.
5196 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
5197 EXPECT_VALID(result);
5198}
5199
5200TEST_CASE(DartAPI_InjectNativeFieldsSuperClass) {
5201 const char* kScriptChars =
5202 "import 'dart:nativewrappers';"
5203 "class NativeFieldsSuper extends NativeFieldWrapperClass1 {\n"
5204 " NativeFieldsSuper() : fld1 = 42 {}\n"
5205 " int fld1;\n"
5206 "}\n"
5207 "class NativeFields extends NativeFieldsSuper {\n"
5208 " fld() => fld1;\n"
5209 "}\n"
5210 "int testMain() {\n"
5211 " NativeFields obj = new NativeFields();\n"
5212 " return obj.fld();\n"
5213 "}\n";
5214 Dart_Handle result;
5215 // Load up a test script in the test library.
5216 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, native_field_lookup);
5217
5218 // Invoke a function which returns an object of type NativeFields.
5219 result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
5220
5221 EXPECT_VALID(result);
5222 EXPECT(Dart_IsInteger(result));
5223 int64_t value = 0;
5224 result = Dart_IntegerToInt64(result, &value);
5225 EXPECT_VALID(result);
5226 EXPECT_EQ(42, value);
5227}
5228
5229static void TestNativeFields(Dart_Handle retobj) {
5230 // Access and set various instance fields of the object.
5231 Dart_Handle result = Dart_GetField(retobj, NewString("fld3"));
5232 EXPECT(Dart_IsError(result));
5233 result = Dart_GetField(retobj, NewString("fld0"));
5234 EXPECT_VALID(result);
5235 EXPECT(Dart_IsNull(result));
5236 result = Dart_GetField(retobj, NewString("fld1"));
5237 EXPECT_VALID(result);
5238 int64_t value = 0;
5239 result = Dart_IntegerToInt64(result, &value);
5240 EXPECT_EQ(10, value);
5241 result = Dart_GetField(retobj, NewString("fld2"));
5242 EXPECT_VALID(result);
5243 result = Dart_IntegerToInt64(result, &value);
5244 EXPECT_EQ(20, value);
5245 result = Dart_SetField(retobj, NewString("fld2"), Dart_NewInteger(40));
5246 EXPECT(Dart_IsError(result));
5247 result = Dart_SetField(retobj, NewString("fld1"), Dart_NewInteger(40));
5248 EXPECT_VALID(result);
5249 result = Dart_GetField(retobj, NewString("fld1"));
5250 EXPECT_VALID(result);
5251 result = Dart_IntegerToInt64(result, &value);
5252 EXPECT_EQ(40, value);
5253
5254 // Now access and set various native instance fields of the returned object.
5255 const int kNativeFld0 = 0;
5256 const int kNativeFld1 = 1;
5257 const int kNativeFld2 = 2;
5258 const int kNativeFld3 = 3;
5259 const int kNativeFld4 = 4;
5260 int field_count = 0;
5261 intptr_t field_value = 0;
5262 EXPECT_VALID(Dart_GetNativeInstanceFieldCount(retobj, &field_count));
5263 EXPECT_EQ(4, field_count);
5264 result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &field_value);
5265 EXPECT(Dart_IsError(result));
5266 result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &field_value);
5267 EXPECT_VALID(result);
5268 EXPECT_EQ(0, field_value);
5269 result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &field_value);
5270 EXPECT_VALID(result);
5271 EXPECT_EQ(0, field_value);
5272 result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &field_value);
5273 EXPECT_VALID(result);
5274 EXPECT_EQ(0, field_value);
5275 result = Dart_GetNativeInstanceField(retobj, kNativeFld3, &field_value);
5276 EXPECT_VALID(result);
5277 EXPECT_EQ(0, field_value);
5278 result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
5279 EXPECT(Dart_IsError(result));
5280 result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 4);
5281 EXPECT_VALID(result);
5282 result = Dart_SetNativeInstanceField(retobj, kNativeFld1, 40);
5283 EXPECT_VALID(result);
5284 result = Dart_SetNativeInstanceField(retobj, kNativeFld2, 400);
5285 EXPECT_VALID(result);
5286 result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 4000);
5287 EXPECT_VALID(result);
5288 result = Dart_GetNativeInstanceField(retobj, kNativeFld3, &field_value);
5289 EXPECT_VALID(result);
5290 EXPECT_EQ(4000, field_value);
5291
5292 // Now re-access various dart instance fields of the returned object
5293 // to ensure that there was no corruption while setting native fields.
5294 result = Dart_GetField(retobj, NewString("fld1"));
5295 EXPECT_VALID(result);
5296 result = Dart_IntegerToInt64(result, &value);
5297 EXPECT_EQ(40, value);
5298 result = Dart_GetField(retobj, NewString("fld2"));
5299 EXPECT_VALID(result);
5300 result = Dart_IntegerToInt64(result, &value);
5301 EXPECT_EQ(20, value);
5302}
5303
5304TEST_CASE(DartAPI_ImplicitNativeFieldAccess) {
5305 const char* nullable_tag = TestCase::NullableTag();
5306 // clang-format off
5307 auto kScriptChars = Utils::CStringUniquePtr(
5308 OS::SCreate(nullptr,
5309 "import 'dart:nativewrappers';"
5310 "class NativeFields extends NativeFieldWrapperClass4 {\n"
5311 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5312 " int%s fld0;\n"
5313 " int fld1;\n"
5314 " final int fld2;\n"
5315 " static int%s fld3;\n"
5316 " static const int fld4 = 10;\n"
5317 "}\n"
5318 "NativeFields testMain() {\n"
5319 " NativeFields obj = new NativeFields(10, 20);\n"
5320 " return obj;\n"
5321 "}\n",
5322 nullable_tag, nullable_tag),
5323 std::free);
5324 // clang-format on
5325 // Load up a test script in the test library.
5326 Dart_Handle lib =
5327 TestCase::LoadTestScript(kScriptChars.get(), native_field_lookup);
5328
5329 // Invoke a function which returns an object of type NativeFields.
5330 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
5331 EXPECT_VALID(retobj);
5332
5333 // Now access and set various instance fields of the returned object.
5334 TestNativeFields(retobj);
5335}
5336
5337TEST_CASE(DartAPI_NegativeNativeFieldAccess) {
5338 // clang-format off
5339 auto kScriptChars = Utils::CStringUniquePtr(
5340 OS::SCreate(nullptr,
5341 "import 'dart:nativewrappers';\n"
5342 "class NativeFields {\n"
5343 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5344 " int fld1;\n"
5345 " final int fld2;\n"
5346 " static int%s fld3;\n"
5347 " static const int fld4 = 10;\n"
5348 "}\n"
5349 "NativeFields testMain1() {\n"
5350 " NativeFields obj = new NativeFields(10, 20);\n"
5351 " return obj;\n"
5352 "}\n"
5353 "Function testMain2() {\n"
5354 " return () {};\n"
5355 "}\n",
5356 TestCase::NullableTag()),
5357 std::free);
5358 // clang-format on
5359
5360 Dart_Handle result;
5361 CHECK_API_SCOPE(thread);
5362
5363 // Create a test library and Load up a test script in it.
5364 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(), NULL);
5365
5366 // Invoke a function which returns an object of type NativeFields.
5367 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain1"), 0, NULL);
5368 EXPECT_VALID(retobj);
5369
5370 // Now access and set various native instance fields of the returned object.
5371 // All of these tests are expected to return failure as there are no
5372 // native fields in an instance of NativeFields.
5373 const int kNativeFld0 = 0;
5374 const int kNativeFld1 = 1;
5375 const int kNativeFld2 = 2;
5376 const int kNativeFld3 = 3;
5377 const int kNativeFld4 = 4;
5378 intptr_t value = 0;
5379 result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &value);
5380 EXPECT(Dart_IsError(result));
5381 result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &value);
5382 EXPECT(Dart_IsError(result));
5383 result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &value);
5384 EXPECT(Dart_IsError(result));
5385 result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &value);
5386 EXPECT(Dart_IsError(result));
5387 result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
5388 EXPECT(Dart_IsError(result));
5389 result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 40);
5390 EXPECT(Dart_IsError(result));
5391 result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 400);
5392 EXPECT(Dart_IsError(result));
5393
5394 // Invoke a function which returns a closure object.
5395 retobj = Dart_Invoke(lib, NewString("testMain2"), 0, NULL);
5396 EXPECT_VALID(retobj);
5397
5398 result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &value);
5399 EXPECT(Dart_IsError(result));
5400 result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &value);
5401 EXPECT(Dart_IsError(result));
5402 result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &value);
5403 EXPECT(Dart_IsError(result));
5404 result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &value);
5405 EXPECT(Dart_IsError(result));
5406 result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
5407 EXPECT(Dart_IsError(result));
5408 result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 40);
5409 EXPECT(Dart_IsError(result));
5410 result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 400);
5411 EXPECT(Dart_IsError(result));
5412}
5413
5414TEST_CASE(DartAPI_GetStaticField_RunsInitializer) {
5415 const char* kScriptChars =
5416 "class TestClass {\n"
5417 " static const int fld1 = 7;\n"
5418 " static int fld2 = 11;\n"
5419 " static void testMain() {\n"
5420 " }\n"
5421 "}\n";
5422 Dart_Handle result;
5423 // Create a test library and Load up a test script in it.
5424 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
5425 Dart_Handle type =
5426 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, NULL);
5427 EXPECT_VALID(type);
5428
5429 // Invoke a function which returns an object.
5430 result = Dart_Invoke(type, NewString("testMain"), 0, NULL);
5431 EXPECT_VALID(result);
5432
5433 // For uninitialized fields, the getter is returned
5434 result = Dart_GetField(type, NewString("fld1"));
5435 EXPECT_VALID(result);
5436 int64_t value = 0;
5437 result = Dart_IntegerToInt64(result, &value);
5438 EXPECT_EQ(7, value);
5439
5440 result = Dart_GetField(type, NewString("fld2"));
5441 EXPECT_VALID(result);
5442 result = Dart_IntegerToInt64(result, &value);
5443 EXPECT_EQ(11, value);
5444
5445 // Overwrite fld2
5446 result = Dart_SetField(type, NewString("fld2"), Dart_NewInteger(13));
5447 EXPECT_VALID(result);
5448
5449 // We now get the new value for fld2, not the initializer
5450 result = Dart_GetField(type, NewString("fld2"));
5451 EXPECT_VALID(result);
5452 result = Dart_IntegerToInt64(result, &value);
5453 EXPECT_EQ(13, value);
5454}
5455
5456TEST_CASE(DartAPI_GetField_CheckIsolate) {
5457 const char* kScriptChars =
5458 "class TestClass {\n"
5459 " static int fld2 = 11;\n"
5460 " static void testMain() {\n"
5461 " }\n"
5462 "}\n";
5463 Dart_Handle result;
5464 int64_t value = 0;
5465
5466 // Create a test library and Load up a test script in it.
5467 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
5468 Dart_Handle type =
5469 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, NULL);
5470 EXPECT_VALID(type);
5471
5472 result = Dart_GetField(type, NewString("fld2"));
5473 EXPECT_VALID(result);
5474 result = Dart_IntegerToInt64(result, &value);
5475 EXPECT_EQ(11, value);
5476}
5477
5478TEST_CASE(DartAPI_SetField_CheckIsolate) {
5479 const char* kScriptChars =
5480 "class TestClass {\n"
5481 " static int fld2 = 11;\n"
5482 " static void testMain() {\n"
5483 " }\n"
5484 "}\n";
5485 Dart_Handle result;
5486 int64_t value = 0;
5487
5488 // Create a test library and Load up a test script in it.
5489 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
5490 Dart_Handle type =
5491 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, NULL);
5492 EXPECT_VALID(type);
5493
5494 result = Dart_SetField(type, NewString("fld2"), Dart_NewInteger(13));
5495 EXPECT_VALID(result);
5496
5497 result = Dart_GetField(type, NewString("fld2"));
5498 EXPECT_VALID(result);
5499 result = Dart_IntegerToInt64(result, &value);
5500 EXPECT_EQ(13, value);
5501}
5502
5503TEST_CASE(DartAPI_New) {
5504 const char* kScriptChars =
5505 "class MyClass {\n"
5506 " MyClass() : foo = 7 {}\n"
5507 " MyClass.named(value) : foo = value {}\n"
5508 " MyClass._hidden(value) : foo = -value {}\n"
5509 " MyClass.exception(value) : foo = value {\n"
5510 " throw 'ConstructorDeath';\n"
5511 " }\n"
5512 " factory MyClass.multiply(value) {\n"
5513 " return new MyClass.named(value * 100);\n"
5514 " }\n"
5515 " factory MyClass.nullo() {\n"
5516 " return null;\n"
5517 " }\n"
5518 " var foo;\n"
5519 "}\n"
5520 "\n"
5521 "abstract class MyExtraHop {\n"
5522 " factory MyExtraHop.hop(value) = MyClass.named;\n"
5523 "}\n"
5524 "\n"
5525 "abstract class MyInterface {\n"
5526 " factory MyInterface.named(value) = MyExtraHop.hop;\n"
5527 " factory MyInterface.multiply(value) = MyClass.multiply;\n"
5528 " MyInterface.notfound(value);\n"
5529 "}\n";
5530
5531 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
5532 Dart_Handle type =
5533 Dart_GetNonNullableType(lib, NewString("MyClass"), 0, NULL);
5534 EXPECT_VALID(type);
5535 Dart_Handle intf =
5536 Dart_GetNonNullableType(lib, NewString("MyInterface"), 0, NULL);
5537 EXPECT_VALID(intf);
5538 Dart_Handle args[1];
5539 args[0] = Dart_NewInteger(11);
5540 Dart_Handle bad_args[1];
5541 bad_args[0] = Dart_NewApiError("myerror");
5542
5543 // Allocate and Invoke the unnamed constructor passing in Dart_Null.
5544 Dart_Handle result = Dart_New(type, Dart_Null(), 0, NULL);
5545 EXPECT_VALID(result);
5546 bool instanceOf = false;
5547 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
5548 EXPECT(instanceOf);
5549 int64_t int_value = 0;
5550 Dart_Handle foo = Dart_GetField(result, NewString("foo"));
5551 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5552 EXPECT_EQ(7, int_value);
5553
5554 // Allocate without a constructor.
5555 Dart_Handle obj = Dart_Allocate(type);
5556 EXPECT_VALID(obj);
5557 instanceOf = false;
5558 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
5559 EXPECT(instanceOf);
5560 foo = Dart_GetField(obj, NewString("foo"));
5561 EXPECT(Dart_IsNull(foo));
5562
5563 // Allocate and Invoke the unnamed constructor passing in an empty string.
5564 result = Dart_New(type, Dart_EmptyString(), 0, NULL);
5565 EXPECT_VALID(result);
5566 instanceOf = false;
5567 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
5568 EXPECT(instanceOf);
5569 int_value = 0;
5570 foo = Dart_GetField(result, NewString("foo"));
5571 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5572 EXPECT_EQ(7, int_value);
5573
5574 // Allocate object and invoke the unnamed constructor with an empty string.
5575 obj = Dart_Allocate(type);
5576 EXPECT_VALID(obj);
5577 instanceOf = false;
5578 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
5579 EXPECT(instanceOf);
5580 // Use the empty string to invoke the unnamed constructor.
5581 result = Dart_InvokeConstructor(obj, Dart_EmptyString(), 0, NULL);
5582 EXPECT_VALID(result);
5583 int_value = 0;
5584 foo = Dart_GetField(result, NewString("foo"));
5585 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5586 EXPECT_EQ(7, int_value);
5587 // use Dart_Null to invoke the unnamed constructor.
5588 result = Dart_InvokeConstructor(obj, Dart_Null(), 0, NULL);
5589 EXPECT_VALID(result);
5590 int_value = 0;
5591 foo = Dart_GetField(result, NewString("foo"));
5592 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5593 EXPECT_EQ(7, int_value);
5594
5595 // Invoke a named constructor.
5596 result = Dart_New(type, NewString("named"), 1, args);
5597 EXPECT_VALID(result);
5598 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
5599 EXPECT(instanceOf);
5600 int_value = 0;
5601 foo = Dart_GetField(result, NewString("foo"));
5602 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5603 EXPECT_EQ(11, int_value);
5604
5605 // Allocate object and invoke a named constructor.
5606 obj = Dart_Allocate(type);
5607 EXPECT_VALID(obj);
5608 instanceOf = false;
5609 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
5610 EXPECT(instanceOf);
5611 result = Dart_InvokeConstructor(obj, NewString("named"), 1, args);
5612 EXPECT_VALID(result);
5613 int_value = 0;
5614 foo = Dart_GetField(result, NewString("foo"));
5615 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5616 EXPECT_EQ(11, int_value);
5617
5618 // Invoke a hidden named constructor.
5619 result = Dart_New(type, NewString("_hidden"), 1, args);
5620 EXPECT_VALID(result);
5621 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
5622 EXPECT(instanceOf);
5623 int_value = 0;
5624 foo = Dart_GetField(result, NewString("foo"));
5625 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5626 EXPECT_EQ(-11, int_value);
5627
5628 // Allocate object and invoke a hidden named constructor.
5629 obj = Dart_Allocate(type);
5630 EXPECT_VALID(obj);
5631 instanceOf = false;
5632 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
5633 EXPECT(instanceOf);
5634 result = Dart_InvokeConstructor(obj, NewString("_hidden"), 1, args);
5635 EXPECT_VALID(result);
5636 int_value = 0;
5637 foo = Dart_GetField(result, NewString("foo"));
5638 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5639 EXPECT_EQ(-11, int_value);
5640
5641 // Allocate object and Invoke a constructor which throws an exception.
5642 obj = Dart_Allocate(type);
5643 EXPECT_VALID(obj);
5644 instanceOf = false;
5645 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
5646 EXPECT(instanceOf);
5647 result = Dart_InvokeConstructor(obj, NewString("exception"), 1, args);
5648 EXPECT_ERROR(result, "ConstructorDeath");
5649
5650 // Invoke a factory constructor.
5651 result = Dart_New(type, NewString("multiply"), 1, args);
5652 EXPECT_VALID(result);
5653 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
5654 EXPECT(instanceOf);
5655 int_value = 0;
5656 foo = Dart_GetField(result, NewString("foo"));
5657 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5658 EXPECT_EQ(1100, int_value);
5659
5660 // Invoke a factory constructor which returns null.
5661 result = Dart_New(type, NewString("nullo"), 0, NULL);
5662 EXPECT_VALID(result);
5663 EXPECT(Dart_IsNull(result));
5664
5665 // Pass an error class object. Error is passed through.
5666 result = Dart_New(Dart_NewApiError("myerror"), NewString("named"), 1, args);
5667 EXPECT_ERROR(result, "myerror");
5668
5669 // Pass a bad class object.
5670 result = Dart_New(Dart_Null(), NewString("named"), 1, args);
5671 EXPECT_ERROR(result, "Dart_New expects argument 'type' to be non-null.");
5672
5673 // Pass a negative arg count.
5674 result = Dart_New(type, NewString("named"), -1, args);
5675 EXPECT_ERROR(
5676 result,
5677 "Dart_New expects argument 'number_of_arguments' to be non-negative.");
5678
5679 // Pass the wrong arg count.
5680 result = Dart_New(type, NewString("named"), 0, NULL);
5681 EXPECT_ERROR(
5682 result,
5683 "Dart_New: wrong argument count for constructor 'MyClass.named': "
5684 "0 passed, 1 expected.");
5685
5686 // Pass a bad argument. Error is passed through.
5687 result = Dart_New(type, NewString("named"), 1, bad_args);
5688 EXPECT_ERROR(result, "myerror");
5689
5690 // Pass a bad constructor name.
5691 result = Dart_New(type, Dart_NewInteger(55), 1, args);
5692 EXPECT_ERROR(
5693 result,
5694 "Dart_New expects argument 'constructor_name' to be of type String.");
5695
5696 // Invoke a missing constructor.
5697 result = Dart_New(type, NewString("missing"), 1, args);
5698 EXPECT_ERROR(result,
5699 "Dart_New: could not find constructor 'MyClass.missing'.");
5700
5701 // Invoke a constructor which throws an exception.
5702 result = Dart_New(type, NewString("exception"), 1, args);
5703 EXPECT_ERROR(result, "ConstructorDeath");
5704
5705 // Invoke two-hop redirecting factory constructor.
5706 result = Dart_New(intf, NewString("named"), 1, args);
5707 EXPECT_VALID(result);
5708 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
5709 EXPECT(instanceOf);
5710 int_value = 0;
5711 foo = Dart_GetField(result, NewString("foo"));
5712 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5713 EXPECT_EQ(11, int_value);
5714
5715 // Invoke one-hop redirecting factory constructor.
5716 result = Dart_New(intf, NewString("multiply"), 1, args);
5717 EXPECT_VALID(result);
5718 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
5719 EXPECT(instanceOf);
5720 int_value = 0;
5721 foo = Dart_GetField(result, NewString("foo"));
5722 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
5723 EXPECT_EQ(1100, int_value);
5724
5725 // Invoke a constructor that is missing in the interface.
5726 result = Dart_New(intf, Dart_Null(), 0, NULL);
5727 EXPECT_ERROR(result, "Dart_New: could not find constructor 'MyInterface.'.");
5728
5729 // Invoke abstract constructor that is present in the interface.
5730 result = Dart_New(intf, NewString("notfound"), 1, args);
5731 EXPECT_VALID(result);
5732 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
5733 EXPECT(!instanceOf);
5734}
5735
5736TEST_CASE(DartAPI_New_Issue2971) {
5737 // Issue 2971: We were unable to use Dart_New to construct an
5738 // instance of List, due to problems implementing interface
5739 // factories.
5740 Dart_Handle core_lib = Dart_LookupLibrary(NewString("dart:core"));
5741 EXPECT_VALID(core_lib);
5742 Dart_Handle list_type =
5743 Dart_GetNonNullableType(core_lib, NewString("List"), 0, NULL);
5744 EXPECT_VALID(list_type);
5745
5746 const int kNumArgs = 1;
5747 Dart_Handle args[kNumArgs];
5748 args[0] = Dart_NewInteger(1);
5749 Dart_Handle list_obj = Dart_New(list_type, Dart_Null(), kNumArgs, args);
5750 EXPECT_VALID(list_obj);
5751 EXPECT(Dart_IsList(list_obj));
5752}
5753
5754TEST_CASE(DartAPI_NewListOf) {
5755 const char* kScriptChars =
5756 "String expectListOfString(List<String> o) => '${o.first}';\n"
5757 "String expectListOfDynamic(List<dynamic> o) => '${o.first}';\n"
5758 "String expectListOfInt(List<int> o) => '${o.first}';\n";
5759 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
5760
5761 const int kNumArgs = 1;
5762 Dart_Handle args[kNumArgs];
5763 const char* str;
5764 Dart_Handle result;
5765 Dart_Handle string_list = Dart_NewListOf(Dart_CoreType_String, 1);
5766 if (!Dart_IsError(string_list)) {
5767 args[0] = string_list;
5768 Dart_Handle result =
5769 Dart_Invoke(lib, NewString("expectListOfString"), kNumArgs, args);
5770 EXPECT_VALID(result);
5771 result = Dart_StringToCString(result, &str);
5772 EXPECT_VALID(result);
5773 EXPECT_STREQ("null", str);
5774 } else {
5775 EXPECT_ERROR(string_list,
5776 "Cannot use legacy types with --sound-null-safety enabled. "
5777 "Use Dart_NewListOfType or Dart_NewListOfTypeFilled instead.");
5778 }
5779
5780 Dart_Handle dynamic_list = Dart_NewListOf(Dart_CoreType_Dynamic, 1);
5781 EXPECT_VALID(dynamic_list);
5782 args[0] = dynamic_list;
5783 result = Dart_Invoke(lib, NewString("expectListOfDynamic"), kNumArgs, args);
5784 EXPECT_VALID(result);
5785 result = Dart_StringToCString(result, &str);
5786 EXPECT_STREQ("null", str);
5787
5788 Dart_Handle int_list = Dart_NewListOf(Dart_CoreType_Int, 1);
5789 if (!Dart_IsError(int_list)) {
5790 args[0] = int_list;
5791 result = Dart_Invoke(lib, NewString("expectListOfInt"), kNumArgs, args);
5792 EXPECT_VALID(result);
5793 result = Dart_StringToCString(result, &str);
5794 EXPECT_STREQ("null", str);
5795 } else {
5796 EXPECT_ERROR(int_list,
5797 "Cannot use legacy types with --sound-null-safety enabled. "
5798 "Use Dart_NewListOfType or Dart_NewListOfTypeFilled instead.");
5799 }
5800}
5801
5802TEST_CASE(DartAPI_NewListOfType) {
5803 const char* kScriptChars =
5804 "class ZXHandle {}\n"
5805 "class ChannelReadResult {\n"
5806 " final List<ZXHandle> handles;\n"
5807 " ChannelReadResult(this.handles);\n"
5808 "}\n"
5809 "void expectListOfString(List<String> _) {}\n"
5810 "void expectListOfDynamic(List<dynamic> _) {}\n"
5811 "void expectListOfVoid(List<void> _) {}\n"
5812 "void expectListOfNever(List<Never> _) {}\n";
5813 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
5814
5815 Dart_Handle zxhandle_type =
5816 Dart_GetNullableType(lib, NewString("ZXHandle"), 0, NULL);
5817 EXPECT_VALID(zxhandle_type);
5818
5819 Dart_Handle zxhandle = Dart_New(zxhandle_type, Dart_Null(), 0, NULL);
5820 EXPECT_VALID(zxhandle);
5821
5822 Dart_Handle zxhandle_list = Dart_NewListOfType(zxhandle_type, 1);
5823 EXPECT_VALID(zxhandle_list);
5824
5825 EXPECT_VALID(Dart_ListSetAt(zxhandle_list, 0, zxhandle));
5826
5827 Dart_Handle readresult_type =
5828 Dart_GetNonNullableType(lib, NewString("ChannelReadResult"), 0, NULL);
5829 EXPECT_VALID(zxhandle_type);
5830
5831 const int kNumArgs = 1;
5832 Dart_Handle args[kNumArgs];
5833 args[0] = zxhandle_list;
5834 EXPECT_VALID(Dart_New(readresult_type, Dart_Null(), kNumArgs, args));
5835
5836 EXPECT_ERROR(
5837 Dart_NewListOfType(Dart_Null(), 1),
5838 "Dart_NewListOfType expects argument 'element_type' to be non-null.");
5839 EXPECT_ERROR(
5840 Dart_NewListOfType(Dart_True(), 1),
5841 "Dart_NewListOfType expects argument 'element_type' to be of type Type.");
5842
5843 Dart_Handle dart_core = Dart_LookupLibrary(NewString("dart:core"));
5844 EXPECT_VALID(dart_core);
5845
5846 Dart_Handle string_type =
5847 Dart_GetNonNullableType(dart_core, NewString("String"), 0, NULL);
5848 EXPECT_VALID(string_type);
5849 Dart_Handle string_list = Dart_NewListOfType(string_type, 0);
5850 EXPECT_VALID(string_list);
5851 args[0] = string_list;
5852 EXPECT_VALID(
5853 Dart_Invoke(lib, NewString("expectListOfString"), kNumArgs, args));
5854
5855 Dart_Handle dynamic_type = Dart_TypeDynamic();
5856 EXPECT_VALID(dynamic_type);
5857 Dart_Handle dynamic_list = Dart_NewListOfType(dynamic_type, 0);
5858 EXPECT_VALID(dynamic_list);
5859 args[0] = dynamic_list;
5860 EXPECT_VALID(
5861 Dart_Invoke(lib, NewString("expectListOfDynamic"), kNumArgs, args));
5862
5863 Dart_Handle void_type = Dart_TypeVoid();
5864 EXPECT_VALID(void_type);
5865 Dart_Handle void_list = Dart_NewListOfType(void_type, 0);
5866 EXPECT_VALID(void_list);
5867 args[0] = void_list;
5868 EXPECT_VALID(Dart_Invoke(lib, NewString("expectListOfVoid"), kNumArgs, args));
5869
5870 Dart_Handle never_type = Dart_TypeNever();
5871 EXPECT_VALID(never_type);
5872 Dart_Handle never_list = Dart_NewListOfType(never_type, 0);
5873 EXPECT_VALID(never_list);
5874 args[0] = never_list;
5875 EXPECT_VALID(
5876 Dart_Invoke(lib, NewString("expectListOfNever"), kNumArgs, args));
5877}
5878
5879TEST_CASE(DartAPI_NewListOfTypeFilled) {
5880 const char* kScriptChars =
5881 "class ZXHandle {}\n"
5882 "class ChannelReadResult {\n"
5883 " final List<ZXHandle> handles;\n"
5884 " ChannelReadResult(this.handles);\n"
5885 "}\n";
5886 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
5887
5888 Dart_Handle zxhandle_type =
5889 Dart_GetNonNullableType(lib, NewString("ZXHandle"), 0, NULL);
5890 EXPECT_VALID(zxhandle_type);
5891
5892 Dart_Handle nullable_zxhandle_type =
5893 Dart_GetNullableType(lib, NewString("ZXHandle"), 0, NULL);
5894 EXPECT_VALID(nullable_zxhandle_type);
5895
5896 Dart_Handle integer = Dart_NewInteger(42);
5897 EXPECT_VALID(integer);
5898
5899 Dart_Handle zxhandle = Dart_New(zxhandle_type, Dart_Null(), 0, NULL);
5900 EXPECT_VALID(zxhandle);
5901
5902 Dart_Handle zxhandle_list =
5903 Dart_NewListOfTypeFilled(zxhandle_type, zxhandle, 1);
5904 EXPECT_VALID(zxhandle_list);
5905
5906 Dart_Handle result = Dart_ListGetAt(zxhandle_list, 0);
5907 EXPECT_VALID(result);
5908
5909 EXPECT(Dart_IdentityEquals(result, zxhandle));
5910
5911 Dart_Handle readresult_type =
5912 Dart_GetNonNullableType(lib, NewString("ChannelReadResult"), 0, NULL);
5913 EXPECT_VALID(zxhandle_type);
5914
5915 const int kNumArgs = 1;
5916 Dart_Handle args[kNumArgs];
5917 args[0] = zxhandle_list;
5918 EXPECT_VALID(Dart_New(readresult_type, Dart_Null(), kNumArgs, args));
5919
5920 EXPECT_ERROR(Dart_NewListOfTypeFilled(Dart_Null(), Dart_Null(), 1),
5921 "Dart_NewListOfTypeFilled expects argument 'element_type' to be "
5922 "non-null.");
5923 EXPECT_ERROR(Dart_NewListOfTypeFilled(Dart_True(), Dart_Null(), 1),
5924 "Dart_NewListOfTypeFilled expects argument 'element_type' to be "
5925 "of type Type.");
5926 EXPECT_ERROR(
5927 Dart_NewListOfTypeFilled(zxhandle_type, Dart_Null(), 1),
5928 "Dart_NewListOfTypeFilled expects argument 'fill_object' to be non-null"
5929 " for a non-nullable 'element_type'");
5930 EXPECT_ERROR(
5931 Dart_NewListOfTypeFilled(zxhandle_type, integer, 1),
5932 "Dart_NewListOfTypeFilled expects argument 'fill_object' to have the same"
5933 " type as 'element_type'.");
5934
5935 EXPECT_VALID(
5936 Dart_NewListOfTypeFilled(nullable_zxhandle_type, Dart_Null(), 1));
5937
5938 // Null is always valid as the fill argument if we're creating an empty list.
5939 EXPECT_VALID(Dart_NewListOfTypeFilled(zxhandle_type, Dart_Null(), 0));
5940}
5941
5942static Dart_Handle PrivateLibName(Dart_Handle lib, const char* str) {
5943 EXPECT(Dart_IsLibrary(lib));
5944 Thread* thread = Thread::Current();
5945 TransitionNativeToVM transition(thread);
5946 const Library& library_obj = Api::UnwrapLibraryHandle(thread->zone(), lib);
5947 const String& name = String::Handle(String::New(str));
5948 return Api::NewHandle(thread, library_obj.PrivateName(name));
5949}
5950
5951TEST_CASE(DartAPI_Invoke) {
5952 const char* kScriptChars =
5953 "class BaseMethods {\n"
5954 " inheritedMethod(arg) => 'inherited $arg';\n"
5955 " static nonInheritedMethod(arg) => 'noninherited $arg';\n"
5956 "}\n"
5957 "\n"
5958 "class Methods extends BaseMethods {\n"
5959 " instanceMethod(arg) => 'instance $arg';\n"
5960 " _instanceMethod(arg) => 'hidden instance $arg';\n"
5961 " static staticMethod(arg) => 'static $arg';\n"
5962 " static _staticMethod(arg) => 'hidden static $arg';\n"
5963 "}\n"
5964 "\n"
5965 "topMethod(arg) => 'top $arg';\n"
5966 "_topMethod(arg) => 'hidden top $arg';\n"
5967 "\n"
5968 "Methods test() {\n"
5969 " return new Methods();\n"
5970 "}\n";
5971
5972 // Shared setup.
5973 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
5974 Dart_Handle type =
5975 Dart_GetNonNullableType(lib, NewString("Methods"), 0, NULL);
5976 EXPECT_VALID(type);
5977 Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, NULL);
5978 EXPECT_VALID(instance);
5979 Dart_Handle args[1];
5980 args[0] = NewString("!!!");
5981 Dart_Handle bad_args[2];
5982 bad_args[0] = NewString("bad1");
5983 bad_args[1] = NewString("bad2");
5984 Dart_Handle result;
5985 Dart_Handle name;
5986 const char* str;
5987
5988 // Instance method.
5989 name = NewString("instanceMethod");
5990 EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
5991 EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
5992 result = Dart_Invoke(instance, name, 1, args);
5993 EXPECT_VALID(result);
5994 result = Dart_StringToCString(result, &str);
5995 EXPECT_STREQ("instance !!!", str);
5996
5997 // Instance method, wrong arg count.
5998 EXPECT_ERROR(Dart_Invoke(instance, name, 2, bad_args),
5999 "Class 'Methods' has no instance method 'instanceMethod'"
6000 " with matching arguments");
6001
6002 name = PrivateLibName(lib, "_instanceMethod");
6003 EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
6004 EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
6005 result = Dart_Invoke(instance, name, 1, args);
6006 EXPECT_VALID(result);
6007 result = Dart_StringToCString(result, &str);
6008 EXPECT_STREQ("hidden instance !!!", str);
6009
6010 // Inherited method.
6011 name = NewString("inheritedMethod");
6012 EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
6013 EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
6014 result = Dart_Invoke(instance, name, 1, args);
6015 EXPECT_VALID(result);
6016 result = Dart_StringToCString(result, &str);
6017 EXPECT_STREQ("inherited !!!", str);
6018
6019 // Static method.
6020 name = NewString("staticMethod");
6021 EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
6022 EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
6023 result = Dart_Invoke(type, name, 1, args);
6024 EXPECT_VALID(result);
6025 result = Dart_StringToCString(result, &str);
6026 EXPECT_STREQ("static !!!", str);
6027
6028 // Static method, wrong arg count.
6029 EXPECT_ERROR(Dart_Invoke(type, name, 2, bad_args),
6030 "NoSuchMethodError: No static method 'staticMethod' with "
6031 "matching arguments");
6032
6033 // Hidden static method.
6034 name = NewString("_staticMethod");
6035 EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
6036 EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
6037 result = Dart_Invoke(type, name, 1, args);
6038 EXPECT_VALID(result);
6039 result = Dart_StringToCString(result, &str);
6040 EXPECT_STREQ("hidden static !!!", str);
6041
6042 // Static non-inherited method. Not found at any level.
6043 name = NewString("non_inheritedMethod");
6044 EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
6045 EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
6046 EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
6047
6048 // Top-Level method.
6049 name = NewString("topMethod");
6050 EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
6051 EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
6052 result = Dart_Invoke(lib, name, 1, args);
6053 EXPECT_VALID(result);
6054 result = Dart_StringToCString(result, &str);
6055 EXPECT_STREQ("top !!!", str);
6056
6057 // Top-level method, wrong arg count.
6058 EXPECT_ERROR(Dart_Invoke(lib, name, 2, bad_args),
6059 "NoSuchMethodError: No top-level method 'topMethod' with "
6060 "matching arguments");
6061
6062 // Hidden top-level method.
6063 name = NewString("_topMethod");
6064 EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
6065 EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
6066 result = Dart_Invoke(lib, name, 1, args);
6067 EXPECT_VALID(result);
6068 result = Dart_StringToCString(result, &str);
6069 EXPECT_STREQ("hidden top !!!", str);
6070}
6071
6072TEST_CASE(DartAPI_Invoke_PrivateStatic) {
6073 const char* kScriptChars =
6074 "class Methods {\n"
6075 " static _staticMethod(arg) => 'hidden static $arg';\n"
6076 "}\n"
6077 "\n";
6078
6079 // Shared setup.
6080 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
6081 Dart_Handle type =
6082 Dart_GetNonNullableType(lib, NewString("Methods"), 0, NULL);
6083 Dart_Handle result;
6084 EXPECT_VALID(type);
6085 Dart_Handle name = NewString("_staticMethod");
6086 EXPECT_VALID(name);
6087
6088 Dart_Handle args[1];
6089 args[0] = NewString("!!!");
6090 result = Dart_Invoke(type, name, 1, args);
6091 EXPECT_VALID(result);
6092
6093 const char* str = NULL;
6094 result = Dart_StringToCString(result, &str);
6095 EXPECT_STREQ("hidden static !!!", str);
6096}
6097
6098TEST_CASE(DartAPI_Invoke_FunnyArgs) {
6099 const char* kScriptChars = "test(arg) => 'hello $arg';\n";
6100
6101 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
6102 Dart_Handle func_name = NewString("test");
6103 Dart_Handle args[1];
6104 const char* str;
6105
6106 // Make sure that valid args yield valid results.
6107 args[0] = NewString("!!!");
6108 Dart_Handle result = Dart_Invoke(lib, func_name, 1, args);
6109 EXPECT_VALID(result);
6110 result = Dart_StringToCString(result, &str);
6111 EXPECT_STREQ("hello !!!", str);
6112
6113 // Make sure that null is legal.
6114 args[0] = Dart_Null();
6115 result = Dart_Invoke(lib, func_name, 1, args);
6116 EXPECT_VALID(result);
6117 result = Dart_StringToCString(result, &str);
6118 EXPECT_STREQ("hello null", str);
6119
6120 // Pass an error handle as the target. The error is propagated.
6121 result = Dart_Invoke(Api::NewError("myerror"), func_name, 1, args);
6122 EXPECT(Dart_IsError(result));
6123 EXPECT_STREQ("myerror", Dart_GetError(result));
6124
6125 // Pass an error handle as the function name. The error is propagated.
6126 result = Dart_Invoke(lib, Api::NewError("myerror"), 1, args);
6127 EXPECT(Dart_IsError(result));
6128 EXPECT_STREQ("myerror", Dart_GetError(result));
6129
6130 // Pass a non-instance handle as a parameter..
6131 args[0] = lib;
6132 result = Dart_Invoke(lib, func_name, 1, args);
6133 EXPECT(Dart_IsError(result));
6134 EXPECT_STREQ("Dart_Invoke expects arguments[0] to be an Instance handle.",
6135 Dart_GetError(result));
6136
6137 // Pass an error handle as a parameter. The error is propagated.
6138 args[0] = Api::NewError("myerror");
6139 result = Dart_Invoke(lib, func_name, 1, args);
6140 EXPECT(Dart_IsError(result));
6141 EXPECT_STREQ("myerror", Dart_GetError(result));
6142}
6143
6144TEST_CASE(DartAPI_Invoke_BadArgs) {
6145 const char* kScriptChars =
6146 "class BaseMethods {\n"
6147 " inheritedMethod(int arg) => 'inherited $arg';\n"
6148 " static nonInheritedMethod(int arg) => 'noninherited $arg';\n"
6149 "}\n"
6150 "\n"
6151 "class Methods extends BaseMethods {\n"
6152 " instanceMethod(int arg) => 'instance $arg';\n"
6153 " _instanceMethod(int arg) => 'hidden instance $arg';\n"
6154 " static staticMethod(int arg) => 'static $arg';\n"
6155 " static _staticMethod(int arg) => 'hidden static $arg';\n"
6156 "}\n"
6157 "\n"
6158 "topMethod(int arg) => 'top $arg';\n"
6159 "_topMethod(int arg) => 'hidden top $arg';\n"
6160 "\n"
6161 "Methods test() {\n"
6162 " return new Methods();\n"
6163 "}\n";
6164
6165#if defined(PRODUCT)
6166 const char* error_msg =
6167 "type '_OneByteString' is not a subtype of type 'int' of 'arg'";
6168#else
6169 const char* error_msg =
6170 "type 'String' is not a subtype of type 'int' of 'arg'";
6171#endif // defined(PRODUCT)
6172
6173 // Shared setup.
6174 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
6175 Dart_Handle type =
6176 Dart_GetNonNullableType(lib, NewString("Methods"), 0, NULL);
6177 EXPECT_VALID(type);
6178 Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, NULL);
6179 EXPECT_VALID(instance);
6180 Dart_Handle args[1];
6181 args[0] = NewString("!!!");
6182 Dart_Handle result;
6183 Dart_Handle name;
6184
6185 // Instance method.
6186 name = NewString("instanceMethod");
6187 result = Dart_Invoke(instance, name, 1, args);
6188 EXPECT(Dart_IsError(result));
6189 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6190
6191 name = PrivateLibName(lib, "_instanceMethod");
6192 result = Dart_Invoke(instance, name, 1, args);
6193 EXPECT(Dart_IsError(result));
6194 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6195
6196 // Inherited method.
6197 name = NewString("inheritedMethod");
6198 result = Dart_Invoke(instance, name, 1, args);
6199 EXPECT(Dart_IsError(result));
6200 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6201
6202 // Static method.
6203 name = NewString("staticMethod");
6204 result = Dart_Invoke(type, name, 1, args);
6205 EXPECT(Dart_IsError(result));
6206 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6207
6208 // Hidden static method.
6209 name = NewString("_staticMethod");
6210 result = Dart_Invoke(type, name, 1, args);
6211 EXPECT(Dart_IsError(result));
6212 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6213
6214 // Top-Level method.
6215 name = NewString("topMethod");
6216 result = Dart_Invoke(lib, name, 1, args);
6217 EXPECT(Dart_IsError(result));
6218 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6219
6220 // Hidden top-level method.
6221 name = NewString("_topMethod");
6222 result = Dart_Invoke(lib, name, 1, args);
6223 EXPECT(Dart_IsError(result));
6224 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6225}
6226
6227TEST_CASE(DartAPI_Invoke_Null) {
6228 Dart_Handle result = Dart_Invoke(Dart_Null(), NewString("toString"), 0, NULL);
6229 EXPECT_VALID(result);
6230 EXPECT(Dart_IsString(result));
6231
6232 const char* value = "";
6233 EXPECT_VALID(Dart_StringToCString(result, &value));
6234 EXPECT_STREQ("null", value);
6235
6236 Dart_Handle function_name = NewString("NoNoNo");
6237 result = Dart_Invoke(Dart_Null(), function_name, 0, NULL);
6238 EXPECT(Dart_IsError(result));
6239 EXPECT(Dart_ErrorHasException(result));
6240
6241 result = Dart_GetField(Dart_Null(), NewString("toString"));
6242 EXPECT_VALID(result);
6243 EXPECT(Dart_IsClosure(result));
6244
6245 result =
6246 Dart_SetField(Dart_Null(), NewString("nullHasNoSetters"), Dart_Null());
6247 // Not that Dart_SetField expects a non-null receiver.
6248 EXPECT_ERROR(
6249 result,
6250 "NoSuchMethodError: The setter 'nullHasNoSetters=' was called on null");
6251}
6252
6253TEST_CASE(DartAPI_InvokeNoSuchMethod) {
6254 const char* kScriptChars =
6255 "class Expect {\n"
6256 " static equals(a, b) {\n"
6257 " if (a != b) {\n"
6258 " throw 'not equal. expected: $a, got: $b';\n"
6259 " }\n"
6260 " }\n"
6261 "}\n"
6262 "class TestClass {\n"
6263 " static int fld1 = 0;\n"
6264 " void noSuchMethod(Invocation invocation) {\n"
6265 // This relies on the Symbol.toString() method returning a String of the
6266 // form 'Symbol("name")'. This is to avoid having to import
6267 // dart:_internal just to get access to the name of the symbol.
6268 " var name = invocation.memberName.toString();\n"
6269 " name = name.split('\"')[1];\n"
6270 " if (name == 'fld') {\n"
6271 " Expect.equals(true, invocation.isGetter);\n"
6272 " Expect.equals(false, invocation.isMethod);\n"
6273 " Expect.equals(false, invocation.isSetter);\n"
6274 " } else if (name == 'setfld') {\n"
6275 " Expect.equals(true, invocation.isSetter);\n"
6276 " Expect.equals(false, invocation.isMethod);\n"
6277 " Expect.equals(false, invocation.isGetter);\n"
6278 " } else if (name == 'method') {\n"
6279 " Expect.equals(true, invocation.isMethod);\n"
6280 " Expect.equals(false, invocation.isSetter);\n"
6281 " Expect.equals(false, invocation.isGetter);\n"
6282 " }\n"
6283 " TestClass.fld1 += 1;\n"
6284 " }\n"
6285 " static TestClass testMain() {\n"
6286 " return new TestClass();\n"
6287 " }\n"
6288 "}\n";
6289 Dart_Handle result;
6290 Dart_Handle instance;
6291 // Create a test library and Load up a test script in it.
6292 // The test library must have a dart: url so it can import dart:_internal.
6293 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
6294 Dart_Handle type =
6295 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, NULL);
6296 EXPECT_VALID(type);
6297
6298 // Invoke a function which returns an object.
6299 instance = Dart_Invoke(type, NewString("testMain"), 0, NULL);
6300 EXPECT_VALID(instance);
6301
6302 // Try to get a field that does not exist, should call noSuchMethod.
6303 result = Dart_GetField(instance, NewString("fld"));
6304 EXPECT_VALID(result);
6305
6306 // Try to set a field that does not exist, should call noSuchMethod.
6307 result = Dart_SetField(instance, NewString("setfld"), Dart_NewInteger(13));
6308 EXPECT_VALID(result);
6309
6310 // Try to invoke a method that does not exist, should call noSuchMethod.
6311 result = Dart_Invoke(instance, NewString("method"), 0, NULL);
6312 EXPECT_VALID(result);
6313
6314 result = Dart_GetField(type, NewString("fld1"));
6315 EXPECT_VALID(result);
6316 int64_t value = 0;
6317 result = Dart_IntegerToInt64(result, &value);
6318 EXPECT_EQ(3, value);
6319}
6320
6321TEST_CASE(DartAPI_InvokeClosure) {
6322 const char* kScriptChars =
6323 "class InvokeClosure {\n"
6324 " InvokeClosure(int i, int j) : fld1 = i, fld2 = j {}\n"
6325 " Function method1(int i) {\n"
6326 " f(int j) => j + i + fld1 + fld2 + fld4; \n"
6327 " return f;\n"
6328 " }\n"
6329 " static Function method2(int i) {\n"
6330 " n(int j) { throw new Exception('I am an exception'); return 1; }\n"
6331 " return n;\n"
6332 " }\n"
6333 " int fld1;\n"
6334 " final int fld2;\n"
6335 " static const int fld4 = 10;\n"
6336 "}\n"
6337 "Function testMain1() {\n"
6338 " InvokeClosure obj = new InvokeClosure(10, 20);\n"
6339 " return obj.method1(10);\n"
6340 "}\n"
6341 "Function testMain2() {\n"
6342 " return InvokeClosure.method2(10);\n"
6343 "}\n";
6344 Dart_Handle result;
6345 CHECK_API_SCOPE(thread);
6346
6347 // Create a test library and Load up a test script in it.
6348 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
6349
6350 // Invoke a function which returns a closure.
6351 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain1"), 0, NULL);
6352 EXPECT_VALID(retobj);
6353
6354 EXPECT(Dart_IsClosure(retobj));
6355 EXPECT(!Dart_IsClosure(Dart_NewInteger(101)));
6356
6357 // Now invoke the closure and check the result.
6358 Dart_Handle dart_arguments[1];
6359 dart_arguments[0] = Dart_NewInteger(1);
6360 result = Dart_InvokeClosure(retobj, 1, dart_arguments);
6361 EXPECT_VALID(result);
6362 EXPECT(Dart_IsInteger(result));
6363 int64_t value = 0;
6364 result = Dart_IntegerToInt64(result, &value);
6365 EXPECT_EQ(51, value);
6366
6367 // Invoke closure with wrong number of args, should result in exception.
6368 result = Dart_InvokeClosure(retobj, 0, NULL);
6369 EXPECT(Dart_IsError(result));
6370 EXPECT(Dart_ErrorHasException(result));
6371
6372 // Invoke a function which returns a closure.
6373 retobj = Dart_Invoke(lib, NewString("testMain2"), 0, NULL);
6374 EXPECT_VALID(retobj);
6375
6376 EXPECT(Dart_IsClosure(retobj));
6377 EXPECT(!Dart_IsClosure(NewString("abcdef")));
6378
6379 // Now invoke the closure and check the result (should be an exception).
6380 dart_arguments[0] = Dart_NewInteger(1);
6381 result = Dart_InvokeClosure(retobj, 1, dart_arguments);
6382 EXPECT(Dart_IsError(result));
6383 EXPECT(Dart_ErrorHasException(result));
6384}
6385
6386void ExceptionNative(Dart_NativeArguments args) {
6387 Dart_EnterScope();
6388 Dart_ThrowException(NewString("Hello from ExceptionNative!"));
6389 UNREACHABLE();
6390}
6391
6392static Dart_NativeFunction native_lookup(Dart_Handle name,
6393 int argument_count,
6394 bool* auto_setup_scope) {
6395 ASSERT(auto_setup_scope != NULL);
6396 *auto_setup_scope = true;
6397 return reinterpret_cast<Dart_NativeFunction>(&ExceptionNative);
6398}
6399
6400TEST_CASE(DartAPI_ThrowException) {
6401 const char* kScriptChars = "int test() native \"ThrowException_native\";";
6402 Dart_Handle result;
6403 intptr_t size = thread->ZoneSizeInBytes();
6404 Dart_EnterScope(); // Start a Dart API scope for invoking API functions.
6405
6406 // Load up a test script which extends the native wrapper class.
6407 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, native_lookup);
6408
6409 // Throwing an exception here should result in an error.
6410 result = Dart_ThrowException(NewString("This doesn't work"));
6411 EXPECT_ERROR(result, "No Dart frames on stack, cannot throw exception");
6412 EXPECT(!Dart_ErrorHasException(result));
6413
6414 // Invoke 'test' and check for an uncaught exception.
6415 result = Dart_Invoke(lib, NewString("test"), 0, NULL);
6416 EXPECT_ERROR(result, "Hello from ExceptionNative!");
6417 EXPECT(Dart_ErrorHasException(result));
6418
6419 Dart_ExitScope(); // Exit the Dart API scope.
6420 EXPECT_EQ(size, thread->ZoneSizeInBytes());
6421}
6422
6423static intptr_t kNativeArgumentNativeField1Value = 30;
6424static intptr_t kNativeArgumentNativeField2Value = 40;
6425static intptr_t native_arg_str_peer = 100;
6426static void NativeArgumentCreate(Dart_NativeArguments args) {
6427 Dart_Handle lib = Dart_LookupLibrary(NewString(TestCase::url()));
6428 Dart_Handle type =
6429 Dart_GetNonNullableType(lib, NewString("MyObject"), 0, NULL);
6430 EXPECT_VALID(type);
6431
6432 // Allocate without a constructor.
6433 const int num_native_fields = 2;
6434 const intptr_t native_fields[] = {kNativeArgumentNativeField1Value,
6435 kNativeArgumentNativeField2Value};
6436 // Allocate and Setup native fields.
6437 Dart_Handle obj =
6438 Dart_AllocateWithNativeFields(type, num_native_fields, native_fields);
6439 EXPECT_VALID(obj);
6440
6441 kNativeArgumentNativeField1Value *= 2;
6442 kNativeArgumentNativeField2Value *= 2;
6443 Dart_SetReturnValue(args, obj);
6444}
6445
6446static void NativeArgumentAccess(Dart_NativeArguments args) {
6447 const int kNumNativeFields = 2;
6448
6449 // Test different argument types with a valid descriptor set.
6450 {
6451 const char* cstr = NULL;
6452 intptr_t native_fields1[kNumNativeFields];
6453 intptr_t native_fields2[kNumNativeFields];
6454 const Dart_NativeArgument_Descriptor arg_descriptors[9] = {
6455 {Dart_NativeArgument_kNativeFields, 0},
6456 {Dart_NativeArgument_kInt32, 1},
6457 {Dart_NativeArgument_kUint64, 2},
6458 {Dart_NativeArgument_kBool, 3},
6459 {Dart_NativeArgument_kDouble, 4},
6460 {Dart_NativeArgument_kString, 5},
6461 {Dart_NativeArgument_kString, 6},
6462 {Dart_NativeArgument_kNativeFields, 7},
6463 {Dart_NativeArgument_kInstance, 7},
6464 };
6465 Dart_NativeArgument_Value arg_values[9];
6466 arg_values[0].as_native_fields.num_fields = kNumNativeFields;
6467 arg_values[0].as_native_fields.values = native_fields1;
6468 arg_values[7].as_native_fields.num_fields = kNumNativeFields;
6469 arg_values[7].as_native_fields.values = native_fields2;
6470 Dart_Handle result =
6471 Dart_GetNativeArguments(args, 9, arg_descriptors, arg_values);
6472 EXPECT_VALID(result);
6473
6474 EXPECT(arg_values[0].as_native_fields.values[0] == 30);
6475 EXPECT(arg_values[0].as_native_fields.values[1] == 40);
6476
6477 EXPECT(arg_values[1].as_int32 == 77);
6478
6479 // When wrapped-around, this value should not fit into int32, because this
6480 // unit test verifies that getting it as int32 produces error.
6481 EXPECT(arg_values[2].as_uint64 == 0x8000000000000000LL);
6482
6483 EXPECT(arg_values[3].as_bool == true);
6484
6485 EXPECT(arg_values[4].as_double == 3.14);
6486
6487 EXPECT_VALID(arg_values[5].as_string.dart_str);
6488 EXPECT(Dart_IsString(arg_values[5].as_string.dart_str));
6489 EXPECT_VALID(Dart_StringToCString(arg_values[5].as_string.dart_str, &cstr));
6490 EXPECT_STREQ("abcdefg", cstr);
6491 EXPECT(arg_values[5].as_string.peer == NULL);
6492
6493 EXPECT(arg_values[6].as_string.dart_str == NULL);
6494 EXPECT(arg_values[6].as_string.peer ==
6495 reinterpret_cast<void*>(&native_arg_str_peer));
6496
6497 EXPECT(arg_values[7].as_native_fields.values[0] == 60);
6498 EXPECT(arg_values[7].as_native_fields.values[1] == 80);
6499
6500 EXPECT_VALID(arg_values[8].as_instance);
6501 EXPECT(Dart_IsInstance(arg_values[8].as_instance));
6502 int field_count = 0;
6503 EXPECT_VALID(Dart_GetNativeInstanceFieldCount(arg_values[8].as_instance,
6504 &field_count));
6505 EXPECT(field_count == 2);
6506 }
6507
6508 // Test with an invalid descriptor set (invalid type).
6509 {
6510 const Dart_NativeArgument_Descriptor arg_descriptors[8] = {
6511 {Dart_NativeArgument_kInt32, 1},
6512 {Dart_NativeArgument_kUint64, 2},
6513 {Dart_NativeArgument_kString, 3},
6514 {Dart_NativeArgument_kDouble, 4},
6515 {Dart_NativeArgument_kString, 5},
6516 {Dart_NativeArgument_kString, 6},
6517 {Dart_NativeArgument_kNativeFields, 0},
6518 {Dart_NativeArgument_kNativeFields, 7},
6519 };
6520 Dart_NativeArgument_Value arg_values[8];
6521 Dart_Handle result =
6522 Dart_GetNativeArguments(args, 8, arg_descriptors, arg_values);
6523 EXPECT(Dart_IsError(result));
6524 }
6525
6526 // Test with an invalid range error.
6527 {
6528 const Dart_NativeArgument_Descriptor arg_descriptors[8] = {
6529 {Dart_NativeArgument_kInt32, 2},
6530 {Dart_NativeArgument_kUint64, 2},
6531 {Dart_NativeArgument_kBool, 3},
6532 {Dart_NativeArgument_kDouble, 4},
6533 {Dart_NativeArgument_kString, 5},
6534 {Dart_NativeArgument_kString, 6},
6535 {Dart_NativeArgument_kNativeFields, 0},
6536 {Dart_NativeArgument_kNativeFields, 7},
6537 };
6538 Dart_NativeArgument_Value arg_values[8];
6539 Dart_Handle result =
6540 Dart_GetNativeArguments(args, 8, arg_descriptors, arg_values);
6541 EXPECT(Dart_IsError(result));
6542 }
6543
6544 Dart_SetIntegerReturnValue(args, 0);
6545}
6546
6547static Dart_NativeFunction native_args_lookup(Dart_Handle name,
6548 int argument_count,
6549 bool* auto_scope_setup) {
6550 TransitionNativeToVM transition(Thread::Current());
6551 const Object& obj = Object::Handle(Api::UnwrapHandle(name));
6552 if (!obj.IsString()) {
6553 return NULL;
6554 }
6555 ASSERT(auto_scope_setup != NULL);
6556 *auto_scope_setup = true;
6557 const char* function_name = obj.ToCString();
6558 ASSERT(function_name != NULL);
6559 if (strcmp(function_name, "NativeArgument_Create") == 0) {
6560 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentCreate);
6561 } else if (strcmp(function_name, "NativeArgument_Access") == 0) {
6562 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentAccess);
6563 }
6564 return NULL;
6565}
6566
6567TEST_CASE(DartAPI_GetNativeArguments) {
6568 const char* kScriptChars =
6569 "import 'dart:nativewrappers';"
6570 "class MyObject extends NativeFieldWrapperClass2 {"
6571 " static MyObject createObject() native 'NativeArgument_Create';"
6572 " int accessFields(int arg1,"
6573 " int arg2,"
6574 " bool arg3,"
6575 " double arg4,"
6576 " String arg5,"
6577 " String arg6,"
6578 " MyObject arg7) native 'NativeArgument_Access';"
6579 "}"
6580 "int testMain(String extstr) {"
6581 " String str = 'abcdefg';"
6582 " MyObject obj1 = MyObject.createObject();"
6583 " MyObject obj2 = MyObject.createObject();"
6584 " return obj1.accessFields(77,"
6585 " 0x8000000000000000,"
6586 " true,"
6587 " 3.14,"
6588 " str,"
6589 " extstr,"
6590 " obj2);"
6591 "}";
6592
6593 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, native_args_lookup);
6594
6595 const char* ascii_str = "string";
6596 intptr_t ascii_str_length = strlen(ascii_str);
6597 Dart_Handle extstr = Dart_NewExternalLatin1String(
6598 reinterpret_cast<const uint8_t*>(ascii_str), ascii_str_length,
6599 reinterpret_cast<void*>(&native_arg_str_peer), ascii_str_length,
6600 NoopFinalizer);
6601
6602 Dart_Handle args[1];
6603 args[0] = extstr;
6604 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 1, args);
6605 EXPECT_VALID(result);
6606 EXPECT(Dart_IsInteger(result));
6607}
6608
6609static void NativeArgumentCounter(Dart_NativeArguments args) {
6610 Dart_EnterScope();
6611 int count = Dart_GetNativeArgumentCount(args);
6612 Dart_SetReturnValue(args, Dart_NewInteger(count));
6613 Dart_ExitScope();
6614}
6615
6616static Dart_NativeFunction gnac_lookup(Dart_Handle name,
6617 int argument_count,
6618 bool* auto_setup_scope) {
6619 ASSERT(auto_setup_scope != NULL);
6620 *auto_setup_scope = true;
6621 return reinterpret_cast<Dart_NativeFunction>(&NativeArgumentCounter);
6622}
6623
6624TEST_CASE(DartAPI_GetNativeArgumentCount) {
6625 const char* kScriptChars =
6626 "class MyObject {"
6627 " int method1(int i, int j) native 'Name_Does_Not_Matter';"
6628 "}"
6629 "testMain() {"
6630 " MyObject obj = new MyObject();"
6631 " return obj.method1(77, 125);"
6632 "}";
6633
6634 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, gnac_lookup);
6635
6636 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
6637 EXPECT_VALID(result);
6638 EXPECT(Dart_IsInteger(result));
6639
6640 int64_t value = 0;
6641 result = Dart_IntegerToInt64(result, &value);
6642 EXPECT_VALID(result);
6643 EXPECT_EQ(3, value);
6644}
6645
6646TEST_CASE(DartAPI_TypeToNullability) {
6647 const char* kScriptChars =
6648 "library testlib;\n"
6649 "class Class {\n"
6650 " static var name = 'Class';\n"
6651 "}\n";
6652
6653 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
6654
6655 const Dart_Handle name = NewString("Class");
6656 // Lookup the legacy type for Class.
6657 Dart_Handle type = Dart_GetType(lib, name, 0, NULL);
6658 Dart_Handle nonNullableType;
6659 Dart_Handle nullableType;
6660 if (Dart_IsError(type)) {
6661 EXPECT_ERROR(
6662 type,
6663 "Cannot use legacy types with --sound-null-safety enabled. "
6664 "Use Dart_GetNullableType or Dart_GetNonNullableType instead.");
6665
6666 nonNullableType = Dart_GetNonNullableType(lib, name, 0, nullptr);
6667 EXPECT_VALID(nonNullableType);
6668 nullableType = Dart_GetNullableType(lib, name, 0, nullptr);
6669 } else {
6670 EXPECT_VALID(type);
6671 bool result = false;
6672 EXPECT_VALID(Dart_IsLegacyType(type, &result));
6673 EXPECT(result);
6674
6675 // Legacy -> Nullable
6676 nullableType = Dart_TypeToNullableType(type);
6677 EXPECT_VALID(nullableType);
6678 result = false;
6679 EXPECT_VALID(Dart_IsNullableType(nullableType, &result));
6680 EXPECT(result);
6681 EXPECT(Dart_IdentityEquals(nullableType,
6682 Dart_GetNullableType(lib, name, 0, nullptr)));
6683
6684 // Legacy -> Non-Nullable
6685 nonNullableType = Dart_TypeToNonNullableType(type);
6686 EXPECT_VALID(nonNullableType);
6687 result = false;
6688 EXPECT_VALID(Dart_IsNonNullableType(nonNullableType, &result));
6689 EXPECT(result);
6690 EXPECT(Dart_IdentityEquals(nonNullableType,
6691 Dart_GetNonNullableType(lib, name, 0, nullptr)));
6692 }
6693
6694 // Nullable -> Non-Nullable
6695 EXPECT(Dart_IdentityEquals(
6696 nonNullableType,
6697 Dart_TypeToNonNullableType(Dart_GetNullableType(lib, name, 0, nullptr))));
6698
6699 // Non-Nullable -> Nullable
6700 EXPECT(Dart_IdentityEquals(
6701 nullableType,
6702 Dart_TypeToNullableType(Dart_GetNonNullableType(lib, name, 0, nullptr))));
6703}
6704
6705TEST_CASE(DartAPI_GetNullableType) {
6706 const char* kScriptChars =
6707 "library testlib;\n"
6708 "class Class {\n"
6709 " static var name = 'Class';\n"
6710 "}\n"
6711 "\n"
6712 "class _Class {\n"
6713 " static var name = '_Class';\n"
6714 "}\n";
6715
6716 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
6717
6718 // Lookup a class.
6719 Dart_Handle type = Dart_GetNullableType(lib, NewString("Class"), 0, NULL);
6720 EXPECT_VALID(type);
6721 bool result = false;
6722 EXPECT_VALID(Dart_IsNullableType(type, &result));
6723 EXPECT(result);
6724 Dart_Handle name = Dart_ToString(type);
6725 EXPECT_VALID(name);
6726 const char* name_cstr = "";
6727 EXPECT_VALID(Dart_StringToCString(name, &name_cstr));
6728 EXPECT_STREQ("Class?", name_cstr);
6729
6730 name = Dart_GetField(type, NewString("name"));
6731 EXPECT_VALID(name);
6732 EXPECT_VALID(Dart_StringToCString(name, &name_cstr));
6733 EXPECT_STREQ("Class", name_cstr);
6734
6735 // Lookup a private class.
6736 type = Dart_GetNullableType(lib, NewString("_Class"), 0, NULL);
6737 EXPECT_VALID(type);
6738 result = false;
6739 EXPECT_VALID(Dart_IsNullableType(type, &result));
6740
6741 name = Dart_GetField(type, NewString("name"));
6742 EXPECT_VALID(name);
6743 name_cstr = "";
6744 EXPECT_VALID(Dart_StringToCString(name, &name_cstr));
6745 EXPECT_STREQ("_Class", name_cstr);
6746
6747 // Lookup a class that does not exist.
6748 type = Dart_GetNullableType(lib, NewString("DoesNotExist"), 0, NULL);
6749 EXPECT(Dart_IsError(type));
6750 EXPECT_STREQ("Type 'DoesNotExist' not found in library 'testlib'.",
6751 Dart_GetError(type));
6752
6753 // Lookup a class from an error library. The error propagates.
6754 type = Dart_GetNullableType(Api::NewError("myerror"), NewString("Class"), 0,
6755 NULL);
6756 EXPECT(Dart_IsError(type));
6757 EXPECT_STREQ("myerror", Dart_GetError(type));
6758
6759 // Lookup a type using an error class name. The error propagates.
6760 type = Dart_GetNullableType(lib, Api::NewError("myerror"), 0, NULL);
6761 EXPECT(Dart_IsError(type));
6762 EXPECT_STREQ("myerror", Dart_GetError(type));
6763}
6764
6765TEST_CASE(DartAPI_GetNonNullableType) {
6766 const char* kScriptChars =
6767 "library testlib;\n"
6768 "class Class {\n"
6769 " static var name = 'Class';\n"
6770 "}\n"
6771 "\n"
6772 "class _Class {\n"
6773 " static var name = '_Class';\n"
6774 "}\n";
6775
6776 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
6777
6778 // Lookup a class.
6779 Dart_Handle type = Dart_GetNonNullableType(lib, NewString("Class"), 0, NULL);
6780 EXPECT_VALID(type);
6781 bool result = false;
6782 EXPECT_VALID(Dart_IsNonNullableType(type, &result));
6783 EXPECT(result);
6784 Dart_Handle name = Dart_ToString(type);
6785 EXPECT_VALID(name);
6786 const char* name_cstr = "";
6787 EXPECT_VALID(Dart_StringToCString(name, &name_cstr));
6788 EXPECT_STREQ("Class", name_cstr);
6789
6790 name = Dart_GetField(type, NewString("name"));
6791 EXPECT_VALID(name);
6792 EXPECT_VALID(Dart_StringToCString(name, &name_cstr));
6793 EXPECT_STREQ("Class", name_cstr);
6794
6795 // Lookup a private class.
6796 type = Dart_GetNonNullableType(lib, NewString("_Class"), 0, NULL);
6797 EXPECT_VALID(type);
6798 result = false;
6799 EXPECT_VALID(Dart_IsNonNullableType(type, &result));
6800 EXPECT(result);
6801
6802 name = Dart_GetField(type, NewString("name"));
6803 EXPECT_VALID(name);
6804 name_cstr = "";
6805 EXPECT_VALID(Dart_StringToCString(name, &name_cstr));
6806 EXPECT_STREQ("_Class", name_cstr);
6807
6808 // Lookup a class that does not exist.
6809 type = Dart_GetNonNullableType(lib, NewString("DoesNotExist"), 0, NULL);
6810 EXPECT(Dart_IsError(type));
6811 EXPECT_STREQ("Type 'DoesNotExist' not found in library 'testlib'.",
6812 Dart_GetError(type));
6813
6814 // Lookup a class from an error library. The error propagates.
6815 type = Dart_GetNonNullableType(Api::NewError("myerror"), NewString("Class"),
6816 0, NULL);
6817 EXPECT(Dart_IsError(type));
6818 EXPECT_STREQ("myerror", Dart_GetError(type));
6819
6820 // Lookup a type using an error class name. The error propagates.
6821 type = Dart_GetNonNullableType(lib, Api::NewError("myerror"), 0, NULL);
6822 EXPECT(Dart_IsError(type));
6823 EXPECT_STREQ("myerror", Dart_GetError(type));
6824}
6825
6826TEST_CASE(DartAPI_InstanceOf) {
6827 const char* kScriptChars =
6828 "class OtherClass {\n"
6829 " static returnNull() { return null; }\n"
6830 "}\n"
6831 "class InstanceOfTest {\n"
6832 " InstanceOfTest() {}\n"
6833 " static InstanceOfTest testMain() {\n"
6834 " return new InstanceOfTest();\n"
6835 " }\n"
6836 "}\n";
6837 Dart_Handle result;
6838 // Create a test library and Load up a test script in it.
6839 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
6840
6841 // Fetch InstanceOfTest class.
6842 Dart_Handle type =
6843 Dart_GetNonNullableType(lib, NewString("InstanceOfTest"), 0, NULL);
6844 EXPECT_VALID(type);
6845
6846 // Invoke a function which returns an object of type InstanceOf..
6847 Dart_Handle instanceOfTestObj =
6848 Dart_Invoke(type, NewString("testMain"), 0, NULL);
6849 EXPECT_VALID(instanceOfTestObj);
6850
6851 // Now check instanceOfTestObj reported as an instance of
6852 // InstanceOfTest class.
6853 bool is_instance = false;
6854 result = Dart_ObjectIsType(instanceOfTestObj, type, &is_instance);
6855 EXPECT_VALID(result);
6856 EXPECT(is_instance);
6857
6858 // Fetch OtherClass and check if instanceOfTestObj is instance of it.
6859 Dart_Handle otherType =
6860 Dart_GetNonNullableType(lib, NewString("OtherClass"), 0, NULL);
6861 EXPECT_VALID(otherType);
6862
6863 result = Dart_ObjectIsType(instanceOfTestObj, otherType, &is_instance);
6864 EXPECT_VALID(result);
6865 EXPECT(!is_instance);
6866
6867 // Check that primitives are not instances of InstanceOfTest class.
6868 result = Dart_ObjectIsType(NewString("a string"), otherType, &is_instance);
6869 EXPECT_VALID(result);
6870 EXPECT(!is_instance);
6871
6872 result = Dart_ObjectIsType(Dart_NewInteger(42), otherType, &is_instance);
6873 EXPECT_VALID(result);
6874 EXPECT(!is_instance);
6875
6876 result = Dart_ObjectIsType(Dart_NewBoolean(true), otherType, &is_instance);
6877 EXPECT_VALID(result);
6878 EXPECT(!is_instance);
6879
6880 // Check that null is not an instance of InstanceOfTest class.
6881 Dart_Handle null = Dart_Invoke(otherType, NewString("returnNull"), 0, NULL);
6882 EXPECT_VALID(null);
6883
6884 result = Dart_ObjectIsType(null, otherType, &is_instance);
6885 EXPECT_VALID(result);
6886 EXPECT(!is_instance);
6887
6888 // Check that error is returned if null is passed as a class argument.
6889 result = Dart_ObjectIsType(null, null, &is_instance);
6890 EXPECT(Dart_IsError(result));
6891}
6892
6893TEST_CASE(DartAPI_RootLibrary) {
6894 const char* kScriptChars =
6895 "library testlib;"
6896 "main() {"
6897 " return 12345;"
6898 "}";
6899
6900 Dart_Handle root_lib = Dart_RootLibrary();
6901 EXPECT_VALID(root_lib);
6902 EXPECT(Dart_IsNull(root_lib));
6903
6904 // Load a script.
6905 EXPECT_VALID(LoadScript(TestCase::url(), kScriptChars));
6906
6907 root_lib = Dart_RootLibrary();
6908 Dart_Handle lib_uri = Dart_LibraryUrl(root_lib);
6909 EXPECT_VALID(lib_uri);
6910 EXPECT(!Dart_IsNull(lib_uri));
6911 const char* uri_cstr = "";
6912 EXPECT_VALID(Dart_StringToCString(lib_uri, &uri_cstr));
6913 EXPECT_STREQ(TestCase::url(), uri_cstr);
6914
6915 Dart_Handle core_uri = Dart_NewStringFromCString("dart:core");
6916 Dart_Handle core_lib = Dart_LookupLibrary(core_uri);
6917 EXPECT_VALID(core_lib);
6918 EXPECT(Dart_IsLibrary(core_lib));
6919
6920 Dart_Handle result = Dart_SetRootLibrary(core_uri); // Not a library.
6921 EXPECT(Dart_IsError(result));
6922 root_lib = Dart_RootLibrary();
6923 lib_uri = Dart_LibraryUrl(root_lib);
6924 EXPECT_VALID(Dart_StringToCString(lib_uri, &uri_cstr));
6925 EXPECT_STREQ(TestCase::url(), uri_cstr); // Root library didn't change.
6926
6927 result = Dart_SetRootLibrary(core_lib);
6928 EXPECT_VALID(result);
6929 root_lib = Dart_RootLibrary();
6930 lib_uri = Dart_LibraryUrl(root_lib);
6931 EXPECT_VALID(Dart_StringToCString(lib_uri, &uri_cstr));
6932 EXPECT_STREQ("dart:core", uri_cstr); // Root library did change.
6933
6934 result = Dart_SetRootLibrary(Dart_Null());
6935 EXPECT_VALID(result);
6936 root_lib = Dart_RootLibrary();
6937 EXPECT(Dart_IsNull(root_lib)); // Root library did change.
6938}
6939
6940TEST_CASE(DartAPI_LookupLibrary) {
6941 const char* kScriptChars =
6942 "import 'library1_dart';"
6943 "main() {}";
6944 const char* kLibrary1 = "file:///library1_dart";
6945 const char* kLibrary1Chars =
6946 "library library1;"
6947 "final x = 0;";
6948
6949 Dart_Handle url;
6950 Dart_Handle result;
6951
6952 // Create a test library and load up a test script in it.
6953 TestCase::AddTestLib("file:///library1_dart", kLibrary1Chars);
6954 // LoadTestScript resets the LibraryTagHandler, which we don't want when
6955 // using the VM compiler, so we only use it with the Dart frontend for this
6956 // test.
6957 result = TestCase::LoadTestScript(kScriptChars, NULL, TestCase::url());
6958 EXPECT_VALID(result);
6959
6960 url = NewString(kLibrary1);
6961 result = Dart_LookupLibrary(url);
6962 EXPECT_VALID(result);
6963
6964 result = Dart_LookupLibrary(Dart_Null());
6965 EXPECT_ERROR(result,
6966 "Dart_LookupLibrary expects argument 'url' to be non-null.");
6967
6968 result = Dart_LookupLibrary(Dart_True());
6969 EXPECT_ERROR(
6970 result,
6971 "Dart_LookupLibrary expects argument 'url' to be of type String.");
6972
6973 result = Dart_LookupLibrary(Dart_NewApiError("incoming error"));
6974 EXPECT(Dart_IsError(result));
6975 EXPECT_STREQ("incoming error", Dart_GetError(result));
6976
6977 url = NewString("noodles.dart");
6978 result = Dart_LookupLibrary(url);
6979 EXPECT_ERROR(result, "Dart_LookupLibrary: library 'noodles.dart' not found.");
6980}
6981
6982TEST_CASE(DartAPI_LibraryUrl) {
6983 const char* kLibrary1Chars = "library library1_name;";
6984 Dart_Handle lib = TestCase::LoadTestLibrary("library1_url", kLibrary1Chars);
6985 Dart_Handle error = Dart_NewApiError("incoming error");
6986 EXPECT_VALID(lib);
6987
6988 Dart_Handle result = Dart_LibraryUrl(Dart_Null());
6989 EXPECT_ERROR(result,
6990 "Dart_LibraryUrl expects argument 'library' to be non-null.");
6991
6992 result = Dart_LibraryUrl(Dart_True());
6993 EXPECT_ERROR(
6994 result,
6995 "Dart_LibraryUrl expects argument 'library' to be of type Library.");
6996
6997 result = Dart_LibraryUrl(error);
6998 EXPECT(Dart_IsError(result));
6999 EXPECT_STREQ("incoming error", Dart_GetError(result));
7000
7001 result = Dart_LibraryUrl(lib);
7002 EXPECT_VALID(result);
7003 EXPECT(Dart_IsString(result));
7004 const char* cstr = NULL;
7005 EXPECT_VALID(Dart_StringToCString(result, &cstr));
7006 EXPECT_SUBSTRING("library1_url", cstr);
7007}
7008
7009static void MyNativeFunction1(Dart_NativeArguments args) {
7010 Dart_EnterScope();
7011 Dart_SetReturnValue(args, Dart_NewInteger(654321));
7012 Dart_ExitScope();
7013}
7014
7015static void MyNativeFunction2(Dart_NativeArguments args) {
7016 Dart_EnterScope();
7017 Dart_SetReturnValue(args, Dart_NewInteger(123456));
7018 Dart_ExitScope();
7019}
7020
7021static Dart_NativeFunction MyNativeResolver1(Dart_Handle name,
7022 int arg_count,
7023 bool* auto_setup_scope) {
7024 ASSERT(auto_setup_scope != NULL);
7025 *auto_setup_scope = false;
7026 return &MyNativeFunction1;
7027}
7028
7029static Dart_NativeFunction MyNativeResolver2(Dart_Handle name,
7030 int arg_count,
7031 bool* auto_setup_scope) {
7032 ASSERT(auto_setup_scope != NULL);
7033 *auto_setup_scope = false;
7034 return &MyNativeFunction2;
7035}
7036
7037TEST_CASE(DartAPI_SetNativeResolver) {
7038 const char* kScriptChars =
7039 "class Test {"
7040 " static foo() native \"SomeNativeFunction\";\n"
7041 " static bar() native \"SomeNativeFunction2\";\n"
7042 " static baz() native \"SomeNativeFunction3\";\n"
7043 "}";
7044 Dart_Handle error = Dart_NewApiError("incoming error");
7045 Dart_Handle result;
7046
7047 // Load a test script.
7048 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
7049 EXPECT_VALID(lib);
7050 result = Dart_FinalizeLoading(false);
7051 EXPECT_VALID(result);
7052 EXPECT(Dart_IsLibrary(lib));
7053 Dart_Handle type = Dart_GetNonNullableType(lib, NewString("Test"), 0, NULL);
7054 EXPECT_VALID(type);
7055
7056 result = Dart_SetNativeResolver(Dart_Null(), &MyNativeResolver1, NULL);
7057 EXPECT_ERROR(
7058 result,
7059 "Dart_SetNativeResolver expects argument 'library' to be non-null.");
7060
7061 result = Dart_SetNativeResolver(Dart_True(), &MyNativeResolver1, NULL);
7062 EXPECT_ERROR(result,
7063 "Dart_SetNativeResolver expects argument 'library' to be of "
7064 "type Library.");
7065
7066 result = Dart_SetNativeResolver(error, &MyNativeResolver1, NULL);
7067 EXPECT(Dart_IsError(result));
7068 EXPECT_STREQ("incoming error", Dart_GetError(result));
7069
7070 result = Dart_SetNativeResolver(lib, &MyNativeResolver1, NULL);
7071 EXPECT_VALID(result);
7072
7073 // Call a function and make sure native resolution works.
7074 result = Dart_Invoke(type, NewString("foo"), 0, NULL);
7075 EXPECT_VALID(result);
7076 EXPECT(Dart_IsInteger(result));
7077 int64_t value = 0;
7078 EXPECT_VALID(Dart_IntegerToInt64(result, &value));
7079 EXPECT_EQ(654321, value);
7080
7081 // A second call succeeds.
7082 result = Dart_SetNativeResolver(lib, &MyNativeResolver2, NULL);
7083 EXPECT_VALID(result);
7084
7085 // 'foo' has already been resolved so gets the old value.
7086 result = Dart_Invoke(type, NewString("foo"), 0, NULL);
7087 EXPECT_VALID(result);
7088 EXPECT(Dart_IsInteger(result));
7089 value = 0;
7090 EXPECT_VALID(Dart_IntegerToInt64(result, &value));
7091 EXPECT_EQ(654321, value);
7092
7093 // 'bar' has not yet been resolved so gets the new value.
7094 result = Dart_Invoke(type, NewString("bar"), 0, NULL);
7095 EXPECT_VALID(result);
7096 EXPECT(Dart_IsInteger(result));
7097 value = 0;
7098 EXPECT_VALID(Dart_IntegerToInt64(result, &value));
7099 EXPECT_EQ(123456, value);
7100
7101 // A NULL resolver is okay, but resolution will fail.
7102 result = Dart_SetNativeResolver(lib, NULL, NULL);
7103 EXPECT_VALID(result);
7104
7105 EXPECT_ERROR(Dart_Invoke(type, NewString("baz"), 0, NULL),
7106 "native function 'SomeNativeFunction3' (0 arguments) "
7107 "cannot be found");
7108}
7109
7110// Test that an imported name does not clash with the same name defined
7111// in the importing library.
7112TEST_CASE(DartAPI_ImportLibrary2) {
7113 const char* kScriptChars =
7114 "import 'library1_dart';\n"
7115 "var foo;\n"
7116 "main() { foo = 0; }\n";
7117 const char* kLibrary1Chars =
7118 "library library1_dart;\n"
7119 "import 'library2_dart';\n"
7120 "var foo;\n";
7121 const char* kLibrary2Chars =
7122 "library library2_dart;\n"
7123 "import 'library1_dart';\n"
7124 "var foo;\n";
7125 Dart_Handle result;
7126 Dart_Handle lib;
7127
7128 // Create a test library and Load up a test script in it.
7129 Dart_SourceFile sourcefiles[] = {
7130 {RESOLVED_USER_TEST_URI, kScriptChars},
7131 {"file:///library1_dart", kLibrary1Chars},
7132 {"file:///library2_dart", kLibrary2Chars},
7133 };
7134 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7135 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, NULL,
7136 true);
7137 EXPECT_VALID(lib);
7138
7139 result = Dart_FinalizeLoading(false);
7140 EXPECT_VALID(result);
7141 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
7142 EXPECT_VALID(result);
7143}
7144
7145// Test that if the same name is imported from two libraries, it is
7146// an error if that name is referenced.
7147TEST_CASE(DartAPI_ImportLibrary3) {
7148 const char* kScriptChars =
7149 "import 'file:///library2_dart';\n"
7150 "import 'file:///library1_dart';\n"
7151 "var foo_top = 10; // foo has dup def. So should be an error.\n"
7152 "main() { foo = 0; }\n";
7153 const char* kLibrary1Chars =
7154 "library library1_dart;\n"
7155 "var foo;";
7156 const char* kLibrary2Chars =
7157 "library library2_dart;\n"
7158 "var foo;";
7159 Dart_Handle result;
7160 Dart_Handle lib;
7161
7162 // Create a test library and Load up a test script in it.
7163 Dart_SourceFile sourcefiles[] = {
7164 {RESOLVED_USER_TEST_URI, kScriptChars},
7165 {"file:///library2_dart", kLibrary2Chars},
7166 {"file:///library1_dart", kLibrary1Chars},
7167 };
7168 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7169 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, NULL,
7170 true);
7171 EXPECT_ERROR(lib,
7172 "Compilation failed /test-lib:4:10:"
7173 " Error: Setter not found: 'foo'");
7174 return;
7175
7176 result = Dart_FinalizeLoading(false);
7177 EXPECT_VALID(result);
7178 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
7179 EXPECT(Dart_IsError(result));
7180 EXPECT_SUBSTRING("NoSuchMethodError", Dart_GetError(result));
7181}
7182
7183// Test that if the same name is imported from two libraries, it is
7184// not an error if that name is not used.
7185TEST_CASE(DartAPI_ImportLibrary4) {
7186 const char* kScriptChars =
7187 "import 'library2_dart';\n"
7188 "import 'library1_dart';\n"
7189 "main() { }\n";
7190 const char* kLibrary1Chars =
7191 "library library1_dart;\n"
7192 "var foo;";
7193 const char* kLibrary2Chars =
7194 "library library2_dart;\n"
7195 "var foo;";
7196 Dart_Handle result;
7197 Dart_Handle lib;
7198
7199 // Create a test library and Load up a test script in it.
7200 Dart_SourceFile sourcefiles[] = {
7201 {RESOLVED_USER_TEST_URI, kScriptChars},
7202 {"file:///library2_dart", kLibrary2Chars},
7203 {"file:///library1_dart", kLibrary1Chars},
7204 };
7205 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7206 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, NULL,
7207 true);
7208 EXPECT_VALID(lib);
7209
7210 result = Dart_FinalizeLoading(false);
7211 EXPECT_VALID(result);
7212 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
7213 EXPECT_VALID(result);
7214}
7215
7216TEST_CASE(DartAPI_ImportLibrary5) {
7217 const char* kScriptChars =
7218 "import 'lib.dart';\n"
7219 "abstract class Y {\n"
7220 " void set handler(void callback(List<int> x));\n"
7221 "}\n"
7222 "void main() {}\n";
7223 const char* kLibraryChars =
7224 "library lib.dart;\n"
7225 "abstract class X {\n"
7226 " void set handler(void callback(List<int> x));\n"
7227 "}\n";
7228 Dart_Handle result;
7229 Dart_Handle lib;
7230
7231 // Create a test library and Load up a test script in it.
7232 Dart_SourceFile sourcefiles[] = {
7233 {RESOLVED_USER_TEST_URI, kScriptChars},
7234 {"file:///lib.dart", kLibraryChars},
7235 };
7236 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7237 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, NULL,
7238 true);
7239 EXPECT_VALID(lib);
7240
7241 result = Dart_FinalizeLoading(false);
7242 EXPECT_VALID(result);
7243 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
7244 EXPECT_VALID(result);
7245}
7246
7247TEST_CASE(DartAPI_Multiroot_Valid) {
7248 const char* kScriptChars =
7249 "import 'lib.dart';\n"
7250 "void main() {}\n";
7251 const char* kLibraryChars = "library lib.dart;\n";
7252 Dart_Handle result;
7253 Dart_Handle lib;
7254
7255 Dart_SourceFile sourcefiles[] = {
7256 {"file:///bar/main.dart", kScriptChars},
7257 {"file:///baz/lib.dart", kLibraryChars},
7258 {"file:///bar/.packages", ""},
7259 };
7260 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7261 lib = TestCase::LoadTestScriptWithDFE(
7262 sourcefiles_count, sourcefiles, NULL, /* finalize= */ true,
7263 /* incrementally= */ true, /* allow_compile_errors= */ false,
7264 "foo:///main.dart",
7265 /* multiroot_filepaths= */ "/bar,/baz",
7266 /* multiroot_scheme= */ "foo");
7267 EXPECT_VALID(lib);
7268 {
7269 TransitionNativeToVM transition(thread);
7270 Library& lib_obj = Library::Handle();
7271 lib_obj ^= Api::UnwrapHandle(lib);
7272 EXPECT_STREQ("foo:///main.dart", String::Handle(lib_obj.url()).ToCString());
7273 const Array& lib_scripts = Array::Handle(lib_obj.LoadedScripts());
7274 Script& script = Script::Handle();
7275 String& uri = String::Handle();
7276 for (intptr_t i = 0; i < lib_scripts.Length(); i++) {
7277 script ^= lib_scripts.At(i);
7278 uri = script.url();
7279 const char* uri_str = uri.ToCString();
7280 EXPECT(strstr(uri_str, "foo:///") == uri_str);
7281 }
7282 }
7283 result = Dart_FinalizeLoading(false);
7284 EXPECT_VALID(result);
7285 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
7286 EXPECT_VALID(result);
7287}
7288
7289TEST_CASE(DartAPI_Multiroot_FailWhenUriIsWrong) {
7290 const char* kScriptChars =
7291 "import 'lib.dart';\n"
7292 "void main() {}\n";
7293 const char* kLibraryChars = "library lib.dart;\n";
7294 Dart_Handle lib;
7295
7296 Dart_SourceFile sourcefiles[] = {
7297 {"file:///bar/main.dart", kScriptChars},
7298 {"file:///baz/lib.dart", kLibraryChars},
7299 {"file:///bar/.packages", "untitled:/"},
7300 };
7301 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7302 lib = TestCase::LoadTestScriptWithDFE(
7303 sourcefiles_count, sourcefiles, NULL, /* finalize= */ true,
7304 /* incrementally= */ true, /* allow_compile_errors= */ false,
7305 "foo1:///main.dart",
7306 /* multiroot_filepaths= */ "/bar,/baz",
7307 /* multiroot_scheme= */ "foo");
7308 EXPECT_ERROR(lib, "Compilation failed FileSystemException(uri=foo1:");
7309}
7310
7311void NewNativePort_send123(Dart_Port dest_port_id, Dart_CObject* message) {
7312 // Gets a send port message.
7313 EXPECT_NOTNULL(message);
7314 EXPECT_EQ(Dart_CObject_kArray, message->type);
7315 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
7316
7317 // Post integer value.
7318 Dart_CObject* response =
7319 reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
7320 response->type = Dart_CObject_kInt32;
7321 response->value.as_int32 = 123;
7322 Dart_PostCObject(message->value.as_array.values[0]->value.as_send_port.id,
7323 response);
7324}
7325
7326void NewNativePort_send321(Dart_Port dest_port_id, Dart_CObject* message) {
7327 // Gets a null message.
7328 EXPECT_NOTNULL(message);
7329 EXPECT_EQ(Dart_CObject_kArray, message->type);
7330 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
7331
7332 // Post integer value.
7333 Dart_CObject* response =
7334 reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
7335 response->type = Dart_CObject_kInt32;
7336 response->value.as_int32 = 321;
7337 Dart_PostCObject(message->value.as_array.values[0]->value.as_send_port.id,
7338 response);
7339}
7340
7341TEST_CASE(DartAPI_IllegalNewSendPort) {
7342 Dart_Handle error = Dart_NewSendPort(ILLEGAL_PORT);
7343 EXPECT(Dart_IsError(error));
7344 EXPECT(Dart_IsApiError(error));
7345}
7346
7347TEST_CASE(DartAPI_IllegalPost) {
7348 Dart_Handle message = Dart_True();
7349 bool success = Dart_Post(ILLEGAL_PORT, message);
7350 EXPECT(!success);
7351}
7352
7353static void UnreachableFinalizer(void* isolate_callback_data,
7354 Dart_WeakPersistentHandle handle,
7355 void* peer) {
7356 UNREACHABLE();
7357}
7358
7359TEST_CASE(DartAPI_PostCObject_DoesNotRunFinalizerOnFailure) {
7360 char* my_str =
7361 Utils::StrDup("Ownership of this memory remains with the caller");
7362
7363 Dart_CObject message;
7364 message.type = Dart_CObject_kExternalTypedData;
7365 message.value.as_external_typed_data.type = Dart_TypedData_kUint8;
7366 message.value.as_external_typed_data.length = strlen(my_str);
7367 message.value.as_external_typed_data.data =
7368 reinterpret_cast<uint8_t*>(my_str);
7369 message.value.as_external_typed_data.peer = my_str;
7370 message.value.as_external_typed_data.callback = UnreachableFinalizer;
7371
7372 bool success = Dart_PostCObject(ILLEGAL_PORT, &message);
7373 EXPECT(!success);
7374
7375 free(my_str); // Never a double-free.
7376}
7377
7378VM_UNIT_TEST_CASE(DartAPI_NewNativePort) {
7379 // Create a port with a bogus handler.
7380 Dart_Port error_port = Dart_NewNativePort("Foo", NULL, true);
7381 EXPECT_EQ(ILLEGAL_PORT, error_port);
7382
7383 // Create the port w/o a current isolate, just to make sure that works.
7384 Dart_Port port_id1 =
7385 Dart_NewNativePort("Port123", NewNativePort_send123, true);
7386
7387 TestIsolateScope __test_isolate__;
7388 const char* kScriptChars =
7389 "import 'dart:isolate';\n"
7390 "void callPort(SendPort port) {\n"
7391 " var receivePort = new RawReceivePort();\n"
7392 " var replyPort = receivePort.sendPort;\n"
7393 " port.send(<dynamic>[replyPort]);\n"
7394 " receivePort.handler = (message) {\n"
7395 " receivePort.close();\n"
7396 " throw new Exception(message);\n"
7397 " };\n"
7398 "}\n";
7399 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
7400 Dart_EnterScope();
7401
7402 // Create a port w/ a current isolate, to make sure that works too.
7403 Dart_Port port_id2 =
7404 Dart_NewNativePort("Port321", NewNativePort_send321, true);
7405
7406 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
7407 EXPECT_VALID(send_port1);
7408 Dart_Handle send_port2 = Dart_NewSendPort(port_id2);
7409 EXPECT_VALID(send_port2);
7410
7411 // Test first port.
7412 Dart_Handle dart_args[1];
7413 dart_args[0] = send_port1;
7414 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
7415 EXPECT_VALID(result);
7416 result = Dart_RunLoop();
7417 EXPECT(Dart_IsError(result));
7418 EXPECT(Dart_ErrorHasException(result));
7419 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
7420
7421 // result second port.
7422 dart_args[0] = send_port2;
7423 result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
7424 EXPECT_VALID(result);
7425 result = Dart_RunLoop();
7426 EXPECT(Dart_IsError(result));
7427 EXPECT(Dart_ErrorHasException(result));
7428 EXPECT_SUBSTRING("Exception: 321\n", Dart_GetError(result));
7429
7430 Dart_ExitScope();
7431
7432 // Delete the native ports.
7433 EXPECT(Dart_CloseNativePort(port_id1));
7434 EXPECT(Dart_CloseNativePort(port_id2));
7435}
7436
7437void NewNativePort_sendInteger123(Dart_Port dest_port_id,
7438 Dart_CObject* message) {
7439 // Gets a send port message.
7440 EXPECT_NOTNULL(message);
7441 EXPECT_EQ(Dart_CObject_kArray, message->type);
7442 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
7443
7444 // Post integer value.
7445 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
7446 123);
7447}
7448
7449void NewNativePort_sendInteger321(Dart_Port dest_port_id,
7450 Dart_CObject* message) {
7451 // Gets a null message.
7452 EXPECT_NOTNULL(message);
7453 EXPECT_EQ(Dart_CObject_kArray, message->type);
7454 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
7455
7456 // Post integer value.
7457 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
7458 321);
7459}
7460
7461TEST_CASE(DartAPI_NativePortPostInteger) {
7462 const char* kScriptChars =
7463 "import 'dart:isolate';\n"
7464 "void callPort(SendPort port) {\n"
7465 " var receivePort = new RawReceivePort();\n"
7466 " var replyPort = receivePort.sendPort;\n"
7467 " port.send(<dynamic>[replyPort]);\n"
7468 " receivePort.handler = (message) {\n"
7469 " receivePort.close();\n"
7470 " throw new Exception(message);\n"
7471 " };\n"
7472 "}\n";
7473 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
7474 Dart_EnterScope();
7475
7476 Dart_Port port_id1 =
7477 Dart_NewNativePort("Port123", NewNativePort_sendInteger123, true);
7478 Dart_Port port_id2 =
7479 Dart_NewNativePort("Port321", NewNativePort_sendInteger321, true);
7480
7481 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
7482 EXPECT_VALID(send_port1);
7483 Dart_Handle send_port2 = Dart_NewSendPort(port_id2);
7484 EXPECT_VALID(send_port2);
7485
7486 // Test first port.
7487 Dart_Handle dart_args[1];
7488 dart_args[0] = send_port1;
7489 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
7490 EXPECT_VALID(result);
7491 result = Dart_RunLoop();
7492 EXPECT(Dart_IsError(result));
7493 EXPECT(Dart_ErrorHasException(result));
7494 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
7495
7496 // result second port.
7497 dart_args[0] = send_port2;
7498 result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
7499 EXPECT_VALID(result);
7500 result = Dart_RunLoop();
7501 EXPECT(Dart_IsError(result));
7502 EXPECT(Dart_ErrorHasException(result));
7503 EXPECT_SUBSTRING("Exception: 321\n", Dart_GetError(result));
7504
7505 Dart_ExitScope();
7506
7507 // Delete the native ports.
7508 EXPECT(Dart_CloseNativePort(port_id1));
7509 EXPECT(Dart_CloseNativePort(port_id2));
7510}
7511
7512void NewNativePort_nativeReceiveNull(Dart_Port dest_port_id,
7513 Dart_CObject* message) {
7514 EXPECT_NOTNULL(message);
7515
7516 if ((message->type == Dart_CObject_kArray) &&
7517 (message->value.as_array.values[0]->type == Dart_CObject_kSendPort)) {
7518 // Post integer value.
7519 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
7520 123);
7521 } else {
7522 EXPECT_EQ(message->type, Dart_CObject_kNull);
7523 }
7524}
7525
7526TEST_CASE(DartAPI_NativePortReceiveNull) {
7527 const char* kScriptChars =
7528 "import 'dart:isolate';\n"
7529 "void callPort(SendPort port) {\n"
7530 " var receivePort = new RawReceivePort();\n"
7531 " var replyPort = receivePort.sendPort;\n"
7532 " port.send(null);\n"
7533 " port.send(<dynamic>[replyPort]);\n"
7534 " receivePort.handler = (message) {\n"
7535 " receivePort.close();\n"
7536 " throw new Exception(message);\n"
7537 " };\n"
7538 "}\n";
7539 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
7540 Dart_EnterScope();
7541
7542 Dart_Port port_id1 =
7543 Dart_NewNativePort("PortNull", NewNativePort_nativeReceiveNull, true);
7544 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
7545 EXPECT_VALID(send_port1);
7546
7547 // Test first port.
7548 Dart_Handle dart_args[1];
7549 dart_args[0] = send_port1;
7550 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
7551 EXPECT_VALID(result);
7552 result = Dart_RunLoop();
7553 EXPECT(Dart_IsError(result));
7554 EXPECT(Dart_ErrorHasException(result));
7555 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
7556
7557 Dart_ExitScope();
7558
7559 // Delete the native ports.
7560 EXPECT(Dart_CloseNativePort(port_id1));
7561}
7562
7563void NewNativePort_nativeReceiveInteger(Dart_Port dest_port_id,
7564 Dart_CObject* message) {
7565 EXPECT_NOTNULL(message);
7566
7567 if ((message->type == Dart_CObject_kArray) &&
7568 (message->value.as_array.values[0]->type == Dart_CObject_kSendPort)) {
7569 // Post integer value.
7570 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
7571 123);
7572 } else {
7573 EXPECT_EQ(message->type, Dart_CObject_kInt32);
7574 EXPECT_EQ(message->value.as_int32, 321);
7575 }
7576}
7577
7578TEST_CASE(DartAPI_NativePortReceiveInteger) {
7579 const char* kScriptChars =
7580 "import 'dart:isolate';\n"
7581 "void callPort(SendPort port) {\n"
7582 " var receivePort = new RawReceivePort();\n"
7583 " var replyPort = receivePort.sendPort;\n"
7584 " port.send(321);\n"
7585 " port.send(<dynamic>[replyPort]);\n"
7586 " receivePort.handler = (message) {\n"
7587 " receivePort.close();\n"
7588 " throw new Exception(message);\n"
7589 " };\n"
7590 "}\n";
7591 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
7592 Dart_EnterScope();
7593
7594 Dart_Port port_id1 =
7595 Dart_NewNativePort("PortNull", NewNativePort_nativeReceiveInteger, true);
7596 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
7597 EXPECT_VALID(send_port1);
7598
7599 // Test first port.
7600 Dart_Handle dart_args[1];
7601 dart_args[0] = send_port1;
7602 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
7603 EXPECT_VALID(result);
7604 result = Dart_RunLoop();
7605 EXPECT(Dart_IsError(result));
7606 EXPECT(Dart_ErrorHasException(result));
7607 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
7608
7609 Dart_ExitScope();
7610
7611 // Delete the native ports.
7612 EXPECT(Dart_CloseNativePort(port_id1));
7613}
7614
7615static Dart_Isolate RunLoopTestCallback(const char* script_name,
7616 const char* main,
7617 const char* package_root,
7618 const char* package_config,
7619 Dart_IsolateFlags* flags,
7620 void* data,
7621 char** error) {
7622 const char* kScriptChars =
7623 "import 'dart:isolate';\n"
7624 "void main(shouldThrowException) {\n"
7625 " var rp = new RawReceivePort();\n"
7626 " rp.handler = (msg) {\n"
7627 " rp.close();\n"
7628 " if (shouldThrowException) {\n"
7629 " throw new Exception('ExceptionFromTimer');\n"
7630 " }\n"
7631 " };\n"
7632 " rp.sendPort.send(1);\n"
7633 "}\n";
7634
7635 if (Dart_CurrentIsolate() != NULL) {
7636 Dart_ExitIsolate();
7637 }
7638 Dart_Isolate isolate = TestCase::CreateTestIsolate(script_name);
7639 ASSERT(isolate != NULL);
7640 if (Dart_IsServiceIsolate(isolate)) {
7641 return isolate;
7642 }
7643 Dart_EnterScope();
7644 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
7645 EXPECT_VALID(lib);
7646 Dart_Handle result = Dart_FinalizeLoading(false);
7647 EXPECT_VALID(result);
7648 Dart_ExitScope();
7649 Dart_ExitIsolate();
7650 char* err_msg = Dart_IsolateMakeRunnable(isolate);
7651 EXPECT(err_msg == NULL);
7652 return isolate;
7653}
7654
7655// Common code for RunLoop_Success/RunLoop_Failure.
7656static void RunLoopTest(bool throw_exception) {
7657 Dart_IsolateGroupCreateCallback saved = Isolate::CreateGroupCallback();
7658 Isolate::SetCreateGroupCallback(RunLoopTestCallback);
7659 Dart_Isolate isolate =
7660 RunLoopTestCallback(NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7661
7662 Dart_EnterIsolate(isolate);
7663 Dart_EnterScope();
7664 Dart_Handle lib = Dart_LookupLibrary(NewString(TestCase::url()));
7665 EXPECT_VALID(lib);
7666
7667 Dart_Handle result;
7668 Dart_Handle args[1];
7669 args[0] = (throw_exception ? Dart_True() : Dart_False());
7670 result = Dart_Invoke(lib, NewString("main"), 1, args);
7671 EXPECT_VALID(result);
7672 result = Dart_RunLoop();
7673 if (throw_exception) {
7674 EXPECT_ERROR(result, "Exception: ExceptionFromTimer");
7675 } else {
7676 EXPECT_VALID(result);
7677 }
7678
7679 Dart_ExitScope();
7680 Dart_ShutdownIsolate();
7681
7682 Isolate::SetCreateGroupCallback(saved);
7683}
7684
7685VM_UNIT_TEST_CASE(DartAPI_RunLoop_Success) {
7686 RunLoopTest(false);
7687}
7688
7689VM_UNIT_TEST_CASE(DartAPI_RunLoop_Exception) {
7690 RunLoopTest(true);
7691}
7692
7693static void* shutdown_isolate_group_data;
7694static void* shutdown_isolate_data;
7695static void* cleanup_isolate_group_data;
7696static void* cleanup_isolate_data;
7697
7698// Called on isolate shutdown time (which is still allowed to run Dart code)
7699static void IsolateShutdownTestCallback(void* group_data, void* isolate_data) {
7700 // Shutdown runs before cleanup.
7701 EXPECT(cleanup_isolate_group_data == nullptr);
7702 EXPECT(cleanup_isolate_data == nullptr);
7703
7704 // Shutdown must have a current isolate (since it is allowed to execute Dart
7705 // code)
7706 EXPECT(Dart_CurrentIsolate() != nullptr);
7707 EXPECT(Dart_CurrentIsolateGroupData() == group_data);
7708 EXPECT(Dart_CurrentIsolateData() == isolate_data);
7709
7710 shutdown_isolate_group_data = group_data;
7711 shutdown_isolate_data = isolate_data;
7712}
7713
7714// Called on isolate cleanup time (which is after the isolate has been
7715// destroyed)
7716static void IsolateCleanupTestCallback(void* group_data, void* isolate_data) {
7717 // Cleanup runs after shutdown.
7718 EXPECT(shutdown_isolate_group_data != nullptr);
7719 EXPECT(shutdown_isolate_data != nullptr);
7720
7721 // The isolate was destroyed and there should not be a current isolate.
7722 EXPECT(Dart_CurrentIsolate() == nullptr);
7723
7724 cleanup_isolate_group_data = group_data;
7725 cleanup_isolate_data = isolate_data;
7726}
7727
7728// Called on isolate group cleanup time (once all isolates have been destroyed)
7729static void* cleanup_group_callback_data;
7730static void IsolateGroupCleanupTestCallback(void* callback_data) {
7731 cleanup_group_callback_data = callback_data;
7732}
7733
7734VM_UNIT_TEST_CASE(DartAPI_IsolateShutdownAndCleanup) {
7735 Dart_IsolateShutdownCallback saved_shutdown = Isolate::ShutdownCallback();
7736 Dart_IsolateGroupCleanupCallback saved_cleanup =
7737 Isolate::GroupCleanupCallback();
7738 Isolate::SetShutdownCallback(IsolateShutdownTestCallback);
7739 Isolate::SetCleanupCallback(IsolateCleanupTestCallback);
7740 Isolate::SetGroupCleanupCallback(IsolateGroupCleanupTestCallback);
7741
7742 shutdown_isolate_group_data = nullptr;
7743 shutdown_isolate_data = nullptr;
7744 cleanup_group_callback_data = nullptr;
7745 void* my_group_data = reinterpret_cast<void*>(123);
7746 void* my_data = reinterpret_cast<void*>(456);
7747
7748 // Create an isolate.
7749 Dart_Isolate isolate =
7750 TestCase::CreateTestIsolate(nullptr, my_group_data, my_data);
7751 EXPECT(isolate != NULL);
7752
7753 // The shutdown callback has not been called.
7754 EXPECT(nullptr == shutdown_isolate_data);
7755 EXPECT(nullptr == shutdown_isolate_group_data);
7756 EXPECT(nullptr == cleanup_group_callback_data);
7757
7758 // The isolate is the active isolate which allows us to access the isolate
7759 // specific and isolate-group specific data.
7760 EXPECT(Dart_CurrentIsolateData() == my_data);
7761 EXPECT(Dart_CurrentIsolateGroupData() == my_group_data);
7762
7763 // Shutdown the isolate.
7764 Dart_ShutdownIsolate();
7765
7766 // The shutdown & cleanup callbacks have been called.
7767 EXPECT(my_data == shutdown_isolate_data);
7768 EXPECT(my_group_data == shutdown_isolate_group_data);
7769 EXPECT(my_data == cleanup_isolate_data);
7770 EXPECT(my_group_data == cleanup_isolate_group_data);
7771 EXPECT(my_group_data == cleanup_group_callback_data);
7772
7773 Isolate::SetShutdownCallback(saved_shutdown);
7774 Isolate::SetGroupCleanupCallback(saved_cleanup);
7775}
7776
7777static int64_t add_result = 0;
7778static void IsolateShutdownRunDartCodeTestCallback(void* isolate_group_data,
7779 void* isolate_data) {
7780 Dart_Isolate isolate = Dart_CurrentIsolate();
7781 if (Dart_IsKernelIsolate(isolate) || Dart_IsServiceIsolate(isolate)) {
7782 return;
7783 } else {
7784 ASSERT(add_result == 0);
7785 }
7786 Dart_EnterScope();
7787 Dart_Handle lib = Dart_RootLibrary();
7788 EXPECT_VALID(lib);
7789 Dart_Handle arg1 = Dart_NewInteger(90);
7790 EXPECT_VALID(arg1);
7791 Dart_Handle arg2 = Dart_NewInteger(9);
7792 EXPECT_VALID(arg2);
7793 Dart_Handle dart_args[2] = {arg1, arg2};
7794 Dart_Handle result = Dart_Invoke(lib, NewString("add"), 2, dart_args);
7795 EXPECT_VALID(result);
7796 result = Dart_IntegerToInt64(result, &add_result);
7797 EXPECT_VALID(result);
7798 Dart_ExitScope();
7799}
7800
7801VM_UNIT_TEST_CASE(DartAPI_IsolateShutdownRunDartCode) {
7802 const char* kScriptChars =
7803 "int add(int a, int b) {\n"
7804 " return a + b;\n"
7805 "}\n"
7806 "\n"
7807 "void main() {\n"
7808 " add(4, 5);\n"
7809 "}\n";
7810
7811 // Create an isolate.
7812 Dart_Isolate isolate = TestCase::CreateTestIsolate();
7813 EXPECT(isolate != NULL);
7814
7815 Isolate::SetShutdownCallback(IsolateShutdownRunDartCodeTestCallback);
7816
7817 {
7818 Dart_EnterScope();
7819 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
7820 EXPECT_VALID(lib);
7821 Dart_Handle result = Dart_SetLibraryTagHandler(TestCase::library_handler);
7822 EXPECT_VALID(result);
7823 result = Dart_FinalizeLoading(false);
7824 EXPECT_VALID(result);
7825 result = Dart_Invoke(lib, NewString("main"), 0, NULL);
7826 EXPECT_VALID(result);
7827 Dart_ExitScope();
7828 }
7829
7830 // The shutdown callback has not been called.
7831 EXPECT_EQ(0, add_result);
7832
7833 EXPECT(isolate != NULL);
7834
7835 // Shutdown the isolate.
7836 Dart_ShutdownIsolate();
7837
7838 // The shutdown callback has been called and ran Dart code.
7839 EXPECT_EQ(99, add_result);
7840}
7841
7842static int64_t GetValue(Dart_Handle arg) {
7843 EXPECT_VALID(arg);
7844 EXPECT(Dart_IsInteger(arg));
7845 int64_t value;
7846 EXPECT_VALID(Dart_IntegerToInt64(arg, &value));
7847 return value;
7848}
7849
7850static void NativeFoo1(Dart_NativeArguments args) {
7851 Dart_EnterScope();
7852 intptr_t i = Dart_GetNativeArgumentCount(args);
7853 EXPECT_EQ(1, i);
7854 Dart_Handle arg = Dart_GetNativeArgument(args, 0);
7855 EXPECT_VALID(arg);
7856 Dart_SetReturnValue(args, Dart_NewInteger(1));
7857 Dart_ExitScope();
7858}
7859
7860static void NativeFoo2(Dart_NativeArguments args) {
7861 Dart_EnterScope();
7862 intptr_t i = Dart_GetNativeArgumentCount(args);
7863 EXPECT_EQ(2, i);
7864 Dart_Handle arg1 = Dart_GetNativeArgument(args, 1);
7865 EXPECT_VALID(arg1);
7866 int64_t value = 0;
7867 EXPECT_VALID(Dart_IntegerToInt64(arg1, &value));
7868 int64_t integer_value = 0;
7869 Dart_Handle result = Dart_GetNativeIntegerArgument(args, 1, &integer_value);
7870 EXPECT_VALID(result);
7871 EXPECT_EQ(value, integer_value);
7872 double double_value;
7873 result = Dart_GetNativeDoubleArgument(args, 1, &double_value);
7874 EXPECT_VALID(result);
7875 bool bool_value;
7876 result = Dart_GetNativeBooleanArgument(args, 1, &bool_value);
7877 EXPECT(Dart_IsError(result));
7878 Dart_SetReturnValue(args, Dart_NewInteger(GetValue(arg1)));
7879 Dart_ExitScope();
7880}
7881
7882static void NativeFoo3(Dart_NativeArguments args) {
7883 Dart_EnterScope();
7884 intptr_t i = Dart_GetNativeArgumentCount(args);
7885 EXPECT_EQ(3, i);
7886 Dart_Handle arg1 = Dart_GetNativeArgument(args, 1);
7887 Dart_Handle arg2 = Dart_GetNativeArgument(args, 2);
7888 Dart_SetReturnValue(args, Dart_NewInteger(GetValue(arg1) + GetValue(arg2)));
7889 Dart_ExitScope();
7890}
7891
7892static void NativeFoo4(Dart_NativeArguments args) {
7893 Dart_EnterScope();
7894 intptr_t i = Dart_GetNativeArgumentCount(args);
7895 EXPECT_EQ(4, i);
7896 Dart_Handle arg1 = Dart_GetNativeArgument(args, 1);
7897 Dart_Handle arg2 = Dart_GetNativeArgument(args, 2);
7898 Dart_Handle arg3 = Dart_GetNativeArgument(args, 3);
7899 Dart_SetReturnValue(
7900 args, Dart_NewInteger(GetValue(arg1) + GetValue(arg2) + GetValue(arg3)));
7901 Dart_ExitScope();
7902}
7903
7904static Dart_NativeFunction MyNativeClosureResolver(Dart_Handle name,
7905 int arg_count,
7906 bool* auto_setup_scope) {
7907 ASSERT(auto_setup_scope != NULL);
7908 *auto_setup_scope = false;
7909 TransitionNativeToVM transition(Thread::Current());
7910 const Object& obj = Object::Handle(Api::UnwrapHandle(name));
7911 if (!obj.IsString()) {
7912 return NULL;
7913 }
7914 const char* function_name = obj.ToCString();
7915 const char* kNativeFoo1 = "NativeFoo1";
7916 const char* kNativeFoo2 = "NativeFoo2";
7917 const char* kNativeFoo3 = "NativeFoo3";
7918 const char* kNativeFoo4 = "NativeFoo4";
7919 if (strncmp(function_name, kNativeFoo1, strlen(kNativeFoo1)) == 0) {
7920 return &NativeFoo1;
7921 } else if (strncmp(function_name, kNativeFoo2, strlen(kNativeFoo2)) == 0) {
7922 return &NativeFoo2;
7923 } else if (strncmp(function_name, kNativeFoo3, strlen(kNativeFoo3)) == 0) {
7924 return &NativeFoo3;
7925 } else if (strncmp(function_name, kNativeFoo4, strlen(kNativeFoo4)) == 0) {
7926 return &NativeFoo4;
7927 } else {
7928 UNREACHABLE();
7929 return NULL;
7930 }
7931}
7932
7933TEST_CASE(DartAPI_NativeFunctionClosure) {
7934 const char* kScriptChars =
7935 "class Test {"
7936 " int foo1() native \"NativeFoo1\";\n"
7937 " int foo2(int i) native \"NativeFoo2\";\n"
7938 " int foo3([int k = 10000, int l = 1]) native \"NativeFoo3\";\n"
7939 " int foo4(int i,"
7940 " [int j = 10, int k = 1]) native \"NativeFoo4\";\n"
7941 " int bar1() { var func = foo1; return func(); }\n"
7942 " int bar2(int i) { var func = foo2; return func(i); }\n"
7943 " int bar30() { var func = foo3; return func(); }\n"
7944 " int bar31(int i) { var func = foo3; return func(i); }\n"
7945 " int bar32(int i, int j) { var func = foo3; return func(i, j); }\n"
7946 " int bar41(int i) {\n"
7947 " var func = foo4; return func(i); }\n"
7948 " int bar42(int i, int j) {\n"
7949 " var func = foo4; return func(i, j); }\n"
7950 " int bar43(int i, int j, int k) {\n"
7951 " var func = foo4; return func(i, j, k); }\n"
7952 "}\n"
7953 "class Expect {\n"
7954 " static equals(a, b) {\n"
7955 " if (a != b) {\n"
7956 " throw 'not equal. expected: $a, got: $b';\n"
7957 " }\n"
7958 " }\n"
7959 "}\n"
7960 "int testMain() {\n"
7961 " Test obj = new Test();\n"
7962 " Expect.equals(1, obj.foo1());\n"
7963 " Expect.equals(1, obj.bar1());\n"
7964 "\n"
7965 " Expect.equals(10, obj.foo2(10));\n"
7966 " Expect.equals(10, obj.bar2(10));\n"
7967 "\n"
7968 " Expect.equals(10001, obj.foo3());\n"
7969 " Expect.equals(10001, obj.bar30());\n"
7970 " Expect.equals(2, obj.foo3(1));\n"
7971 " Expect.equals(2, obj.bar31(1));\n"
7972 " Expect.equals(4, obj.foo3(2, 2));\n"
7973 " Expect.equals(4, obj.bar32(2, 2));\n"
7974 "\n"
7975 " Expect.equals(12, obj.foo4(1));\n"
7976 " Expect.equals(12, obj.bar41(1));\n"
7977 " Expect.equals(3, obj.foo4(1, 1));\n"
7978 " Expect.equals(3, obj.bar42(1, 1));\n"
7979 " Expect.equals(6, obj.foo4(2, 2, 2));\n"
7980 " Expect.equals(6, obj.bar43(2, 2, 2));\n"
7981 "\n"
7982 " return 0;\n"
7983 "}\n";
7984
7985 Dart_Handle result;
7986
7987 // Load a test script.
7988 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
7989 EXPECT_VALID(lib);
7990 EXPECT(Dart_IsLibrary(lib));
7991 result = Dart_SetNativeResolver(lib, &MyNativeClosureResolver, NULL);
7992 EXPECT_VALID(result);
7993 result = Dart_FinalizeLoading(false);
7994 EXPECT_VALID(result);
7995
7996 result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
7997 EXPECT_VALID(result);
7998 EXPECT(Dart_IsInteger(result));
7999 int64_t value = 0;
8000 EXPECT_VALID(Dart_IntegerToInt64(result, &value));
8001 EXPECT_EQ(0, value);
8002}
8003
8004static void StaticNativeFoo1(Dart_NativeArguments args) {
8005 Dart_EnterScope();
8006 intptr_t i = Dart_GetNativeArgumentCount(args);
8007 EXPECT_EQ(0, i);
8008 Dart_SetReturnValue(args, Dart_NewInteger(0));
8009 Dart_ExitScope();
8010}
8011
8012static void StaticNativeFoo2(Dart_NativeArguments args) {
8013 Dart_EnterScope();
8014 intptr_t i = Dart_GetNativeArgumentCount(args);
8015 EXPECT_EQ(1, i);
8016 Dart_Handle arg = Dart_GetNativeArgument(args, 0);
8017 Dart_SetReturnValue(args, Dart_NewInteger(GetValue(arg)));
8018 Dart_ExitScope();
8019}
8020
8021static void StaticNativeFoo3(Dart_NativeArguments args) {
8022 Dart_EnterScope();
8023 intptr_t i = Dart_GetNativeArgumentCount(args);
8024 EXPECT_EQ(2, i);
8025 Dart_Handle arg1 = Dart_GetNativeArgument(args, 0);
8026 Dart_Handle arg2 = Dart_GetNativeArgument(args, 1);
8027 Dart_SetReturnValue(args, Dart_NewInteger(GetValue(arg1) + GetValue(arg2)));
8028 Dart_ExitScope();
8029}
8030
8031static void StaticNativeFoo4(Dart_NativeArguments args) {
8032 Dart_EnterScope();
8033 intptr_t i = Dart_GetNativeArgumentCount(args);
8034 EXPECT_EQ(3, i);
8035 Dart_Handle arg1 = Dart_GetNativeArgument(args, 0);
8036 Dart_Handle arg2 = Dart_GetNativeArgument(args, 1);
8037 Dart_Handle arg3 = Dart_GetNativeArgument(args, 2);
8038 Dart_SetReturnValue(
8039 args, Dart_NewInteger(GetValue(arg1) + GetValue(arg2) + GetValue(arg3)));
8040 Dart_ExitScope();
8041}
8042
8043static Dart_NativeFunction MyStaticNativeClosureResolver(
8044 Dart_Handle name,
8045 int arg_count,
8046 bool* auto_setup_scope) {
8047 ASSERT(auto_setup_scope != NULL);
8048 *auto_setup_scope = false;
8049 TransitionNativeToVM transition(Thread::Current());
8050 const Object& obj = Object::Handle(Api::UnwrapHandle(name));
8051 if (!obj.IsString()) {
8052 return NULL;
8053 }
8054 const char* function_name = obj.ToCString();
8055 const char* kNativeFoo1 = "StaticNativeFoo1";
8056 const char* kNativeFoo2 = "StaticNativeFoo2";
8057 const char* kNativeFoo3 = "StaticNativeFoo3";
8058 const char* kNativeFoo4 = "StaticNativeFoo4";
8059 if (strncmp(function_name, kNativeFoo1, strlen(kNativeFoo1)) == 0) {
8060 return &StaticNativeFoo1;
8061 } else if (strncmp(function_name, kNativeFoo2, strlen(kNativeFoo2)) == 0) {
8062 return &StaticNativeFoo2;
8063 } else if (strncmp(function_name, kNativeFoo3, strlen(kNativeFoo3)) == 0) {
8064 return &StaticNativeFoo3;
8065 } else if (strncmp(function_name, kNativeFoo4, strlen(kNativeFoo4)) == 0) {
8066 return &StaticNativeFoo4;
8067 } else {
8068 UNREACHABLE();
8069 return NULL;
8070 }
8071}
8072
8073TEST_CASE(DartAPI_NativeStaticFunctionClosure) {
8074 const char* kScriptChars =
8075 "class Test {"
8076 " static int foo1() native \"StaticNativeFoo1\";\n"
8077 " static int foo2(int i) native \"StaticNativeFoo2\";\n"
8078 " static int foo3([int k = 10000, int l = 1])"
8079 " native \"StaticNativeFoo3\";\n"
8080 " static int foo4(int i, [int j = 10, int k = 1])"
8081 " native \"StaticNativeFoo4\";\n"
8082 " int bar1() { var func = foo1; return func(); }\n"
8083 " int bar2(int i) { var func = foo2; return func(i); }\n"
8084 " int bar30() { var func = foo3; return func(); }\n"
8085 " int bar31(int i) { var func = foo3; return func(i); }\n"
8086 " int bar32(int i, int j) { var func = foo3; return func(i, j); }\n"
8087 " int bar41(int i) {\n"
8088 " var func = foo4; return func(i); }\n"
8089 " int bar42(int i, int j) {\n"
8090 " var func = foo4; return func(i, j); }\n"
8091 " int bar43(int i, int j, int k) {\n"
8092 " var func = foo4; return func(i, j, k); }\n"
8093 "}\n"
8094 "class Expect {\n"
8095 " static equals(a, b) {\n"
8096 " if (a != b) {\n"
8097 " throw 'not equal. expected: $a, got: $b';\n"
8098 " }\n"
8099 " }\n"
8100 "}\n"
8101 "int testMain() {\n"
8102 " Test obj = new Test();\n"
8103 " Expect.equals(0, Test.foo1());\n"
8104 " Expect.equals(0, obj.bar1());\n"
8105 "\n"
8106 " Expect.equals(10, Test.foo2(10));\n"
8107 " Expect.equals(10, obj.bar2(10));\n"
8108 "\n"
8109 " Expect.equals(10001, Test.foo3());\n"
8110 " Expect.equals(10001, obj.bar30());\n"
8111 " Expect.equals(2, Test.foo3(1));\n"
8112 " Expect.equals(2, obj.bar31(1));\n"
8113 " Expect.equals(4, Test.foo3(2, 2));\n"
8114 " Expect.equals(4, obj.bar32(2, 2));\n"
8115 "\n"
8116 " Expect.equals(12, Test.foo4(1));\n"
8117 " Expect.equals(12, obj.bar41(1));\n"
8118 " Expect.equals(3, Test.foo4(1, 1));\n"
8119 " Expect.equals(3, obj.bar42(1, 1));\n"
8120 " Expect.equals(6, Test.foo4(2, 2, 2));\n"
8121 " Expect.equals(6, obj.bar43(2, 2, 2));\n"
8122 "\n"
8123 " return 0;\n"
8124 "}\n";
8125
8126 Dart_Handle result;
8127
8128 // Load a test script.
8129 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
8130 EXPECT_VALID(lib);
8131 EXPECT(Dart_IsLibrary(lib));
8132 result = Dart_SetNativeResolver(lib, &MyStaticNativeClosureResolver, NULL);
8133 EXPECT_VALID(result);
8134 result = Dart_FinalizeLoading(false);
8135 EXPECT_VALID(result);
8136
8137 result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
8138 EXPECT_VALID(result);
8139 EXPECT(Dart_IsInteger(result));
8140 int64_t value = 0;
8141 EXPECT_VALID(Dart_IntegerToInt64(result, &value));
8142 EXPECT_EQ(0, value);
8143}
8144
8145TEST_CASE(DartAPI_RangeLimits) {
8146 uint8_t chars8[1] = {'a'};
8147 uint16_t chars16[1] = {'a'};
8148 int32_t chars32[1] = {'a'};
8149
8150 EXPECT_ERROR(Dart_NewList(-1),
8151 "expects argument 'length' to be in the range");
8152 EXPECT_ERROR(Dart_NewList(Array::kMaxElements + 1),
8153 "expects argument 'length' to be in the range");
8154 EXPECT_ERROR(Dart_NewStringFromUTF8(chars8, -1),
8155 "expects argument 'length' to be in the range");
8156 EXPECT_ERROR(Dart_NewStringFromUTF8(chars8, OneByteString::kMaxElements + 1),
8157 "expects argument 'length' to be in the range");
8158 EXPECT_ERROR(Dart_NewStringFromUTF16(chars16, -1),
8159 "expects argument 'length' to be in the range");
8160 EXPECT_ERROR(
8161 Dart_NewStringFromUTF16(chars16, TwoByteString::kMaxElements + 1),
8162 "expects argument 'length' to be in the range");
8163 EXPECT_ERROR(Dart_NewStringFromUTF32(chars32, -1),
8164 "expects argument 'length' to be in the range");
8165 EXPECT_ERROR(
8166 Dart_NewStringFromUTF32(chars32, TwoByteString::kMaxElements + 1),
8167 "expects argument 'length' to be in the range");
8168}
8169
8170TEST_CASE(DartAPI_NewString_Null) {
8171 Dart_Handle str = Dart_NewStringFromUTF8(NULL, 0);
8172 EXPECT_VALID(str);
8173 EXPECT(Dart_IsString(str));
8174 intptr_t len = -1;
8175 EXPECT_VALID(Dart_StringLength(str, &len));
8176 EXPECT_EQ(0, len);
8177
8178 str = Dart_NewStringFromUTF16(NULL, 0);
8179 EXPECT_VALID(str);
8180 EXPECT(Dart_IsString(str));
8181 len = -1;
8182 EXPECT_VALID(Dart_StringLength(str, &len));
8183 EXPECT_EQ(0, len);
8184
8185 str = Dart_NewStringFromUTF32(NULL, 0);
8186 EXPECT_VALID(str);
8187 EXPECT(Dart_IsString(str));
8188 len = -1;
8189 EXPECT_VALID(Dart_StringLength(str, &len));
8190 EXPECT_EQ(0, len);
8191}
8192
8193// Try to allocate a peer with a handles to objects of prohibited
8194// subtypes.
8195TEST_CASE(DartAPI_InvalidGetSetPeer) {
8196 void* out = &out;
8197 EXPECT(Dart_IsError(Dart_GetPeer(Dart_Null(), &out)));
8198 EXPECT(out == &out);
8199 EXPECT(Dart_IsError(Dart_SetPeer(Dart_Null(), &out)));
8200 out = &out;
8201 EXPECT(Dart_IsError(Dart_GetPeer(Dart_True(), &out)));
8202 EXPECT(out == &out);
8203 EXPECT(Dart_IsError(Dart_SetPeer(Dart_True(), &out)));
8204 out = &out;
8205 EXPECT(Dart_IsError(Dart_GetPeer(Dart_False(), &out)));
8206 EXPECT(out == &out);
8207 EXPECT(Dart_IsError(Dart_SetPeer(Dart_False(), &out)));
8208 out = &out;
8209 Dart_Handle smi = Dart_NewInteger(0);
8210 EXPECT(Dart_IsError(Dart_GetPeer(smi, &out)));
8211 EXPECT(out == &out);
8212 EXPECT(Dart_IsError(Dart_SetPeer(smi, &out)));
8213 out = &out;
8214 Dart_Handle big = Dart_NewIntegerFromHexCString("0x10000000000000000");
8215 EXPECT(Dart_IsApiError(big));
8216 out = &out;
8217 Dart_Handle dbl = Dart_NewDouble(0.0);
8218 EXPECT(Dart_IsError(Dart_GetPeer(dbl, &out)));
8219 EXPECT(out == &out);
8220 EXPECT(Dart_IsError(Dart_SetPeer(dbl, &out)));
8221}
8222
8223// Allocates an object in new space and assigns it a peer. Removes
8224// the peer and checks that the count of peer objects is decremented
8225// by one.
8226TEST_CASE(DartAPI_OneNewSpacePeer) {
8227 Isolate* isolate = Isolate::Current();
8228 Dart_Handle str = NewString("a string");
8229 EXPECT_VALID(str);
8230 EXPECT(Dart_IsString(str));
8231 EXPECT_EQ(0, isolate->heap()->PeerCount());
8232 void* out = &out;
8233 EXPECT_VALID(Dart_GetPeer(str, &out));
8234 EXPECT(out == NULL);
8235 int peer = 1234;
8236 EXPECT_VALID(Dart_SetPeer(str, &peer));
8237 EXPECT_EQ(1, isolate->heap()->PeerCount());
8238 out = &out;
8239 EXPECT_VALID(Dart_GetPeer(str, &out));
8240 EXPECT(out == reinterpret_cast<void*>(&peer));
8241 EXPECT_VALID(Dart_SetPeer(str, NULL));
8242 out = &out;
8243 EXPECT_VALID(Dart_GetPeer(str, &out));
8244 EXPECT(out == NULL);
8245 EXPECT_EQ(0, isolate->heap()->PeerCount());
8246}
8247
8248// Allocates an object in new space and assigns it a peer. Allows the
8249// peer referent to be garbage collected and checks that the count of
8250// peer objects is decremented by one.
8251TEST_CASE(DartAPI_CollectOneNewSpacePeer) {
8252 Isolate* isolate = Isolate::Current();
8253 Dart_EnterScope();
8254 {
8255 CHECK_API_SCOPE(thread);
8256 Dart_Handle str = NewString("a string");
8257 EXPECT_VALID(str);
8258 EXPECT(Dart_IsString(str));
8259 EXPECT_EQ(0, isolate->heap()->PeerCount());
8260 void* out = &out;
8261 EXPECT_VALID(Dart_GetPeer(str, &out));
8262 EXPECT(out == NULL);
8263 int peer = 1234;
8264 EXPECT_VALID(Dart_SetPeer(str, &peer));
8265 EXPECT_EQ(1, isolate->heap()->PeerCount());
8266 out = &out;
8267 EXPECT_VALID(Dart_GetPeer(str, &out));
8268 EXPECT(out == reinterpret_cast<void*>(&peer));
8269 {
8270 TransitionNativeToVM transition(thread);
8271 GCTestHelper::CollectNewSpace();
8272 EXPECT_EQ(1, isolate->heap()->PeerCount());
8273 }
8274 out = &out;
8275 EXPECT_VALID(Dart_GetPeer(str, &out));
8276 EXPECT(out == reinterpret_cast<void*>(&peer));
8277 }
8278 Dart_ExitScope();
8279 {
8280 TransitionNativeToVM transition(thread);
8281 GCTestHelper::CollectNewSpace();
8282 EXPECT_EQ(0, isolate->heap()->PeerCount());
8283 }
8284}
8285
8286// Allocates two objects in new space and assigns them peers. Removes
8287// the peers and checks that the count of peer objects is decremented
8288// by two.
8289TEST_CASE(DartAPI_TwoNewSpacePeers) {
8290 Isolate* isolate = Isolate::Current();
8291 Dart_Handle s1 = NewString("s1");
8292 EXPECT_VALID(s1);
8293 EXPECT(Dart_IsString(s1));
8294 void* o1 = &o1;
8295 EXPECT_VALID(Dart_GetPeer(s1, &o1));
8296 EXPECT(o1 == NULL);
8297 EXPECT_EQ(0, isolate->heap()->PeerCount());
8298 int p1 = 1234;
8299 EXPECT_VALID(Dart_SetPeer(s1, &p1));
8300 EXPECT_EQ(1, isolate->heap()->PeerCount());
8301 EXPECT_VALID(Dart_GetPeer(s1, &o1));
8302 EXPECT(o1 == reinterpret_cast<void*>(&p1));
8303 Dart_Handle s2 = NewString("a string");
8304 EXPECT_VALID(s2);
8305 EXPECT(Dart_IsString(s2));
8306 EXPECT_EQ(1, isolate->heap()->PeerCount());
8307 void* o2 = &o2;
8308 EXPECT(Dart_GetPeer(s2, &o2));
8309 EXPECT(o2 == NULL);
8310 int p2 = 5678;
8311 EXPECT_VALID(Dart_SetPeer(s2, &p2));
8312 EXPECT_EQ(2, isolate->heap()->PeerCount());
8313 EXPECT_VALID(Dart_GetPeer(s2, &o2));
8314 EXPECT(o2 == reinterpret_cast<void*>(&p2));
8315 EXPECT_VALID(Dart_SetPeer(s1, NULL));
8316 EXPECT_EQ(1, isolate->heap()->PeerCount());
8317 EXPECT(Dart_GetPeer(s1, &o1));
8318 EXPECT(o1 == NULL);
8319 EXPECT_VALID(Dart_SetPeer(s2, NULL));
8320 EXPECT_EQ(0, isolate->heap()->PeerCount());
8321 EXPECT(Dart_GetPeer(s2, &o2));
8322 EXPECT(o2 == NULL);
8323}
8324
8325// Allocates two objects in new space and assigns them a peer. Allow
8326// the peer referents to be garbage collected and check that the count
8327// of peer objects is decremented by two.
8328TEST_CASE(DartAPI_CollectTwoNewSpacePeers) {
8329 Isolate* isolate = Isolate::Current();
8330 Dart_EnterScope();
8331 {
8332 CHECK_API_SCOPE(thread);
8333 Dart_Handle s1 = NewString("s1");
8334 EXPECT_VALID(s1);
8335 EXPECT(Dart_IsString(s1));
8336 EXPECT_EQ(0, isolate->heap()->PeerCount());
8337 void* o1 = &o1;
8338 EXPECT(Dart_GetPeer(s1, &o1));
8339 EXPECT(o1 == NULL);
8340 int p1 = 1234;
8341 EXPECT_VALID(Dart_SetPeer(s1, &p1));
8342 EXPECT_EQ(1, isolate->heap()->PeerCount());
8343 EXPECT_VALID(Dart_GetPeer(s1, &o1));
8344 EXPECT(o1 == reinterpret_cast<void*>(&p1));
8345 Dart_Handle s2 = NewString("s2");
8346 EXPECT_VALID(s2);
8347 EXPECT(Dart_IsString(s2));
8348 EXPECT_EQ(1, isolate->heap()->PeerCount());
8349 void* o2 = &o2;
8350 EXPECT(Dart_GetPeer(s2, &o2));
8351 EXPECT(o2 == NULL);
8352 int p2 = 5678;
8353 EXPECT_VALID(Dart_SetPeer(s2, &p2));
8354 EXPECT_EQ(2, isolate->heap()->PeerCount());
8355 EXPECT_VALID(Dart_GetPeer(s2, &o2));
8356 EXPECT(o2 == reinterpret_cast<void*>(&p2));
8357 }
8358 Dart_ExitScope();
8359 {
8360 TransitionNativeToVM transition(thread);
8361 GCTestHelper::CollectNewSpace();
8362 EXPECT_EQ(0, isolate->heap()->PeerCount());
8363 }
8364}
8365
8366// Allocates several objects in new space. Performs successive
8367// garbage collections and checks that the peer count is stable.
8368TEST_CASE(DartAPI_CopyNewSpacePeers) {
8369 const int kPeerCount = 10;
8370 Isolate* isolate = Isolate::Current();
8371 Dart_Handle s[kPeerCount];
8372 for (int i = 0; i < kPeerCount; ++i) {
8373 s[i] = NewString("a string");
8374 EXPECT_VALID(s[i]);
8375 EXPECT(Dart_IsString(s[i]));
8376 void* o = &o;
8377 EXPECT_VALID(Dart_GetPeer(s[i], &o));
8378 EXPECT(o == NULL);
8379 }
8380 EXPECT_EQ(0, isolate->heap()->PeerCount());
8381 int p[kPeerCount];
8382 for (int i = 0; i < kPeerCount; ++i) {
8383 EXPECT_VALID(Dart_SetPeer(s[i], &p[i]));
8384 EXPECT_EQ(i + 1, isolate->heap()->PeerCount());
8385 void* o = &o;
8386 EXPECT_VALID(Dart_GetPeer(s[i], &o));
8387 EXPECT(o == reinterpret_cast<void*>(&p[i]));
8388 }
8389 EXPECT_EQ(kPeerCount, isolate->heap()->PeerCount());
8390 {
8391 TransitionNativeToVM transition(thread);
8392 GCTestHelper::CollectNewSpace();
8393 EXPECT_EQ(kPeerCount, isolate->heap()->PeerCount());
8394 GCTestHelper::CollectNewSpace();
8395 EXPECT_EQ(kPeerCount, isolate->heap()->PeerCount());
8396 }
8397}
8398
8399// Allocates an object in new space and assigns it a peer. Promotes
8400// the peer to old space. Removes the peer and check that the count
8401// of peer objects is decremented by one.
8402TEST_CASE(DartAPI_OnePromotedPeer) {
8403 Isolate* isolate = Isolate::Current();
8404 Dart_Handle str = NewString("a string");
8405 EXPECT_VALID(str);
8406 EXPECT(Dart_IsString(str));
8407 EXPECT_EQ(0, isolate->heap()->PeerCount());
8408 void* out = &out;
8409 EXPECT(Dart_GetPeer(str, &out));
8410 EXPECT(out == NULL);
8411 int peer = 1234;
8412 EXPECT_VALID(Dart_SetPeer(str, &peer));
8413 out = &out;
8414 EXPECT(Dart_GetPeer(str, &out));
8415 EXPECT(out == reinterpret_cast<void*>(&peer));
8416 EXPECT_EQ(1, isolate->heap()->PeerCount());
8417 {
8418 TransitionNativeToVM transition(thread);
8419 GCTestHelper::CollectNewSpace();
8420 GCTestHelper::CollectNewSpace();
8421 }
8422 {
8423 CHECK_API_SCOPE(thread);
8424 TransitionNativeToVM transition(thread);
8425 HANDLESCOPE(thread);
8426 String& handle = String::Handle();
8427 handle ^= Api::UnwrapHandle(str);
8428 EXPECT(handle.IsOld());
8429 }
8430 EXPECT_VALID(Dart_GetPeer(str, &out));
8431 EXPECT(out == reinterpret_cast<void*>(&peer));
8432 EXPECT_EQ(1, isolate->heap()->PeerCount());
8433 EXPECT_VALID(Dart_SetPeer(str, NULL));
8434 out = &out;
8435 EXPECT_VALID(Dart_GetPeer(str, &out));
8436 EXPECT(out == NULL);
8437 EXPECT_EQ(0, isolate->heap()->PeerCount());
8438}
8439
8440// Allocates an object in old space and assigns it a peer. Removes
8441// the peer and checks that the count of peer objects is decremented
8442// by one.
8443TEST_CASE(DartAPI_OneOldSpacePeer) {
8444 Isolate* isolate = Isolate::Current();
8445 Dart_Handle str = AllocateOldString("str");
8446 EXPECT_VALID(str);
8447 EXPECT(Dart_IsString(str));
8448 EXPECT_EQ(0, isolate->heap()->PeerCount());
8449 void* out = &out;
8450 EXPECT(Dart_GetPeer(str, &out));
8451 EXPECT(out == NULL);
8452 int peer = 1234;
8453 EXPECT_VALID(Dart_SetPeer(str, &peer));
8454 EXPECT_EQ(1, isolate->heap()->PeerCount());
8455 out = &out;
8456 EXPECT_VALID(Dart_GetPeer(str, &out));
8457 EXPECT(out == reinterpret_cast<void*>(&peer));
8458 {
8459 TransitionNativeToVM transition(thread);
8460 GCTestHelper::CollectOldSpace();
8461 EXPECT_EQ(1, isolate->heap()->PeerCount());
8462 }
8463 EXPECT_VALID(Dart_GetPeer(str, &out));
8464 EXPECT(out == reinterpret_cast<void*>(&peer));
8465 EXPECT_VALID(Dart_SetPeer(str, NULL));
8466 out = &out;
8467 EXPECT_VALID(Dart_GetPeer(str, &out));
8468 EXPECT(out == NULL);
8469 EXPECT_EQ(0, isolate->heap()->PeerCount());
8470}
8471
8472// Allocates an object in old space and assigns it a peer. Allow the
8473// peer referent to be garbage collected and check that the count of
8474// peer objects is decremented by one.
8475TEST_CASE(DartAPI_CollectOneOldSpacePeer) {
8476 Isolate* isolate = Isolate::Current();
8477 Dart_EnterScope();
8478 {
8479 Thread* T = Thread::Current();
8480 CHECK_API_SCOPE(T);
8481 Dart_Handle str = AllocateOldString("str");
8482 EXPECT_VALID(str);
8483 EXPECT(Dart_IsString(str));
8484 EXPECT_EQ(0, isolate->heap()->PeerCount());
8485 void* out = &out;
8486 EXPECT(Dart_GetPeer(str, &out));
8487 EXPECT(out == NULL);
8488 int peer = 1234;
8489 EXPECT_VALID(Dart_SetPeer(str, &peer));
8490 EXPECT_EQ(1, isolate->heap()->PeerCount());
8491 out = &out;
8492 EXPECT_VALID(Dart_GetPeer(str, &out));
8493 EXPECT(out == reinterpret_cast<void*>(&peer));
8494 {
8495 TransitionNativeToVM transition(thread);
8496 GCTestHelper::CollectOldSpace();
8497 EXPECT_EQ(1, isolate->heap()->PeerCount());
8498 }
8499 EXPECT_VALID(Dart_GetPeer(str, &out));
8500 EXPECT(out == reinterpret_cast<void*>(&peer));
8501 }
8502 Dart_ExitScope();
8503 {
8504 TransitionNativeToVM transition(thread);
8505 GCTestHelper::CollectOldSpace();
8506 EXPECT_EQ(0, isolate->heap()->PeerCount());
8507 }
8508}
8509
8510// Allocates two objects in old space and assigns them peers. Removes
8511// the peers and checks that the count of peer objects is decremented
8512// by two.
8513TEST_CASE(DartAPI_TwoOldSpacePeers) {
8514 Isolate* isolate = Isolate::Current();
8515 Dart_Handle s1 = AllocateOldString("s1");
8516 EXPECT_VALID(s1);
8517 EXPECT(Dart_IsString(s1));
8518 EXPECT_EQ(0, isolate->heap()->PeerCount());
8519 void* o1 = &o1;
8520 EXPECT(Dart_GetPeer(s1, &o1));
8521 EXPECT(o1 == NULL);
8522 int p1 = 1234;
8523 EXPECT_VALID(Dart_SetPeer(s1, &p1));
8524 EXPECT_EQ(1, isolate->heap()->PeerCount());
8525 o1 = &o1;
8526 EXPECT_VALID(Dart_GetPeer(s1, &o1));
8527 EXPECT(o1 == reinterpret_cast<void*>(&p1));
8528 Dart_Handle s2 = AllocateOldString("s2");
8529 EXPECT_VALID(s2);
8530 EXPECT(Dart_IsString(s2));
8531 EXPECT_EQ(1, isolate->heap()->PeerCount());
8532 void* o2 = &o2;
8533 EXPECT(Dart_GetPeer(s2, &o2));
8534 EXPECT(o2 == NULL);
8535 int p2 = 5678;
8536 EXPECT_VALID(Dart_SetPeer(s2, &p2));
8537 EXPECT_EQ(2, isolate->heap()->PeerCount());
8538 o2 = &o2;
8539 EXPECT_VALID(Dart_GetPeer(s2, &o2));
8540 EXPECT(o2 == reinterpret_cast<void*>(&p2));
8541 EXPECT_VALID(Dart_SetPeer(s1, NULL));
8542 EXPECT_EQ(1, isolate->heap()->PeerCount());
8543 o1 = &o1;
8544 EXPECT(Dart_GetPeer(s1, &o1));
8545 EXPECT(o1 == NULL);
8546 EXPECT_VALID(Dart_SetPeer(s2, NULL));
8547 EXPECT_EQ(0, isolate->heap()->PeerCount());
8548 o2 = &o2;
8549 EXPECT_VALID(Dart_GetPeer(s2, &o2));
8550 EXPECT(o2 == NULL);
8551}
8552
8553// Allocates two objects in old space and assigns them a peer. Allows
8554// the peer referents to be garbage collected and checks that the
8555// count of peer objects is decremented by two.
8556TEST_CASE(DartAPI_CollectTwoOldSpacePeers) {
8557 Isolate* isolate = Isolate::Current();
8558 Dart_EnterScope();
8559 {
8560 Thread* T = Thread::Current();
8561 CHECK_API_SCOPE(T);
8562 Dart_Handle s1 = AllocateOldString("s1");
8563 EXPECT_VALID(s1);
8564 EXPECT(Dart_IsString(s1));
8565 EXPECT_EQ(0, isolate->heap()->PeerCount());
8566 void* o1 = &o1;
8567 EXPECT(Dart_GetPeer(s1, &o1));
8568 EXPECT(o1 == NULL);
8569 int p1 = 1234;
8570 EXPECT_VALID(Dart_SetPeer(s1, &p1));
8571 EXPECT_EQ(1, isolate->heap()->PeerCount());
8572 o1 = &o1;
8573 EXPECT_VALID(Dart_GetPeer(s1, &o1));
8574 EXPECT(o1 == reinterpret_cast<void*>(&p1));
8575 Dart_Handle s2 = AllocateOldString("s2");
8576 EXPECT_VALID(s2);
8577 EXPECT(Dart_IsString(s2));
8578 EXPECT_EQ(1, isolate->heap()->PeerCount());
8579 void* o2 = &o2;
8580 EXPECT(Dart_GetPeer(s2, &o2));
8581 EXPECT(o2 == NULL);
8582 int p2 = 5678;
8583 EXPECT_VALID(Dart_SetPeer(s2, &p2));
8584 EXPECT_EQ(2, isolate->heap()->PeerCount());
8585 o2 = &o2;
8586 EXPECT_VALID(Dart_GetPeer(s2, &o2));
8587 EXPECT(o2 == reinterpret_cast<void*>(&p2));
8588 }
8589 Dart_ExitScope();
8590 {
8591 TransitionNativeToVM transition(thread);
8592 GCTestHelper::CollectOldSpace();
8593 EXPECT_EQ(0, isolate->heap()->PeerCount());
8594 }
8595}
8596
8597TEST_CASE(DartAPI_ExternalStringIndexOf) {
8598 const char* kScriptChars =
8599 "main(String pattern) {\n"
8600 " var str = 'Hello World';\n"
8601 " return str.indexOf(pattern);\n"
8602 "}\n";
8603 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
8604
8605 uint8_t data8[] = {'W'};
8606 Dart_Handle ext8 = Dart_NewExternalLatin1String(
8607 data8, ARRAY_SIZE(data8), data8, sizeof(data8), NoopFinalizer);
8608 EXPECT_VALID(ext8);
8609 EXPECT(Dart_IsString(ext8));
8610 EXPECT(Dart_IsExternalString(ext8));
8611
8612 Dart_Handle dart_args[1];
8613 dart_args[0] = ext8;
8614 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 1, dart_args);
8615 int64_t value = 0;
8616 result = Dart_IntegerToInt64(result, &value);
8617 EXPECT_VALID(result);
8618 EXPECT_EQ(6, value);
8619}
8620
8621TEST_CASE(DartAPI_StringFromExternalTypedData) {
8622 const char* kScriptChars =
8623 "test(external) {\n"
8624 " var str1 = new String.fromCharCodes(external);\n"
8625 " var str2 = new String.fromCharCodes(new List.from(external));\n"
8626 " if (str2 != str1) throw 'FAIL';\n"
8627 " return str1;\n"
8628 "}\n"
8629 "testView8(external) {\n"
8630 " return test(external.buffer.asUint8List());\n"
8631 "}\n"
8632 "testView16(external) {\n"
8633 " return test(external.buffer.asUint16List());\n"
8634 "}\n";
8635 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
8636
8637 {
8638 uint8_t data[64];
8639 for (int i = 0; i < 64; i++) {
8640 data[i] = i * 4;
8641 }
8642 // LATIN-1 in external Uint8List.
8643 Dart_Handle external =
8644 Dart_NewExternalTypedData(Dart_TypedData_kUint8, data, 64);
8645 EXPECT_VALID(external);
8646 Dart_Handle dart_args[1];
8647 dart_args[0] = external;
8648 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 1, dart_args);
8649 EXPECT_VALID(result);
8650 EXPECT(Dart_IsString(result));
8651
8652 result = Dart_Invoke(lib, NewString("testView8"), 1, dart_args);
8653 EXPECT_VALID(result);
8654 EXPECT(Dart_IsString(result));
8655 }
8656
8657 {
8658 uint16_t data[64];
8659 for (int i = 0; i < 64; i++) {
8660 data[i] = i * 4;
8661 }
8662 // LATIN-1 in external Uint16List.
8663 Dart_Handle external =
8664 Dart_NewExternalTypedData(Dart_TypedData_kUint16, data, 64);
8665 EXPECT_VALID(external);
8666 Dart_Handle dart_args[1];
8667 dart_args[0] = external;
8668 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 1, dart_args);
8669 EXPECT_VALID(result);
8670 EXPECT(Dart_IsString(result));
8671
8672 result = Dart_Invoke(lib, NewString("testView16"), 1, dart_args);
8673 EXPECT_VALID(result);
8674 EXPECT(Dart_IsString(result));
8675 }
8676
8677 {
8678 uint16_t data[64];
8679 for (int i = 0; i < 64; i++) {
8680 data[i] = 0x2000 + i * 4;
8681 }
8682 // Non-LATIN-1 in external Uint16List.
8683 Dart_Handle external =
8684 Dart_NewExternalTypedData(Dart_TypedData_kUint16, data, 64);
8685 EXPECT_VALID(external);
8686 Dart_Handle dart_args[1];
8687 dart_args[0] = external;
8688 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 1, dart_args);
8689 EXPECT_VALID(result);
8690 EXPECT(Dart_IsString(result));
8691
8692 result = Dart_Invoke(lib, NewString("testView16"), 1, dart_args);
8693 EXPECT_VALID(result);
8694 EXPECT(Dart_IsString(result));
8695 }
8696}
8697
8698#ifndef PRODUCT
8699
8700TEST_CASE(DartAPI_TimelineDuration) {
8701 Isolate* isolate = Isolate::Current();
8702 // Grab embedder stream.
8703 TimelineStream* stream = Timeline::GetEmbedderStream();
8704 // Make sure it is enabled.
8705 stream->set_enabled(true);
8706 // Add a duration event.
8707 Dart_TimelineEvent("testDurationEvent", 0, 1, Dart_Timeline_Event_Duration, 0,
8708 NULL, NULL);
8709 // Check that it is in the output.
8710 TimelineEventRecorder* recorder = Timeline::recorder();
8711 Timeline::ReclaimCachedBlocksFromThreads();
8712 JSONStream js;
8713 IsolateTimelineEventFilter filter(isolate->main_port());
8714 recorder->PrintJSON(&js, &filter);
8715 EXPECT_SUBSTRING("testDurationEvent", js.ToCString());
8716}
8717
8718TEST_CASE(DartAPI_TimelineInstant) {
8719 Isolate* isolate = Isolate::Current();
8720 // Grab embedder stream.
8721 TimelineStream* stream = Timeline::GetEmbedderStream();
8722 // Make sure it is enabled.
8723 stream->set_enabled(true);
8724 Dart_TimelineEvent("testInstantEvent", 0, 1, Dart_Timeline_Event_Instant, 0,
8725 NULL, NULL);
8726 // Check that it is in the output.
8727 TimelineEventRecorder* recorder = Timeline::recorder();
8728 Timeline::ReclaimCachedBlocksFromThreads();
8729 JSONStream js;
8730 IsolateTimelineEventFilter filter(isolate->main_port());
8731 recorder->PrintJSON(&js, &filter);
8732 EXPECT_SUBSTRING("testInstantEvent", js.ToCString());
8733}
8734
8735TEST_CASE(DartAPI_TimelineAsyncDisabled) {
8736 // Grab embedder stream.
8737 TimelineStream* stream = Timeline::GetEmbedderStream();
8738 // Make sure it is disabled.
8739 stream->set_enabled(false);
8740 int64_t async_id = 99;
8741 Dart_TimelineEvent("testAsyncEvent", 0, async_id,
8742 Dart_Timeline_Event_Async_Begin, 0, NULL, NULL);
8743 // Check that testAsync is not in the output.
8744 TimelineEventRecorder* recorder = Timeline::recorder();
8745 Timeline::ReclaimCachedBlocksFromThreads();
8746 JSONStream js;
8747 TimelineEventFilter filter;
8748 recorder->PrintJSON(&js, &filter);
8749 EXPECT_NOTSUBSTRING("testAsyncEvent", js.ToCString());
8750}
8751
8752TEST_CASE(DartAPI_TimelineAsync) {
8753 Isolate* isolate = Isolate::Current();
8754 // Grab embedder stream.
8755 TimelineStream* stream = Timeline::GetEmbedderStream();
8756 // Make sure it is enabled.
8757 stream->set_enabled(true);
8758 int64_t async_id = 99;
8759 Dart_TimelineEvent("testAsyncEvent", 0, async_id,
8760 Dart_Timeline_Event_Async_Begin, 0, NULL, NULL);
8761
8762 // Check that it is in the output.
8763 TimelineEventRecorder* recorder = Timeline::recorder();
8764 Timeline::ReclaimCachedBlocksFromThreads();
8765 JSONStream js;
8766 IsolateTimelineEventFilter filter(isolate->main_port());
8767 recorder->PrintJSON(&js, &filter);
8768 EXPECT_SUBSTRING("testAsyncEvent", js.ToCString());
8769}
8770
8771static void HintFreedNative(Dart_NativeArguments args) {
8772 int64_t size = 0;
8773 EXPECT_VALID(Dart_GetNativeIntegerArgument(args, 0, &size));
8774 Dart_HintFreed(size);
8775}
8776
8777static Dart_NativeFunction HintFreed_native_lookup(Dart_Handle name,
8778 int argument_count,
8779 bool* auto_setup_scope) {
8780 return HintFreedNative;
8781}
8782
8783TEST_CASE(DartAPI_HintFreed) {
8784 const char* kScriptChars =
8785 "void hintFreed(int size) native 'Test_nativeFunc';\n"
8786 "void main() {\n"
8787 " var v;\n"
8788 " for (var i = 0; i < 100; i++) {\n"
8789 " var t = [];\n"
8790 " for (var j = 0; j < 10000; j++) {\n"
8791 " t.add(List.filled(100, null));\n"
8792 " }\n"
8793 " v = t;\n"
8794 " hintFreed(100 * 10000 * 4);\n"
8795 " }\n"
8796 "}\n";
8797 Dart_Handle lib =
8798 TestCase::LoadTestScript(kScriptChars, &HintFreed_native_lookup);
8799 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
8800 EXPECT_VALID(result);
8801}
8802
8803static void NotifyIdleShortNative(Dart_NativeArguments args) {
8804 Dart_NotifyIdle(Dart_TimelineGetMicros() + 10 * kMicrosecondsPerMillisecond);
8805}
8806
8807static Dart_NativeFunction NotifyIdleShort_native_lookup(
8808 Dart_Handle name,
8809 int argument_count,
8810 bool* auto_setup_scope) {
8811 return NotifyIdleShortNative;
8812}
8813
8814TEST_CASE(DartAPI_NotifyIdleShort) {
8815 const char* kScriptChars =
8816 "void notifyIdle() native 'Test_nativeFunc';\n"
8817 "void main() {\n"
8818 " var v;\n"
8819 " for (var i = 0; i < 100; i++) {\n"
8820 " var t = [];\n"
8821 " for (var j = 0; j < 10000; j++) {\n"
8822 " t.add(List.filled(100, null));\n"
8823 " }\n"
8824 " v = t;\n"
8825 " notifyIdle();\n"
8826 " }\n"
8827 "}\n";
8828 Dart_Handle lib =
8829 TestCase::LoadTestScript(kScriptChars, &NotifyIdleShort_native_lookup);
8830 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
8831 EXPECT_VALID(result);
8832}
8833
8834static void NotifyIdleLongNative(Dart_NativeArguments args) {
8835 Dart_NotifyIdle(Dart_TimelineGetMicros() + 100 * kMicrosecondsPerMillisecond);
8836}
8837
8838static Dart_NativeFunction NotifyIdleLong_native_lookup(
8839 Dart_Handle name,
8840 int argument_count,
8841 bool* auto_setup_scope) {
8842 return NotifyIdleLongNative;
8843}
8844
8845TEST_CASE(DartAPI_NotifyIdleLong) {
8846 const char* kScriptChars =
8847 "void notifyIdle() native 'Test_nativeFunc';\n"
8848 "void main() {\n"
8849 " var v;\n"
8850 " for (var i = 0; i < 100; i++) {\n"
8851 " var t = [];\n"
8852 " for (var j = 0; j < 10000; j++) {\n"
8853 " t.add(List.filled(100, null));\n"
8854 " }\n"
8855 " v = t;\n"
8856 " notifyIdle();\n"
8857 " }\n"
8858 "}\n";
8859 Dart_Handle lib =
8860 TestCase::LoadTestScript(kScriptChars, &NotifyIdleLong_native_lookup);
8861 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
8862 EXPECT_VALID(result);
8863}
8864
8865static void NotifyLowMemoryNative(Dart_NativeArguments args) {
8866 Dart_NotifyLowMemory();
8867}
8868
8869static Dart_NativeFunction NotifyLowMemory_native_lookup(
8870 Dart_Handle name,
8871 int argument_count,
8872 bool* auto_setup_scope) {
8873 return NotifyLowMemoryNative;
8874}
8875
8876TEST_CASE(DartAPI_NotifyLowMemory) {
8877 const char* kScriptChars =
8878 "import 'dart:isolate';\n"
8879 "void notifyLowMemory() native 'Test_nativeFunc';\n"
8880 "void main() {\n"
8881 " var v;\n"
8882 " for (var i = 0; i < 100; i++) {\n"
8883 " var t = [];\n"
8884 " for (var j = 0; j < 10000; j++) {\n"
8885 " t.add(List.filled(100, null));\n"
8886 " }\n"
8887 " v = t;\n"
8888 " notifyLowMemory();\n"
8889 " }\n"
8890 "}\n";
8891 Dart_Handle lib =
8892 TestCase::LoadTestScript(kScriptChars, &NotifyLowMemory_native_lookup);
8893 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
8894 EXPECT_VALID(result);
8895}
8896
8897// There exists another test by name DartAPI_Invoke_CrossLibrary.
8898// However, that currently fails for the dartk configuration as it
8899// uses Dart_LoadLibray. This test here effectively tests the same
8900// functionality but invokes a function from an imported standard
8901// library.
8902TEST_CASE(DartAPI_InvokeImportedFunction) {
8903 const char* kScriptChars =
8904 "import 'dart:math';\n"
8905 "import 'dart:developer';\n"
8906 "main() {}";
8907 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
8908 EXPECT_VALID(lib);
8909
8910 Dart_Handle max = Dart_NewStringFromCString("max");
8911
8912 Dart_Handle args[2] = {Dart_NewInteger(123), Dart_NewInteger(321)};
8913 Dart_Handle result = Dart_Invoke(lib, max, 2, args);
8914 EXPECT_ERROR(result,
8915 "NoSuchMethodError: No top-level method 'max' declared.");
8916
8917 Dart_Handle getCurrentTag = Dart_NewStringFromCString("getCurrentTag");
8918 result = Dart_Invoke(lib, getCurrentTag, 0, NULL);
8919 EXPECT_ERROR(
8920 result,
8921 "NoSuchMethodError: No top-level method 'getCurrentTag' declared.");
8922}
8923
8924TEST_CASE(DartAPI_InvokeVMServiceMethod) {
8925 char buffer[1024];
8926 snprintf(buffer, sizeof(buffer),
8927 R"({
8928 "jsonrpc": 2.0,
8929 "id": "foo",
8930 "method": "getVM",
8931 "params": { }
8932 })");
8933 uint8_t* response_json = nullptr;
8934 intptr_t response_json_length = 0;
8935 char* error = nullptr;
8936 const bool success = Dart_InvokeVMServiceMethod(
8937 reinterpret_cast<uint8_t*>(buffer), strlen(buffer), &response_json,
8938 &response_json_length, &error);
8939 EXPECT(success);
8940 EXPECT(error == nullptr);
8941
8942 Dart_Handle bytes = Dart_NewExternalTypedDataWithFinalizer(
8943 Dart_TypedData_kUint8, response_json, response_json_length, response_json,
8944 response_json_length,
8945 [](void* ignored, Dart_WeakPersistentHandle handle, void* peer) {
8946 free(peer);
8947 });
8948 EXPECT_VALID(bytes);
8949
8950 // We don't have a C++ JSON decoder so we'll invoke dart to validate the
8951 // result.
8952 const char* kScript =
8953 R"(
8954 import 'dart:convert';
8955 import 'dart:typed_data';
8956 bool validate(bool condition) {
8957 if (!condition) {
8958 throw 'Failed to validate InvokeVMServiceMethod() response.';
8959 }
8960 return false;
8961 }
8962 bool validateResult(Uint8List bytes) {
8963 final map = json.decode(utf8.decode(bytes));
8964 validate(map['jsonrpc'] == '2.0');
8965 validate(map['id'] == 'foo');
8966 validate(map['result']['name'] == 'vm');
8967 validate(map['result']['type'] == 'VM');
8968 validate(map['result'].containsKey('architectureBits'));
8969 validate(map['result'].containsKey('pid'));
8970 validate(map['result'].containsKey('startTime'));
8971 validate(map['result'].containsKey('hostCPU'));
8972 validate(map['result'].containsKey('targetCPU'));
8973 validate(map['result'].containsKey('version'));
8974 return true;
8975 }
8976 )";
8977
8978 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
8979 EXPECT_VALID(lib);
8980 Dart_Handle result = Dart_Invoke(lib, NewString("validateResult"), 1, &bytes);
8981 EXPECT(Dart_IsBoolean(result));
8982 EXPECT(result == Dart_True());
8983}
8984
8985#endif // !PRODUCT
8986
8987} // namespace dart
8988