Flutter Engine
The Flutter Engine
dart_api_impl_test.cc
Go to the documentation of this file.
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"
11#include "platform/assert.h"
13#include "platform/utils.h"
14#include "vm/class_finalizer.h"
16#include "vm/dart.h"
17#include "vm/dart_api_state.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);
27DECLARE_FLAG(bool, complete_timeline);
28
29#ifndef PRODUCT
30
31UNIT_TEST_CASE(DartAPI_DartInitializeAfterCleanup) {
34 memset(&params, 0, sizeof(Dart_InitializeParams));
36 params.vm_snapshot_data = TesterState::vm_snapshot_data;
38 params.shutdown_isolate = TesterState::shutdown_callback;
40 params.start_kernel_isolate = true;
41
42 // Reinitialize and ensure we can execute Dart code.
43 EXPECT(Dart_Initialize(&params) == nullptr);
44 {
45 TestIsolateScope scope;
46 const char* kScriptChars =
47 "int testMain() {\n"
48 " return 42;\n"
49 "}\n";
50 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
51 EXPECT_VALID(lib);
52 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
54 int64_t value = 0;
56 EXPECT_EQ(42, value);
57 }
58 EXPECT(Dart_Cleanup() == nullptr);
59}
60
61UNIT_TEST_CASE(DartAPI_DartInitializeCallsCodeObserver) {
64 memset(&params, 0, sizeof(Dart_InitializeParams));
66 params.vm_snapshot_data = TesterState::vm_snapshot_data;
68 params.shutdown_isolate = TesterState::shutdown_callback;
70 params.start_kernel_isolate = true;
71
72 bool was_called = false;
73 Dart_CodeObserver code_observer;
74 code_observer.data = &was_called;
75 code_observer.on_new_code = [](Dart_CodeObserver* observer, const char* name,
76 uintptr_t base, uintptr_t size) {
77 *static_cast<bool*>(observer->data) = true;
78 };
79 params.code_observer = &code_observer;
80
81 // Reinitialize and ensure we can execute Dart code.
82 EXPECT(Dart_Initialize(&params) == nullptr);
83
84 // Wait for 5 seconds to let the kernel service load the snapshot,
85 // which should trigger calls to the code observer.
86 OS::Sleep(5);
87
88 EXPECT(was_called);
89 EXPECT(Dart_Cleanup() == nullptr);
90}
91
92UNIT_TEST_CASE(DartAPI_DartInitializeHeapSizes) {
94 memset(&params, 0, sizeof(Dart_InitializeParams));
96 params.vm_snapshot_data = TesterState::vm_snapshot_data;
98 params.shutdown_isolate = TesterState::shutdown_callback;
100 params.start_kernel_isolate = true;
101
102 // Initialize with a normal heap size specification.
103 const char* options_1[] = {"--old-gen-heap-size=3192",
104 "--new-gen-semi-max-size=32"};
105 EXPECT(Dart_SetVMFlags(2, options_1) == nullptr);
106 EXPECT(Dart_Initialize(&params) == nullptr);
107 EXPECT(FLAG_old_gen_heap_size == 3192);
108 EXPECT(FLAG_new_gen_semi_max_size == 32);
109 EXPECT(Dart_Cleanup() == nullptr);
110
111 const char* options_2[] = {"--old-gen-heap-size=16384",
112 "--new-gen-semi-max-size=16384"};
113 EXPECT(Dart_SetVMFlags(2, options_2) == nullptr);
114 EXPECT(Dart_Initialize(&params) == nullptr);
115 if (kMaxAddrSpaceMB == 4096) {
116 EXPECT(FLAG_old_gen_heap_size == 0);
117 EXPECT(FLAG_new_gen_semi_max_size == kDefaultNewGenSemiMaxSize);
118 } else {
119 EXPECT(FLAG_old_gen_heap_size == 16384);
120 EXPECT(FLAG_new_gen_semi_max_size == 16384);
121 }
122 EXPECT(Dart_Cleanup() == nullptr);
123
124 const char* options_3[] = {"--old-gen-heap-size=30720",
125 "--new-gen-semi-max-size=30720"};
126 EXPECT(Dart_SetVMFlags(2, options_3) == nullptr);
127 EXPECT(Dart_Initialize(&params) == nullptr);
128 if (kMaxAddrSpaceMB == 4096) {
129 EXPECT(FLAG_old_gen_heap_size == 0);
130 EXPECT(FLAG_new_gen_semi_max_size == kDefaultNewGenSemiMaxSize);
131 } else {
132 EXPECT(FLAG_old_gen_heap_size == 30720);
133 EXPECT(FLAG_new_gen_semi_max_size == 30720);
134 }
135 EXPECT(Dart_Cleanup() == nullptr);
136}
137
139 const char* kScriptChars =
140 "int testMain() {\n"
141 " return 42;\n"
142 "}\n";
143 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
144 EXPECT_VALID(lib);
145 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
147 int64_t value = 0;
149 EXPECT_EQ(42, value);
150 Dart_Isolate isolate = reinterpret_cast<Dart_Isolate>(Isolate::Current());
151 Dart_KillIsolate(isolate);
152 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
154 EXPECT_STREQ("isolate terminated by Isolate.kill", Dart_GetError(result));
155}
156
158 public:
159 InfiniteLoopTask(Dart_Isolate* isolate, Monitor* monitor, bool* interrupted)
160 : isolate_(isolate), monitor_(monitor), interrupted_(interrupted) {}
161 virtual void Run() {
162 TestIsolateScope scope;
163 const char* kScriptChars =
164 "testMain() {\n"
165 " while(true) {};"
166 "}\n";
167 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
168 EXPECT_VALID(lib);
169 *isolate_ = reinterpret_cast<Dart_Isolate>(Isolate::Current());
170 {
171 MonitorLocker ml(monitor_);
172 ml.Notify();
173 }
174 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
175 // Test should run an infinite loop and expect that to be killed.
177 EXPECT_STREQ("isolate terminated by Isolate.kill", Dart_GetError(result));
178 {
179 MonitorLocker ml(monitor_);
180 *interrupted_ = true;
181 ml.Notify();
182 }
183 }
184
185 private:
186 Dart_Isolate* isolate_;
187 Monitor* monitor_;
188 bool* interrupted_;
189};
190
191TEST_CASE(Dart_KillIsolatePriority) {
192 Monitor monitor;
193 bool interrupted = false;
194 Dart_Isolate isolate;
195 Dart::thread_pool()->Run<InfiniteLoopTask>(&isolate, &monitor, &interrupted);
196 {
197 MonitorLocker ml(&monitor);
198 ml.Wait();
199 }
200
201 Dart_KillIsolate(isolate);
202
203 {
204 MonitorLocker ml(&monitor);
205 while (!interrupted) {
206 ml.Wait();
207 }
208 }
209 EXPECT(interrupted);
210}
211
212TEST_CASE(DartAPI_ErrorHandleBasics) {
213 const char* kScriptChars =
214 "void testMain() {\n"
215 " throw new Exception(\"bad news\");\n"
216 "}\n";
217
218 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
219
221 Dart_Handle error = Api::NewError("myerror");
222 Dart_Handle exception = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
223
226 EXPECT(Dart_IsError(exception));
227
230 EXPECT(Dart_ErrorHasException(exception));
231
232 EXPECT_STREQ("", Dart_GetError(instance));
233 EXPECT_STREQ("myerror", Dart_GetError(error));
234 EXPECT_STREQ(ZONE_STR("Unhandled exception:\n"
235 "Exception: bad news\n"
236 "#0 testMain (%s:2:3)",
237 TestCase::url()),
238 Dart_GetError(exception));
239
246}
247
248TEST_CASE(DartAPI_StackTraceInfo) {
249 const char* kScriptChars =
250 "bar() => throw new Error();\n"
251 "foo() => bar();\n"
252 "testMain() => foo();\n";
253
254 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
255 Dart_Handle error = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
256
258
259 Dart_StackTrace stacktrace;
262
263 intptr_t frame_count = 0;
264 result = Dart_StackTraceLength(stacktrace, &frame_count);
266 EXPECT_EQ(3, frame_count);
267
269 Dart_Handle script_url;
270 intptr_t line_number = 0;
271 intptr_t column_number = 0;
272 const char* cstr = "";
273
275 result = Dart_GetActivationFrame(stacktrace, 0, &frame);
278 &line_number, &column_number);
281 EXPECT_STREQ("bar", cstr);
282 Dart_StringToCString(script_url, &cstr);
283 EXPECT_SUBSTRING("test-lib", cstr);
284 EXPECT_EQ(1, line_number);
285 EXPECT_EQ(10, column_number);
286
287 result = Dart_GetActivationFrame(stacktrace, 1, &frame);
290 &line_number, &column_number);
293 EXPECT_STREQ("foo", cstr);
294 Dart_StringToCString(script_url, &cstr);
295 EXPECT_SUBSTRING("test-lib", cstr);
296 EXPECT_EQ(2, line_number);
297 EXPECT_EQ(10, column_number);
298
299 result = Dart_GetActivationFrame(stacktrace, 2, &frame);
302 &line_number, &column_number);
305 EXPECT_STREQ("testMain", cstr);
306 Dart_StringToCString(script_url, &cstr);
307 EXPECT_SUBSTRING("test-lib", cstr);
308 EXPECT_EQ(3, line_number);
309 EXPECT_EQ(15, column_number);
310
311 // Out-of-bounds frames.
312 result = Dart_GetActivationFrame(stacktrace, frame_count, &frame);
314 result = Dart_GetActivationFrame(stacktrace, -1, &frame);
316}
317
318TEST_CASE(DartAPI_DeepStackTraceInfo) {
319 const char* kScriptChars =
320 "foo(n) => n == 1 ? throw new Error() : foo(n-1);\n"
321 "testMain() => foo(100);\n";
322
323 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
324 Dart_Handle error = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
325
327
328 Dart_StackTrace stacktrace;
331
332 intptr_t frame_count = 0;
333 result = Dart_StackTraceLength(stacktrace, &frame_count);
335 EXPECT_EQ(101, frame_count);
336 // Test something bigger than the preallocated size to verify nothing was
337 // truncated.
339
341 Dart_Handle script_url;
342 intptr_t line_number = 0;
343 intptr_t column_number = 0;
344 const char* cstr = "";
345
346 // Top frame at positioned at throw.
348 result = Dart_GetActivationFrame(stacktrace, 0, &frame);
351 &line_number, &column_number);
354 EXPECT_STREQ("foo", cstr);
355 Dart_StringToCString(script_url, &cstr);
356 EXPECT_SUBSTRING("test-lib", cstr);
357 EXPECT_EQ(1, line_number);
358 EXPECT_EQ(20, column_number);
359
360 // Middle frames positioned at the recursive call.
361 for (intptr_t frame_index = 1; frame_index < (frame_count - 1);
362 frame_index++) {
363 result = Dart_GetActivationFrame(stacktrace, frame_index, &frame);
366 &line_number, &column_number);
369 EXPECT_STREQ("foo", cstr);
370 Dart_StringToCString(script_url, &cstr);
371 EXPECT_SUBSTRING("test-lib", cstr);
372 EXPECT_EQ(1, line_number);
373 EXPECT_EQ(40, column_number);
374 }
375
376 // Bottom frame positioned at testMain().
377 result = Dart_GetActivationFrame(stacktrace, frame_count - 1, &frame);
380 &line_number, &column_number);
383 EXPECT_STREQ("testMain", cstr);
384 Dart_StringToCString(script_url, &cstr);
385 EXPECT_SUBSTRING("test-lib", cstr);
386 EXPECT_EQ(2, line_number);
387 EXPECT_EQ(15, column_number);
388
389 // Out-of-bounds frames.
390 result = Dart_GetActivationFrame(stacktrace, frame_count, &frame);
392 result = Dart_GetActivationFrame(stacktrace, -1, &frame);
394}
395
397 const char* top_frame_func_name,
398 const char* entry_func_name,
399 int expected_line_number,
400 int expected_column_number) {
402 Dart_Handle error = Dart_Invoke(lib, NewString(entry_func_name), 0, nullptr);
403
405
406 Dart_StackTrace stacktrace;
409
410 intptr_t frame_count = 0;
411 result = Dart_StackTraceLength(stacktrace, &frame_count);
413 EXPECT_EQ(StackTrace::kPreallocatedStackdepth - 1, frame_count);
414
416 Dart_Handle script_url;
417 intptr_t line_number = 0;
418 intptr_t column_number = 0;
419 const char* cstr = "";
420
421 // Top frame at recursive call.
423 result = Dart_GetActivationFrame(stacktrace, 0, &frame);
426 &line_number, &column_number);
429 EXPECT_STREQ(top_frame_func_name, cstr);
430 Dart_StringToCString(script_url, &cstr);
431 EXPECT_STREQ(TestCase::url(), cstr);
432 EXPECT_EQ(expected_line_number, line_number);
433 EXPECT_EQ(expected_column_number, column_number);
434
435 // Out-of-bounds frames.
436 result = Dart_GetActivationFrame(stacktrace, frame_count, &frame);
438 result = Dart_GetActivationFrame(stacktrace, -1, &frame);
440}
441
442TEST_CASE(DartAPI_StackOverflowStackTraceInfoBraceFunction1) {
443 int line = 2;
444 int col = 3;
446 "class C {\n"
447 " static foo(int i) { foo(i); }\n"
448 "}\n"
449 "testMain() => C.foo(10);\n",
450 "C.foo", "testMain", line, col);
451}
452
453TEST_CASE(DartAPI_StackOverflowStackTraceInfoBraceFunction2) {
454 int line = 2;
455 int col = 3;
457 "class C {\n"
458 " static foo(int i, int j) {\n"
459 " foo(i, j);\n"
460 " }\n"
461 "}\n"
462 "testMain() => C.foo(10, 11);\n",
463 "C.foo", "testMain", line, col);
464}
465
466TEST_CASE(DartAPI_StackOverflowStackTraceInfoArrowFunction) {
467 int line = 2;
468 int col = 3;
470 "class C {\n"
471 " static foo(int i) => foo(i);\n"
472 "}\n"
473 "testMain() => C.foo(10);\n",
474 "C.foo", "testMain", line, col);
475}
476
477TEST_CASE(DartAPI_OutOfMemoryStackTraceInfo) {
478 const char* kScriptChars =
479 "var number_of_ints = 134000000;\n"
480 "testMain() {\n"
481 " new List<int>(number_of_ints)\n"
482 "}\n";
483
484 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
485 Dart_Handle error = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
486
488
489 Dart_StackTrace stacktrace;
491 EXPECT(Dart_IsError(result)); // No StackTrace for OutOfMemory.
492}
493
496
497 Dart_StackTrace stacktrace;
500
501 intptr_t frame_count = 0;
502 result = Dart_StackTraceLength(stacktrace, &frame_count);
504 EXPECT_EQ(102, frame_count);
505 // Test something bigger than the preallocated size to verify nothing was
506 // truncated.
508
510 Dart_Handle script_url;
511 intptr_t line_number = 0;
512 intptr_t column_number = 0;
513 const char* cstr = "";
514 const char* test_lib = "file:///test-lib";
515
516 // Top frame is inspectStack().
518 result = Dart_GetActivationFrame(stacktrace, 0, &frame);
521 &line_number, &column_number);
524 EXPECT_STREQ("inspectStack", cstr);
525 Dart_StringToCString(script_url, &cstr);
526 EXPECT_STREQ(test_lib, cstr);
527 EXPECT_EQ(3, line_number);
528 EXPECT_EQ(24, column_number);
529
530 // Second frame is foo() positioned at call to inspectStack().
531 result = Dart_GetActivationFrame(stacktrace, 1, &frame);
534 &line_number, &column_number);
537 EXPECT_STREQ("foo", cstr);
538 Dart_StringToCString(script_url, &cstr);
539 EXPECT_STREQ(test_lib, cstr);
540 EXPECT_EQ(4, line_number);
541 EXPECT_EQ(20, column_number);
542
543 // Middle frames positioned at the recursive call.
544 for (intptr_t frame_index = 2; frame_index < (frame_count - 1);
545 frame_index++) {
546 result = Dart_GetActivationFrame(stacktrace, frame_index, &frame);
549 &line_number, &column_number);
552 EXPECT_STREQ("foo", cstr);
553 Dart_StringToCString(script_url, &cstr);
554 EXPECT_STREQ(test_lib, cstr);
555 EXPECT_EQ(4, line_number);
556 EXPECT_EQ(37, column_number);
557 }
558
559 // Bottom frame positioned at testMain().
560 result = Dart_GetActivationFrame(stacktrace, frame_count - 1, &frame);
563 &line_number, &column_number);
566 EXPECT_STREQ("testMain", cstr);
567 Dart_StringToCString(script_url, &cstr);
568 EXPECT_STREQ(test_lib, cstr);
569 EXPECT_EQ(5, line_number);
570 EXPECT_EQ(15, column_number);
571
572 // Out-of-bounds frames.
573 result = Dart_GetActivationFrame(stacktrace, frame_count, &frame);
575 result = Dart_GetActivationFrame(stacktrace, -1, &frame);
577
580}
581
584 int argument_count,
585 bool* auto_setup_scope) {
586 ASSERT(auto_setup_scope != nullptr);
587 *auto_setup_scope = true;
589}
590
591TEST_CASE(DartAPI_CurrentStackTraceInfo) {
592 const char* kScriptChars = R"(
593@pragma("vm:external-name", "CurrentStackTraceNative")
594external inspectStack();
595foo(n) => n == 1 ? inspectStack() : foo(n-1);
596testMain() => foo(100);
597 )";
598
599 Dart_Handle lib =
601 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
604 int64_t value = 0;
606 EXPECT_EQ(42, value);
607}
608
609#endif // !PRODUCT
610
611TEST_CASE(DartAPI_ErrorHandleTypes) {
612 Dart_Handle not_error = NewString("NotError");
613 Dart_Handle api_error = Dart_NewApiError("ApiError");
614 Dart_Handle exception_error =
616 Dart_Handle compile_error = Dart_NewCompilationError("CompileError");
617 Dart_Handle fatal_error;
618 {
619 TransitionNativeToVM transition(thread);
620 const String& fatal_message = String::Handle(String::New("FatalError"));
621 fatal_error = Api::NewHandle(thread, UnwindError::New(fatal_message));
622 }
623
624 EXPECT_VALID(not_error);
625 EXPECT(Dart_IsError(api_error));
626 EXPECT(Dart_IsError(exception_error));
627 EXPECT(Dart_IsError(compile_error));
628 EXPECT(Dart_IsError(fatal_error));
629
630 EXPECT(!Dart_IsApiError(not_error));
631 EXPECT(Dart_IsApiError(api_error));
632 EXPECT(!Dart_IsApiError(exception_error));
633 EXPECT(!Dart_IsApiError(compile_error));
634 EXPECT(!Dart_IsApiError(fatal_error));
635
638 EXPECT(Dart_IsUnhandledExceptionError(exception_error));
639 EXPECT(!Dart_IsUnhandledExceptionError(compile_error));
641
642 EXPECT(!Dart_IsCompilationError(not_error));
643 EXPECT(!Dart_IsCompilationError(api_error));
644 EXPECT(!Dart_IsCompilationError(exception_error));
645 EXPECT(Dart_IsCompilationError(compile_error));
646 EXPECT(!Dart_IsCompilationError(fatal_error));
647
648 EXPECT(!Dart_IsFatalError(not_error));
649 EXPECT(!Dart_IsFatalError(api_error));
650 EXPECT(!Dart_IsFatalError(exception_error));
651 EXPECT(!Dart_IsFatalError(compile_error));
652 EXPECT(Dart_IsFatalError(fatal_error));
653
654 EXPECT_STREQ("", Dart_GetError(not_error));
655 EXPECT_STREQ("ApiError", Dart_GetError(api_error));
656 EXPECT_SUBSTRING("Unhandled exception:\nExceptionError",
657 Dart_GetError(exception_error));
658 EXPECT_STREQ("CompileError", Dart_GetError(compile_error));
659 EXPECT_STREQ("FatalError", Dart_GetError(fatal_error));
660}
661
662TEST_CASE(DartAPI_UnhandleExceptionError) {
663 const char* exception_cstr = "";
664
665 // Test with an API Error.
666 const char* kApiError = "Api Error Exception Test.";
667 Dart_Handle api_error = Dart_NewApiError(kApiError);
668 Dart_Handle exception_error = Dart_NewUnhandledExceptionError(api_error);
669 EXPECT(!Dart_IsApiError(exception_error));
670 EXPECT(Dart_IsUnhandledExceptionError(exception_error));
673 &exception_cstr));
674 EXPECT_STREQ(kApiError, exception_cstr);
675
676 // Test with a Compilation Error.
677 const char* kCompileError = "CompileError Exception Test.";
679 exception_error = Dart_NewUnhandledExceptionError(compile_error);
680 EXPECT(!Dart_IsApiError(exception_error));
681 EXPECT(Dart_IsUnhandledExceptionError(exception_error));
684 &exception_cstr));
685 EXPECT_STREQ(kCompileError, exception_cstr);
686
687 // Test with a Fatal Error.
688 Dart_Handle fatal_error;
689 {
690 TransitionNativeToVM transition(thread);
691 const String& fatal_message =
692 String::Handle(String::New("FatalError Exception Test."));
693 fatal_error = Api::NewHandle(thread, UnwindError::New(fatal_message));
694 }
695 exception_error = Dart_NewUnhandledExceptionError(fatal_error);
696 EXPECT(Dart_IsError(exception_error));
697 EXPECT(!Dart_IsUnhandledExceptionError(exception_error));
698
699 // Test with a Regular object.
700 const char* kRegularString = "Regular String Exception Test.";
701 exception_error = Dart_NewUnhandledExceptionError(NewString(kRegularString));
702 EXPECT(!Dart_IsApiError(exception_error));
703 EXPECT(Dart_IsUnhandledExceptionError(exception_error));
706 &exception_cstr));
707 EXPECT_STREQ(kRegularString, exception_cstr);
708}
709
716 UNREACHABLE();
717}
718
720 int argument_count,
721 bool* auto_setup_scope) {
722 ASSERT(auto_setup_scope != nullptr);
723 *auto_setup_scope = true;
725}
726
727TEST_CASE(DartAPI_EnsureUnwindErrorHandled_WhenKilled) {
728 const char* kScriptChars = R"(
729import 'dart:isolate';
730
731exitRightNow() {
732 Isolate.current.kill(priority: Isolate.immediate);
733}
734
735@pragma("vm:external-name", "Test_nativeFunc")
736external void nativeFunc(closure);
737
738void Func1() {
739 nativeFunc(() => exitRightNow());
740}
741)";
742 Dart_Handle lib =
745
746 result = Dart_Invoke(lib, NewString("Func1"), 0, nullptr);
748 EXPECT_SUBSTRING("isolate terminated by Isolate.kill", Dart_GetError(result));
749
750 result = Dart_Invoke(lib, NewString("Func1"), 0, nullptr);
752 EXPECT_SUBSTRING("No api calls are allowed while unwind is in progress",
754}
755
756TEST_CASE(DartAPI_EnsureUnwindErrorHandled_WhenSendAndExit) {
757 const char* kScriptChars = R"(
758import 'dart:isolate';
759
760sendAndExitNow() {
761 final receivePort = ReceivePort();
762 Isolate.exit(receivePort.sendPort, true);
763}
764
765@pragma("vm:external-name", "Test_nativeFunc")
766external void nativeFunc(closure);
767
768void Func1() {
769 nativeFunc(() => sendAndExitNow());
770}
771)";
772 Dart_Handle lib =
775
776 result = Dart_Invoke(lib, NewString("Func1"), 0, nullptr);
778 EXPECT_SUBSTRING("isolate terminated by Isolate.exit", Dart_GetError(result));
779
780 result = Dart_Invoke(lib, NewString("Func1"), 0, nullptr);
782 EXPECT_SUBSTRING("No api calls are allowed while unwind is in progress",
784}
785
786// Should we propagate the error via Dart_SetReturnValue?
787static bool use_set_return = false;
788
789// Should we propagate the error via Dart_ThrowException?
790static bool use_throw_exception = false;
791
797 if (use_set_return) {
799 } else if (use_throw_exception) {
801 EXPECT_VALID(result); // We do not expect to reach here.
802 UNREACHABLE();
803 } else {
805 UNREACHABLE();
806 }
807}
808
811 int argument_count,
812 bool* auto_setup_scope) {
813 ASSERT(auto_setup_scope != nullptr);
814 *auto_setup_scope = true;
816}
817
818TEST_CASE(DartAPI_PropagateCompileTimeError) {
819 const char* kScriptChars = R"(
820raiseCompileError() {
821 return missing_semicolon
822}
823
824@pragma("vm:external-name", "Test_nativeFunc")
825external void nativeFunc(closure);
826
827void Func1() {
828 nativeFunc(() => raiseCompileError());
829}
830)";
831 Dart_Handle lib =
834
835 // Use Dart_PropagateError to propagate the error.
836 use_throw_exception = false;
837 use_set_return = false;
838
839 result = Dart_Invoke(lib, NewString("Func1"), 0, nullptr);
841
842 EXPECT_SUBSTRING("Expected ';' after this.", Dart_GetError(result));
843
844 // Use Dart_SetReturnValue to propagate the error.
845 use_throw_exception = false;
846 use_set_return = true;
847
848 result = Dart_Invoke(lib, NewString("Func1"), 0, nullptr);
850 EXPECT_SUBSTRING("Expected ';' after this.", Dart_GetError(result));
851
852 // Use Dart_ThrowException to propagate the error.
853 use_throw_exception = true;
854 use_set_return = false;
855
856 result = Dart_Invoke(lib, NewString("Func1"), 0, nullptr);
858 EXPECT_SUBSTRING("Expected ';' after this.", Dart_GetError(result));
859}
860
861TEST_CASE(DartAPI_PropagateError) {
862 const char* kScriptChars = R"(
863void throwException() {
864 throw new Exception('myException');
865}
866
867@pragma("vm:external-name", "Test_nativeFunc")
868external void nativeFunc(closure);
869
870void Func2() {
871 nativeFunc(() => throwException());
872}
873)";
874 Dart_Handle lib =
877
878 // Use Dart_PropagateError to propagate the error.
879 use_throw_exception = false;
880 use_set_return = false;
881
882 result = Dart_Invoke(lib, NewString("Func2"), 0, nullptr);
885 EXPECT_SUBSTRING("myException", Dart_GetError(result));
886
887 // Use Dart_SetReturnValue to propagate the error.
888 use_throw_exception = false;
889 use_set_return = true;
890
891 result = Dart_Invoke(lib, NewString("Func2"), 0, nullptr);
894 EXPECT_SUBSTRING("myException", Dart_GetError(result));
895
896 // Use Dart_ThrowException to propagate the error.
897 use_throw_exception = true;
898 use_set_return = false;
899
900 result = Dart_Invoke(lib, NewString("Func2"), 0, nullptr);
903 EXPECT_SUBSTRING("myException", Dart_GetError(result));
904}
905
906TEST_CASE(DartAPI_Error) {
908 {
909 TransitionNativeToVM transition(thread);
910 error = Api::NewError("An %s", "error");
911 }
913 EXPECT_STREQ("An error", Dart_GetError(error));
914}
915
916TEST_CASE(DartAPI_Null) {
917 Dart_Handle null = Dart_Null();
918 EXPECT_VALID(null);
919 EXPECT(Dart_IsNull(null));
920
921 Dart_Handle str = NewString("test");
922 EXPECT_VALID(str);
923 EXPECT(!Dart_IsNull(str));
924}
925
926TEST_CASE(DartAPI_EmptyString) {
931 intptr_t length = -1;
933 EXPECT_EQ(0, length);
934}
935
936TEST_CASE(DartAPI_TypeDynamic) {
940
942 EXPECT_VALID(str);
943 const char* cstr = nullptr;
945 EXPECT_STREQ("dynamic", cstr);
946}
947
948TEST_CASE(DartAPI_TypeVoid) {
952
954 EXPECT_VALID(str);
955 const char* cstr = nullptr;
957 EXPECT_STREQ("void", cstr);
958}
959
960TEST_CASE(DartAPI_TypeNever) {
964
966 EXPECT_VALID(str);
967 const char* cstr = nullptr;
969 EXPECT_STREQ("Never", cstr);
970}
971
972TEST_CASE(DartAPI_IdentityEquals) {
974 Dart_Handle five_again = Dart_NewInteger(5);
975 Dart_Handle mint = Dart_NewInteger(0xFFFFFFFF);
976 Dart_Handle mint_again = Dart_NewInteger(0xFFFFFFFF);
977 Dart_Handle abc = NewString("abc");
978 Dart_Handle abc_again = NewString("abc");
979 Dart_Handle xyz = NewString("xyz");
980 Dart_Handle dart_core = NewString("dart:core");
981 Dart_Handle dart_mirrors = NewString("dart:mirrors");
982
983 // Same objects.
984 EXPECT(Dart_IdentityEquals(five, five));
985 EXPECT(Dart_IdentityEquals(mint, mint));
986 EXPECT(Dart_IdentityEquals(abc, abc));
987 EXPECT(Dart_IdentityEquals(xyz, xyz));
988
989 // Equal objects with special spec rules.
990 EXPECT(Dart_IdentityEquals(five, five_again));
991 EXPECT(Dart_IdentityEquals(mint, mint_again));
992
993 // Equal objects without special spec rules.
994 EXPECT(!Dart_IdentityEquals(abc, abc_again));
995
996 // Different objects.
997 EXPECT(!Dart_IdentityEquals(five, mint));
998 EXPECT(!Dart_IdentityEquals(abc, xyz));
999
1000 // Case where identical() is not the same as pointer equality.
1001 Dart_Handle nan1 = Dart_NewDouble(NAN);
1002 Dart_Handle nan2 = Dart_NewDouble(NAN);
1003 EXPECT(Dart_IdentityEquals(nan1, nan2));
1004
1005 // Non-instance objects.
1006 {
1007 CHECK_API_SCOPE(thread);
1008 Dart_Handle lib1 = Dart_LookupLibrary(dart_core);
1009 Dart_Handle lib2 = Dart_LookupLibrary(dart_mirrors);
1010
1011 EXPECT(Dart_IdentityEquals(lib1, lib1));
1012 EXPECT(Dart_IdentityEquals(lib2, lib2));
1013 EXPECT(!Dart_IdentityEquals(lib1, lib2));
1014
1015 // Mix instance and non-instance.
1016 EXPECT(!Dart_IdentityEquals(lib1, nan1));
1017 EXPECT(!Dart_IdentityEquals(nan1, lib1));
1018 }
1019}
1020
1021TEST_CASE(DartAPI_ObjectEquals) {
1022 bool equal = false;
1023 Dart_Handle five = NewString("5");
1024 Dart_Handle five_again = NewString("5");
1025 Dart_Handle seven = NewString("7");
1026
1027 // Same objects.
1028 EXPECT_VALID(Dart_ObjectEquals(five, five, &equal));
1029 EXPECT(equal);
1030
1031 // Equal objects.
1032 EXPECT_VALID(Dart_ObjectEquals(five, five_again, &equal));
1033 EXPECT(equal);
1034
1035 // Different objects.
1036 EXPECT_VALID(Dart_ObjectEquals(five, seven, &equal));
1037 EXPECT(!equal);
1038
1039 // Case where identity is not equality.
1040 Dart_Handle nan = Dart_NewDouble(NAN);
1042 EXPECT(!equal);
1043}
1044
1045TEST_CASE(DartAPI_InstanceValues) {
1048
1049 // By convention, our Is*() functions exclude null.
1051}
1052
1053TEST_CASE(DartAPI_InstanceGetType) {
1054 Zone* zone = thread->zone();
1055 // Get the handle from a valid instance handle.
1059 {
1060 TransitionNativeToVM transition(thread);
1061 const Type& null_type_obj = Api::UnwrapTypeHandle(zone, type);
1062 EXPECT(null_type_obj.ptr() == Type::NullType());
1063 }
1064
1069 {
1070 TransitionNativeToVM transition(thread);
1071 const Type& bool_type_obj = Api::UnwrapTypeHandle(zone, type);
1072 EXPECT(bool_type_obj.ptr() == Type::BoolType());
1073 }
1074
1075 // Errors propagate.
1076 Dart_Handle error = Dart_NewApiError("MyError");
1078 EXPECT_ERROR(error_type, "MyError");
1079
1080 // Get the handle from a non-instance handle.
1081 Dart_Handle dart_core = NewString("dart:core");
1082 Dart_Handle obj = Dart_LookupLibrary(dart_core);
1083 Dart_Handle type_type = Dart_InstanceGetType(obj);
1084 EXPECT_ERROR(type_type,
1085 "Dart_InstanceGetType expects argument 'instance' to be of "
1086 "type Instance.");
1087}
1088
1089TEST_CASE(DartAPI_FunctionName) {
1090 const char* kScriptChars = "int getInt() { return 1; }\n";
1091 // Create a test library and Load up a test script in it.
1092 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1093 EXPECT_VALID(lib);
1094
1095 Dart_Handle closure = Dart_GetField(lib, NewString("getInt"));
1097 if (Dart_IsClosure(closure)) {
1100 }
1101
1104 const char* result_str = "";
1105 Dart_StringToCString(name, &result_str);
1106 EXPECT_STREQ(result_str, "getInt");
1107}
1108
1109TEST_CASE(DartAPI_FunctionOwner) {
1110 const char* kScriptChars = "int getInt() { return 1; }\n";
1111 // Create a test library and Load up a test script in it.
1112 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1113 EXPECT_VALID(lib);
1114
1115 Dart_Handle closure = Dart_GetField(lib, NewString("getInt"));
1117 if (Dart_IsClosure(closure)) {
1120 }
1121
1122 const char* url = "";
1124 EXPECT_VALID(owner);
1125 Dart_Handle owner_url = Dart_LibraryUrl(owner);
1126 EXPECT_VALID(owner_url);
1127 Dart_StringToCString(owner_url, &url);
1128
1129 const char* lib_url = "";
1130 Dart_Handle library_url = Dart_LibraryUrl(lib);
1131 EXPECT_VALID(library_url);
1132 Dart_StringToCString(library_url, &lib_url);
1133
1134 EXPECT_STREQ(url, lib_url);
1135}
1136
1137TEST_CASE(DartAPI_IsTearOff) {
1138 const char* kScriptChars =
1139 "int getInt() { return 1; }\n"
1140 "getTearOff() => getInt;\n"
1141 "Function foo = () { print('baz'); };\n"
1142 "class Baz {\n"
1143 " static int foo() => 42;\n"
1144 " getTearOff() => bar;\n"
1145 " int bar() => 24;\n"
1146 "}\n"
1147 "Baz getBaz() => Baz();\n";
1148 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1149 EXPECT_VALID(lib);
1150
1151 // Check tear-off of top-level static method.
1152 Dart_Handle get_tear_off = Dart_GetField(lib, NewString("getTearOff"));
1153 EXPECT_VALID(get_tear_off);
1154 EXPECT(Dart_IsTearOff(get_tear_off));
1155 Dart_Handle tear_off = Dart_InvokeClosure(get_tear_off, 0, nullptr);
1156 EXPECT_VALID(tear_off);
1157 EXPECT(Dart_IsTearOff(tear_off));
1158
1159 // Check anonymous closures are not considered tear-offs.
1160 Dart_Handle anonymous_closure = Dart_GetField(lib, NewString("foo"));
1161 EXPECT_VALID(anonymous_closure);
1162 EXPECT(!Dart_IsTearOff(anonymous_closure));
1163
1164 Dart_Handle baz_cls = Dart_GetClass(lib, NewString("Baz"));
1165 EXPECT_VALID(baz_cls);
1166
1167 // Check tear-off for a static method in a class.
1169 Dart_GetStaticMethodClosure(lib, baz_cls, NewString("foo"));
1172
1173 // Flutter will use Dart_IsTearOff in conjunction with Dart_ClosureFunction
1174 // and Dart_FunctionIsStatic to prevent anonymous closures from being used to
1175 // generate callback handles. We'll test that case here, just to be sure.
1178 bool is_static = false;
1181 EXPECT(is_static);
1182
1183 // Check tear-off for an instance method in a class.
1184 Dart_Handle instance = Dart_Invoke(lib, NewString("getBaz"), 0, nullptr);
1186 closure = Dart_Invoke(instance, NewString("getTearOff"), 0, nullptr);
1189}
1190
1191TEST_CASE(DartAPI_FunctionIsStatic) {
1192 const char* kScriptChars =
1193 "int getInt() { return 1; }\n"
1194 "class Foo { String getString() => 'foobar'; }\n";
1195 // Create a test library and Load up a test script in it.
1196 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1197 EXPECT_VALID(lib);
1198
1199 Dart_Handle closure = Dart_GetField(lib, NewString("getInt"));
1201 if (Dart_IsClosure(closure)) {
1204 }
1205
1206 bool is_static = false;
1209 EXPECT(is_static);
1210
1211 Dart_Handle klass =
1212 Dart_GetNonNullableType(lib, NewString("Foo"), 0, nullptr);
1213 EXPECT_VALID(klass);
1214
1216
1217 closure = Dart_GetField(instance, NewString("getString"));
1219 if (Dart_IsClosure(closure)) {
1222 }
1223
1224 result = Dart_FunctionIsStatic(closure, &is_static);
1226 EXPECT(!is_static);
1227}
1228
1229TEST_CASE(DartAPI_ClosureFunction) {
1230 const char* kScriptChars = "int getInt() { return 1; }\n";
1231 // Create a test library and Load up a test script in it.
1232 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1233 EXPECT_VALID(lib);
1234
1235 Dart_Handle closure = Dart_GetField(lib, NewString("getInt"));
1238 Dart_Handle closure_str = Dart_ToString(closure);
1239 const char* result = "";
1240 Dart_StringToCString(closure_str, &result);
1241 EXPECT(strstr(result, "getInt") != nullptr);
1242
1247 Dart_StringToCString(func_str, &result);
1248 EXPECT(strstr(result, "getInt"));
1249}
1250
1251TEST_CASE(DartAPI_GetStaticMethodClosure) {
1252 const char* kScriptChars =
1253 "class Foo {\n"
1254 " static int getInt() {\n"
1255 " return 1;\n"
1256 " }\n"
1257 " double getDouble() {\n"
1258 " return 1.0;\n"
1259 " }\n"
1260 "}\n";
1261 // Create a test library and Load up a test script in it.
1262 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1263 EXPECT_VALID(lib);
1264 Dart_Handle foo_cls = Dart_GetClass(lib, NewString("Foo"));
1265 EXPECT_VALID(foo_cls);
1266
1268 Dart_GetStaticMethodClosure(lib, foo_cls, NewString("getInt"));
1271 Dart_Handle closure_str = Dart_ToString(closure);
1272 const char* result = "";
1273 Dart_StringToCString(closure_str, &result);
1274 EXPECT_SUBSTRING("getInt", result);
1275
1280 Dart_StringToCString(func_str, &result);
1281 EXPECT_SUBSTRING("getInt", result);
1282
1284 EXPECT_VALID(cls);
1285 EXPECT(Dart_IsInstance(cls));
1286 Dart_Handle cls_str = Dart_ClassName(cls);
1287 Dart_StringToCString(cls_str, &result);
1288 EXPECT_SUBSTRING("Foo", result);
1289
1291 "Dart_ClassName expects argument 'cls_type' to be non-null.");
1293 Dart_GetStaticMethodClosure(Dart_Null(), foo_cls, NewString("getInt")),
1294 "Dart_GetStaticMethodClosure expects argument 'library' to be non-null.");
1297 "Dart_GetStaticMethodClosure expects argument 'cls_type' to be "
1298 "non-null.");
1300 "Dart_GetStaticMethodClosure expects argument 'function_name' "
1301 "to be non-null.");
1302}
1303
1304TEST_CASE(DartAPI_ClassLibrary) {
1305 Dart_Handle lib = Dart_LookupLibrary(NewString("dart:core"));
1306 EXPECT_VALID(lib);
1307 Dart_Handle type = Dart_GetNonNullableType(lib, NewString("int"), 0, nullptr);
1312 const char* str = nullptr;
1313 Dart_StringToCString(lib_url, &str);
1314 EXPECT_STREQ("dart:core", str);
1315}
1316
1317TEST_CASE(DartAPI_BooleanValues) {
1318 Dart_Handle str = NewString("test");
1319 EXPECT(!Dart_IsBoolean(str));
1320
1321 bool value = false;
1324
1325 Dart_Handle val1 = Dart_NewBoolean(true);
1326 EXPECT(Dart_IsBoolean(val1));
1327
1328 result = Dart_BooleanValue(val1, &value);
1330 EXPECT(value);
1331
1332 Dart_Handle val2 = Dart_NewBoolean(false);
1333 EXPECT(Dart_IsBoolean(val2));
1334
1335 result = Dart_BooleanValue(val2, &value);
1337 EXPECT(!value);
1338}
1339
1340TEST_CASE(DartAPI_BooleanConstants) {
1341 Dart_Handle true_handle = Dart_True();
1342 EXPECT_VALID(true_handle);
1343 EXPECT(Dart_IsBoolean(true_handle));
1344
1345 bool value = false;
1346 Dart_Handle result = Dart_BooleanValue(true_handle, &value);
1348 EXPECT(value);
1349
1350 Dart_Handle false_handle = Dart_False();
1351 EXPECT_VALID(false_handle);
1352 EXPECT(Dart_IsBoolean(false_handle));
1353
1354 result = Dart_BooleanValue(false_handle, &value);
1356 EXPECT(!value);
1357}
1358
1359TEST_CASE(DartAPI_DoubleValues) {
1360 const double kDoubleVal1 = 201.29;
1361 const double kDoubleVal2 = 101.19;
1362 Dart_Handle val1 = Dart_NewDouble(kDoubleVal1);
1363 EXPECT(Dart_IsDouble(val1));
1364 Dart_Handle val2 = Dart_NewDouble(kDoubleVal2);
1365 EXPECT(Dart_IsDouble(val2));
1366 double out1, out2;
1367 Dart_Handle result = Dart_DoubleValue(val1, &out1);
1369 EXPECT_EQ(kDoubleVal1, out1);
1370 result = Dart_DoubleValue(val2, &out2);
1372 EXPECT_EQ(kDoubleVal2, out2);
1373}
1374
1375TEST_CASE(DartAPI_NumberValues) {
1376 // TODO(antonm): add various kinds of ints (smi, mint, bigint).
1377 const char* kScriptChars =
1378 "int getInt() { return 1; }\n"
1379 "double getDouble() { return 1.0; }\n"
1380 "bool getBool() { return false; }\n"
1381 "getNull() { return null; }\n";
1383 // Create a test library and Load up a test script in it.
1384 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1385
1386 // Check int case.
1387 result = Dart_Invoke(lib, NewString("getInt"), 0, nullptr);
1390
1391 // Check double case.
1392 result = Dart_Invoke(lib, NewString("getDouble"), 0, nullptr);
1395
1396 // Check bool case.
1397 result = Dart_Invoke(lib, NewString("getBool"), 0, nullptr);
1400
1401 // Check null case.
1402 result = Dart_Invoke(lib, NewString("getNull"), 0, nullptr);
1405}
1406
1407TEST_CASE(DartAPI_IntegerValues) {
1408 const int64_t kIntegerVal1 = 100;
1409 const int64_t kIntegerVal2 = 0xffffffff;
1410 const char* kIntegerVal3 = "0x123456789123456789123456789";
1411 const uint64_t kIntegerVal4 = 0xffffffffffffffff;
1412 const int64_t kIntegerVal5 = -0x7fffffffffffffff;
1413
1414 Dart_Handle val1 = Dart_NewInteger(kIntegerVal1);
1415 EXPECT(Dart_IsInteger(val1));
1416 bool fits = false;
1419 EXPECT(fits);
1420
1421 int64_t out = 0;
1422 result = Dart_IntegerToInt64(val1, &out);
1424 EXPECT_EQ(kIntegerVal1, out);
1425
1426 Dart_Handle val2 = Dart_NewInteger(kIntegerVal2);
1427 EXPECT(Dart_IsInteger(val2));
1428 result = Dart_IntegerFitsIntoInt64(val2, &fits);
1430 EXPECT(fits);
1431
1432 result = Dart_IntegerToInt64(val2, &out);
1434 EXPECT_EQ(kIntegerVal2, out);
1435
1436 Dart_Handle val3 = Dart_NewIntegerFromHexCString(kIntegerVal3);
1437 EXPECT(Dart_IsApiError(val3));
1438
1439 Dart_Handle val4 = Dart_NewIntegerFromUint64(kIntegerVal4);
1440 EXPECT(Dart_IsApiError(val4));
1441
1442 Dart_Handle val5 = Dart_NewInteger(-1);
1443 EXPECT_VALID(val5);
1444 uint64_t out5 = 0;
1445 result = Dart_IntegerToUint64(val5, &out5);
1447
1448 Dart_Handle val6 = Dart_NewInteger(kIntegerVal5);
1449 EXPECT_VALID(val6);
1450 uint64_t out6 = 0;
1451 result = Dart_IntegerToUint64(val6, &out6);
1453}
1454
1455TEST_CASE(DartAPI_IntegerToHexCString) {
1456 const struct {
1457 int64_t i;
1458 const char* s;
1459 } kIntTestCases[] = {
1460 {0, "0x0"},
1461 {1, "0x1"},
1462 {-1, "-0x1"},
1463 {0x123, "0x123"},
1464 {-0xABCDEF, "-0xABCDEF"},
1465 {DART_INT64_C(-0x7FFFFFFFFFFFFFFF), "-0x7FFFFFFFFFFFFFFF"},
1466 {kMaxInt64, "0x7FFFFFFFFFFFFFFF"},
1467 {kMinInt64, "-0x8000000000000000"},
1468 };
1469
1470 const size_t kNumberOfIntTestCases =
1471 sizeof(kIntTestCases) / sizeof(kIntTestCases[0]);
1472
1473 for (size_t i = 0; i < kNumberOfIntTestCases; ++i) {
1474 Dart_Handle val = Dart_NewInteger(kIntTestCases[i].i);
1475 EXPECT_VALID(val);
1476 const char* chars = nullptr;
1479 EXPECT_STREQ(kIntTestCases[i].s, chars);
1480 }
1481}
1482
1483TEST_CASE(DartAPI_IntegerFitsIntoInt64) {
1486 bool fits = false;
1489 EXPECT(fits);
1490
1491 Dart_Handle above_max = Dart_NewIntegerFromHexCString("0x10000000000000000");
1492 EXPECT(Dart_IsApiError(above_max));
1493
1496 fits = false;
1499 EXPECT(fits);
1500
1501 Dart_Handle below_min = Dart_NewIntegerFromHexCString("-0x10000000000000001");
1502 EXPECT(Dart_IsApiError(below_min));
1503}
1504
1505TEST_CASE(DartAPI_IntegerFitsIntoUint64) {
1508
1509 Dart_Handle above_max = Dart_NewIntegerFromHexCString("0x10000000000000000");
1510 EXPECT(Dart_IsApiError(above_max));
1511
1514 bool fits = false;
1517 EXPECT(fits);
1518
1520 EXPECT(Dart_IsInteger(below_min));
1521 fits = true;
1522 result = Dart_IntegerFitsIntoUint64(below_min, &fits);
1524 EXPECT(!fits);
1525}
1526
1527TEST_CASE(DartAPI_ArrayValues) {
1529 const int kArrayLength = 10;
1530 Dart_Handle str = NewString("test");
1531 EXPECT(!Dart_IsList(str));
1532 Dart_Handle val = Dart_NewList(kArrayLength);
1533 EXPECT(Dart_IsList(val));
1534 intptr_t len = 0;
1537 EXPECT_EQ(kArrayLength, len);
1538
1539 // Check invalid array access.
1540 result = Dart_ListSetAt(val, (kArrayLength + 10), Dart_NewInteger(10));
1542 result = Dart_ListSetAt(val, -10, Dart_NewInteger(10));
1544 result = Dart_ListGetAt(val, (kArrayLength + 10));
1546 result = Dart_ListGetAt(val, -10);
1548
1549 for (int i = 0; i < kArrayLength; i++) {
1552 }
1553 for (int i = 0; i < kArrayLength; i++) {
1554 result = Dart_ListGetAt(val, i);
1556 int64_t value;
1559 EXPECT_EQ(i, value);
1560 }
1561}
1562
1563TEST_CASE(DartAPI_IsString) {
1564 uint8_t latin1[] = {'o', 'n', 'e', 0xC2, 0xA2};
1565
1566 Dart_Handle latin1str = Dart_NewStringFromUTF8(latin1, ARRAY_SIZE(latin1));
1567 EXPECT_VALID(latin1str);
1568 EXPECT(Dart_IsString(latin1str));
1569 EXPECT(Dart_IsStringLatin1(latin1str));
1570 intptr_t len = -1;
1571 EXPECT_VALID(Dart_StringLength(latin1str, &len));
1572 EXPECT_EQ(4, len);
1573 intptr_t char_size;
1574 intptr_t str_len;
1575 void* peer;
1577 Dart_StringGetProperties(latin1str, &char_size, &str_len, &peer));
1578 EXPECT_EQ(1, char_size);
1579 EXPECT_EQ(4, str_len);
1580 EXPECT(!peer);
1581
1582 uint8_t data8[] = {'o', 'n', 'e', 0x7F};
1583
1584 Dart_Handle str8 = Dart_NewStringFromUTF8(data8, ARRAY_SIZE(data8));
1585 EXPECT_VALID(str8);
1586 EXPECT(Dart_IsString(str8));
1588
1589 uint8_t latin1_array[] = {0, 0, 0, 0, 0};
1590 len = 5;
1591 Dart_Handle result = Dart_StringToLatin1(str8, latin1_array, &len);
1593 EXPECT_EQ(4, len);
1594 for (intptr_t i = 0; i < len; i++) {
1595 EXPECT_EQ(data8[i], latin1_array[i]);
1596 }
1597
1598 uint16_t data16[] = {'t', 'w', 'o', 0xFFFF};
1599
1600 Dart_Handle str16 = Dart_NewStringFromUTF16(data16, ARRAY_SIZE(data16));
1601 EXPECT_VALID(str16);
1602 EXPECT(Dart_IsString(str16));
1603 EXPECT(!Dart_IsStringLatin1(str16));
1604 EXPECT_VALID(Dart_StringGetProperties(str16, &char_size, &str_len, &peer));
1605 EXPECT_EQ(2, char_size);
1606 EXPECT_EQ(4, str_len);
1607 EXPECT(!peer);
1608
1609 int32_t data32[] = {'f', 'o', 'u', 'r', 0x10FFFF};
1610
1611 Dart_Handle str32 = Dart_NewStringFromUTF32(data32, ARRAY_SIZE(data32));
1612 EXPECT_VALID(str32);
1613 EXPECT(Dart_IsString(str32));
1614}
1615
1616TEST_CASE(DartAPI_NewString) {
1617 const char* ascii = "string";
1618 Dart_Handle ascii_str = NewString(ascii);
1619 EXPECT_VALID(ascii_str);
1620 EXPECT(Dart_IsString(ascii_str));
1621
1622 const char* null = nullptr;
1623 Dart_Handle null_str = NewString(null);
1624 EXPECT(Dart_IsError(null_str));
1625
1626 uint8_t data[] = {0xE4, 0xBA, 0x8c}; // U+4E8C.
1628 EXPECT_VALID(utf8_str);
1629 EXPECT(Dart_IsString(utf8_str));
1630
1631 uint8_t invalid[] = {0xE4, 0xBA}; // underflow.
1632 Dart_Handle invalid_str =
1634 EXPECT(Dart_IsError(invalid_str));
1635}
1636
1637TEST_CASE(DartAPI_MalformedStringToUTF8) {
1638 // 1D11E = treble clef
1639 // [0] should be high surrogate D834
1640 // [1] should be low surrogate DD1E
1641 // Strings are allowed to have individual or out of order surrogates, even
1642 // if that doesn't make sense as renderable characters.
1643 const char* kScriptChars =
1644 "String lowSurrogate() {"
1645 " return '\\u{1D11E}'[1];"
1646 "}"
1647 "String highSurrogate() {"
1648 " return '\\u{1D11E}'[0];"
1649 "}"
1650 "String reversed() => lowSurrogate() + highSurrogate();";
1651
1652 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1653 Dart_Handle str1 = Dart_Invoke(lib, NewString("lowSurrogate"), 0, nullptr);
1654 EXPECT_VALID(str1);
1655
1656 uint8_t* utf8_encoded = nullptr;
1657 intptr_t utf8_length = 0;
1658 Dart_Handle result = Dart_StringToUTF8(str1, &utf8_encoded, &utf8_length);
1660 EXPECT_EQ(3, utf8_length);
1661 // Unpaired surrogate is encoded as replacement character.
1662 EXPECT_EQ(239, static_cast<intptr_t>(utf8_encoded[0]));
1663 EXPECT_EQ(191, static_cast<intptr_t>(utf8_encoded[1]));
1664 EXPECT_EQ(189, static_cast<intptr_t>(utf8_encoded[2]));
1665
1666 Dart_Handle str2 = Dart_NewStringFromUTF8(utf8_encoded, utf8_length);
1667 EXPECT_VALID(str2); // Replacement character, but still valid
1668
1669 Dart_Handle reversed = Dart_Invoke(lib, NewString("reversed"), 0, nullptr);
1670 EXPECT_VALID(reversed); // This is also allowed.
1671 uint8_t* utf8_encoded_reversed = nullptr;
1672 intptr_t utf8_length_reversed = 0;
1673 result = Dart_StringToUTF8(reversed, &utf8_encoded_reversed,
1674 &utf8_length_reversed);
1676 EXPECT_EQ(6, utf8_length_reversed);
1677 // Two unpaired surrogates are encoded as two replacement characters.
1678 uint8_t expected[6] = {239, 191, 189, 239, 191, 189};
1679 for (int i = 0; i < 6; i++) {
1680 EXPECT_EQ(expected[i], utf8_encoded_reversed[i]);
1681 }
1682}
1683
1684TEST_CASE(DartAPI_CopyUTF8EncodingOfString) {
1685 const char* kScriptChars =
1686 "String lowSurrogate() {"
1687 " return '\\u{1D11E}'[1];"
1688 "}";
1689
1690 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1691 Dart_Handle str1 = Dart_Invoke(lib, NewString("lowSurrogate"), 0, nullptr);
1692 EXPECT_VALID(str1);
1693
1694 uint8_t* utf8_encoded = nullptr;
1695 intptr_t utf8_length = 0;
1696 Dart_Handle result = Dart_StringToUTF8(str1, &utf8_encoded, &utf8_length);
1698 EXPECT_EQ(3, utf8_length);
1699
1700 intptr_t utf8_copy_length = 0;
1701 result = Dart_StringUTF8Length(str1, &utf8_copy_length);
1702 uint8_t* utf8_encoded_copy = Dart_ScopeAllocate(utf8_copy_length);
1703 result =
1704 Dart_CopyUTF8EncodingOfString(str1, utf8_encoded_copy, utf8_copy_length);
1706 EXPECT_EQ(0, memcmp(utf8_encoded, utf8_encoded_copy, utf8_length));
1707}
1708
1709TEST_CASE(DartAPI_ExternalTypedDataPretenure) {
1710 {
1712 const int kBigLength = 16 * MB / 8;
1713 int64_t* big_data = new int64_t[kBigLength]();
1714 Dart_Handle big =
1715 Dart_NewExternalTypedData(Dart_TypedData_kInt64, big_data, kBigLength);
1716 EXPECT_VALID(big);
1717 const int kSmallLength = 16 * KB / 8;
1718 int64_t* small_data = new int64_t[kSmallLength]();
1720 small_data, kSmallLength);
1721 EXPECT_VALID(small);
1722 {
1723 CHECK_API_SCOPE(thread);
1724 TransitionNativeToVM transition(thread);
1725 HANDLESCOPE(thread);
1727 handle ^= Api::UnwrapHandle(big);
1728 EXPECT(handle.IsOld());
1729 handle ^= Api::UnwrapHandle(small);
1730 EXPECT(handle.IsNew());
1731 }
1733 delete[] big_data;
1734 delete[] small_data;
1735 }
1736}
1737
1738TEST_CASE(DartAPI_ListAccess) {
1739 const char* kScriptChars =
1740 "List testMain() {"
1741 " List a = List.empty(growable: true);"
1742 " a.add(10);"
1743 " a.add(20);"
1744 " a.add(30);"
1745 " return a;"
1746 "}"
1747 ""
1748 "List immutable() {"
1749 " return const [0, 1, 2];"
1750 "}";
1752
1753 // Create a test library and Load up a test script in it.
1754 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1755
1756 // Invoke a function which returns an object of type List.
1757 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
1759
1760 // First ensure that the returned object is an array.
1761 Dart_Handle list_access_test_obj = result;
1762
1763 EXPECT(Dart_IsList(list_access_test_obj));
1764
1765 // Get length of array object.
1766 intptr_t len = 0;
1767 result = Dart_ListLength(list_access_test_obj, &len);
1769 EXPECT_EQ(3, len);
1770
1771 // Access elements in the array.
1772 int64_t value;
1773
1774 result = Dart_ListGetAt(list_access_test_obj, 0);
1778 EXPECT_EQ(10, value);
1779
1780 result = Dart_ListGetAt(list_access_test_obj, 1);
1784 EXPECT_EQ(20, value);
1785
1786 result = Dart_ListGetAt(list_access_test_obj, 2);
1790 EXPECT_EQ(30, value);
1791
1792 // Set some elements in the array.
1793 result = Dart_ListSetAt(list_access_test_obj, 0, Dart_NewInteger(0));
1795 result = Dart_ListSetAt(list_access_test_obj, 1, Dart_NewInteger(1));
1797 result = Dart_ListSetAt(list_access_test_obj, 2, Dart_NewInteger(2));
1799
1800 // Get length of array object.
1801 result = Dart_ListLength(list_access_test_obj, &len);
1803 EXPECT_EQ(3, len);
1804
1805 // Now try and access these elements in the array.
1806 result = Dart_ListGetAt(list_access_test_obj, 0);
1810 EXPECT_EQ(0, value);
1811
1812 result = Dart_ListGetAt(list_access_test_obj, 1);
1816 EXPECT_EQ(1, value);
1817
1818 result = Dart_ListGetAt(list_access_test_obj, 2);
1822 EXPECT_EQ(2, value);
1823
1824 uint8_t native_array[3];
1825 result = Dart_ListGetAsBytes(list_access_test_obj, 0, native_array, 3);
1827 EXPECT_EQ(0, native_array[0]);
1828 EXPECT_EQ(1, native_array[1]);
1829 EXPECT_EQ(2, native_array[2]);
1830
1831 native_array[0] = 10;
1832 native_array[1] = 20;
1833 native_array[2] = 30;
1834 result = Dart_ListSetAsBytes(list_access_test_obj, 0, native_array, 3);
1836 result = Dart_ListGetAsBytes(list_access_test_obj, 0, native_array, 3);
1838 EXPECT_EQ(10, native_array[0]);
1839 EXPECT_EQ(20, native_array[1]);
1840 EXPECT_EQ(30, native_array[2]);
1841 result = Dart_ListGetAt(list_access_test_obj, 2);
1845 EXPECT_EQ(30, value);
1846
1847 // Check if we get an exception when accessing beyond limit.
1848 result = Dart_ListGetAt(list_access_test_obj, 4);
1850
1851 // Check if we can get a range of values.
1852 result = Dart_ListGetRange(list_access_test_obj, 8, 4, nullptr);
1854 const int kRangeOffset = 1;
1855 const int kRangeLength = 2;
1856 Dart_Handle values[kRangeLength];
1857
1858 result = Dart_ListGetRange(list_access_test_obj, 8, 4, values);
1860
1861 result = Dart_ListGetRange(list_access_test_obj, kRangeOffset, kRangeLength,
1862 values);
1864
1867 EXPECT_EQ(20, value);
1868
1871 EXPECT_EQ(30, value);
1872
1873 // Check that we get an exception (and not a fatal error) when
1874 // calling ListSetAt and ListSetAsBytes with an immutable list.
1875 list_access_test_obj = Dart_Invoke(lib, NewString("immutable"), 0, nullptr);
1876 EXPECT_VALID(list_access_test_obj);
1877 EXPECT(Dart_IsList(list_access_test_obj));
1878
1879 result = Dart_ListSetAsBytes(list_access_test_obj, 0, native_array, 3);
1882
1883 result = Dart_ListSetAt(list_access_test_obj, 0, Dart_NewInteger(42));
1886}
1887
1888TEST_CASE(DartAPI_MapAccess) {
1890 const char* kScriptChars =
1891 "Map testMain() {"
1892 " return {"
1893 " 'a' : 1,"
1894 " 'b' : null,"
1895 " };"
1896 "}";
1898
1899 // Create a test library and Load up a test script in it.
1900 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1901
1902 // Invoke a function which returns an object of type Map.
1903 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
1905
1906 // First ensure that the returned object is a map.
1908 Dart_Handle a = NewString("a");
1909 Dart_Handle b = NewString("b");
1910 Dart_Handle c = NewString("c");
1911
1913 EXPECT(!Dart_IsMap(a));
1914
1915 // Access values in the map.
1916 int64_t value;
1921 EXPECT_EQ(value, 1);
1922
1925
1926 result = Dart_MapGetAt(map, c);
1928
1930
1931 // Test for presence of keys.
1932 bool contains = false;
1938
1939 contains = false;
1945
1946 contains = true;
1951 EXPECT(!contains);
1952
1954
1955 // Enumerate keys. (Note literal maps guarantee key order.)
1957 EXPECT_VALID(keys);
1958
1959 intptr_t len = 0;
1960 bool equals;
1961 result = Dart_ListLength(keys, &len);
1963 EXPECT_EQ(2, len);
1964
1965 result = Dart_ListGetAt(keys, 0);
1967 equals = false;
1969 EXPECT(equals);
1970
1971 result = Dart_ListGetAt(keys, 1);
1973 equals = false;
1975 EXPECT(equals);
1976
1978}
1979
1980TEST_CASE(DartAPI_IsFuture) {
1981 const char* kScriptChars =
1982 "import 'dart:async';"
1983 "Future testMain() {"
1984 " return new Completer().future;"
1985 "}";
1987
1988 // Create a test library and Load up a test script in it.
1989 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1990
1991 // Invoke a function which returns an object of type Future.
1992 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
1995
1996 EXPECT(!Dart_IsFuture(lib)); // Non-instance.
1997 Dart_Handle anInteger = Dart_NewInteger(0);
1998 EXPECT(!Dart_IsFuture(anInteger));
1999 Dart_Handle aString = NewString("I am not a Future");
2000 EXPECT(!Dart_IsFuture(aString));
2001 Dart_Handle null = Dart_Null();
2002 EXPECT(!Dart_IsFuture(null));
2003}
2004
2005TEST_CASE(DartAPI_TypedDataViewListGetAsBytes) {
2006 const int kSize = 1000;
2007
2008 const char* kScriptChars =
2009 "import 'dart:typed_data';\n"
2010 "List testMain(int size) {\n"
2011 " var a = new Int8List(size);\n"
2012 " var view = new Int8List.view(a.buffer, 0, size);\n"
2013 " return view;\n"
2014 "}\n";
2015 // Create a test library and Load up a test script in it.
2016 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2017
2018 // Test with a typed data view object.
2019 Dart_Handle dart_args[1];
2020 dart_args[0] = Dart_NewInteger(kSize);
2021 Dart_Handle view_obj = Dart_Invoke(lib, NewString("testMain"), 1, dart_args);
2022 EXPECT_VALID(view_obj);
2023 for (intptr_t i = 0; i < kSize; ++i) {
2024 EXPECT_VALID(Dart_ListSetAt(view_obj, i, Dart_NewInteger(i & 0xff)));
2025 }
2026 uint8_t* data = new uint8_t[kSize];
2027 EXPECT_VALID(Dart_ListGetAsBytes(view_obj, 0, data, kSize));
2028 for (intptr_t i = 0; i < kSize; ++i) {
2029 EXPECT_EQ(i & 0xff, data[i]);
2030 }
2031
2032 Dart_Handle result = Dart_ListGetAsBytes(view_obj, 0, data, kSize + 1);
2034 delete[] data;
2035}
2036
2037TEST_CASE(DartAPI_TypedDataViewListIsTypedData) {
2038 const int kSize = 1000;
2039
2040 const char* kScriptChars =
2041 "import 'dart:typed_data';\n"
2042 "List testMain(int size) {\n"
2043 " var a = new Int8List(size);\n"
2044 " var view = new Int8List.view(a.buffer, 0, size);\n"
2045 " return view;\n"
2046 "}\n";
2047 // Create a test library and Load up a test script in it.
2048 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2049
2050 // Create a typed data view object.
2051 Dart_Handle dart_args[1];
2052 dart_args[0] = Dart_NewInteger(kSize);
2053 Dart_Handle view_obj = Dart_Invoke(lib, NewString("testMain"), 1, dart_args);
2054 EXPECT_VALID(view_obj);
2055 // Test that the API considers it a TypedData object.
2056 EXPECT(Dart_IsTypedData(view_obj));
2057 EXPECT_EQ(Dart_TypedData_kInt8, Dart_GetTypeOfTypedData(view_obj));
2058}
2059
2060TEST_CASE(DartAPI_UnmodifiableTypedDataViewListIsTypedData) {
2061 const int kSize = 1000;
2062
2063 const char* kScriptChars =
2064 "import 'dart:typed_data';\n"
2065 "List testMain(int size) {\n"
2066 " var a = new Int8List(size);\n"
2067 " var view = a.asUnmodifiableView();\n"
2068 " return view;\n"
2069 "}\n";
2070 // Create a test library and Load up a test script in it.
2071 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2072
2073 // Create a typed data view object.
2074 Dart_Handle dart_args[1];
2075 dart_args[0] = Dart_NewInteger(kSize);
2076 Dart_Handle view_obj = Dart_Invoke(lib, NewString("testMain"), 1, dart_args);
2077 EXPECT_VALID(view_obj);
2078 // Test that the API considers it a TypedData object.
2079 EXPECT(Dart_IsTypedData(view_obj));
2080 EXPECT_EQ(Dart_TypedData_kInt8, Dart_GetTypeOfTypedData(view_obj));
2081}
2082
2083TEST_CASE(DartAPI_TypedDataAccess) {
2085 EXPECT_EQ(Dart_TypedData_kInvalid,
2088 EXPECT_VALID(byte_array1);
2089 EXPECT_EQ(Dart_TypedData_kUint8, Dart_GetTypeOfTypedData(byte_array1));
2090 EXPECT_EQ(Dart_TypedData_kInvalid,
2091 Dart_GetTypeOfExternalTypedData(byte_array1));
2092 EXPECT(Dart_IsList(byte_array1));
2094 EXPECT(Dart_IsTypedData(byte_array1));
2095 EXPECT(!Dart_IsByteBuffer(byte_array1));
2096
2097 intptr_t length = 0;
2098 Dart_Handle result = Dart_ListLength(byte_array1, &length);
2100 EXPECT_EQ(10, length);
2101
2102 result = Dart_ListSetAt(byte_array1, -1, Dart_NewInteger(1));
2104
2105 result = Dart_ListSetAt(byte_array1, 10, Dart_NewInteger(1));
2107
2108 // Set through the List API.
2109 for (intptr_t i = 0; i < 10; ++i) {
2110 EXPECT_VALID(Dart_ListSetAt(byte_array1, i, Dart_NewInteger(i + 1)));
2111 }
2112 for (intptr_t i = 0; i < 10; ++i) {
2113 // Get through the List API.
2114 Dart_Handle integer_obj = Dart_ListGetAt(byte_array1, i);
2115 EXPECT_VALID(integer_obj);
2116 int64_t int64_t_value = -1;
2117 EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
2118 EXPECT_EQ(i + 1, int64_t_value);
2119 }
2120
2122 bool is_equal = false;
2123 Dart_ObjectEquals(byte_array1, byte_array2, &is_equal);
2124 EXPECT(!is_equal);
2125
2126 // Set through the List API.
2127 for (intptr_t i = 0; i < 10; ++i) {
2128 result = Dart_ListSetAt(byte_array1, i, Dart_NewInteger(i + 2));
2130 result = Dart_ListSetAt(byte_array2, i, Dart_NewInteger(i + 2));
2132 }
2133 for (intptr_t i = 0; i < 10; ++i) {
2134 // Get through the List API.
2135 Dart_Handle e1 = Dart_ListGetAt(byte_array1, i);
2136 Dart_Handle e2 = Dart_ListGetAt(byte_array2, i);
2137 is_equal = false;
2140 }
2141
2142 uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
2143 for (intptr_t i = 0; i < 10; ++i) {
2144 EXPECT_VALID(Dart_ListSetAt(byte_array1, i, Dart_NewInteger(10 - i)));
2145 }
2146 Dart_ListGetAsBytes(byte_array1, 0, data, 10);
2147 for (intptr_t i = 0; i < 10; ++i) {
2148 Dart_Handle integer_obj = Dart_ListGetAt(byte_array1, i);
2149 EXPECT_VALID(integer_obj);
2150 int64_t int64_t_value = -1;
2151 EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
2152 EXPECT_EQ(10 - i, int64_t_value);
2153 }
2154}
2155
2156TEST_CASE(DartAPI_ByteBufferAccess) {
2159 EXPECT_VALID(byte_array);
2160 // Set through the List API.
2161 for (intptr_t i = 0; i < 10; ++i) {
2162 EXPECT_VALID(Dart_ListSetAt(byte_array, i, Dart_NewInteger(i + 1)));
2163 }
2164 Dart_Handle byte_buffer = Dart_NewByteBuffer(byte_array);
2165 EXPECT_VALID(byte_buffer);
2166 EXPECT(Dart_IsByteBuffer(byte_buffer));
2167 EXPECT(!Dart_IsTypedData(byte_buffer));
2168
2169 Dart_Handle byte_buffer_data = Dart_GetDataFromByteBuffer(byte_buffer);
2170 EXPECT_VALID(byte_buffer_data);
2171 EXPECT(!Dart_IsByteBuffer(byte_buffer_data));
2172 EXPECT(Dart_IsTypedData(byte_buffer_data));
2173
2174 intptr_t length = 0;
2175 Dart_Handle result = Dart_ListLength(byte_buffer_data, &length);
2177 EXPECT_EQ(10, length);
2178
2179 for (intptr_t i = 0; i < 10; ++i) {
2180 // Get through the List API.
2181 Dart_Handle integer_obj = Dart_ListGetAt(byte_buffer_data, i);
2182 EXPECT_VALID(integer_obj);
2183 int64_t int64_t_value = -1;
2184 EXPECT_VALID(Dart_IntegerToInt64(integer_obj, &int64_t_value));
2185 EXPECT_EQ(i + 1, int64_t_value);
2186 }
2187
2188 // Some negative tests.
2191 result = Dart_NewByteBuffer(byte_buffer);
2195 result = Dart_GetDataFromByteBuffer(byte_array);
2197}
2198
2199static int kLength = 16;
2200
2204 EXPECT_VALID(byte_data);
2206 Dart_SetReturnValue(args, byte_data);
2208}
2209
2211 int arg_count,
2212 bool* auto_setup_scope) {
2213 ASSERT(auto_setup_scope != nullptr);
2214 *auto_setup_scope = true;
2215 return &ByteDataNativeFunction;
2216}
2217
2218TEST_CASE(DartAPI_ByteDataAccess) {
2219 const char* kScriptChars = R"(
2220import 'dart:typed_data';
2221class Expect {
2222 static equals(a, b) {
2223 if (a != b) {
2224 throw 'not equal. expected: $a, got: $b';
2225 }
2226 }
2227}
2228@pragma("vm:external-name", "CreateByteData")
2229external ByteData createByteData();
2230ByteData main() {
2231 var length = 16;
2232 var a = createByteData();
2233 Expect.equals(length, a.lengthInBytes);
2234 for (int i = 0; i < length; i+=1) {
2235 a.setInt8(i, 0x42);
2236 }
2237 for (int i = 0; i < length; i+=2) {
2238 Expect.equals(0x4242, a.getInt16(i));
2239 }
2240 return a;
2241}
2242)";
2243 // Create a test library and Load up a test script in it.
2244 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2245
2249
2250 // Invoke 'main' function.
2251 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
2253}
2254
2255static constexpr intptr_t kExtLength = 16;
2256static int8_t data[kExtLength] = {
2257 0x41, 0x42, 0x41, 0x42, 0x41, 0x42, 0x41, 0x42,
2258 0x41, 0x42, 0x41, 0x42, 0x41, 0x42, 0x41, 0x42,
2259};
2260
2263 Dart_Handle external_byte_data =
2265 EXPECT_VALID(external_byte_data);
2266 EXPECT_EQ(Dart_TypedData_kByteData,
2267 Dart_GetTypeOfTypedData(external_byte_data));
2268 Dart_SetReturnValue(args, external_byte_data);
2270}
2271
2274 int arg_count,
2275 bool* auto_setup_scope) {
2276 ASSERT(auto_setup_scope != nullptr);
2277 *auto_setup_scope = true;
2279}
2280
2281TEST_CASE(DartAPI_ExternalByteDataAccess) {
2282 // TODO(asiva): Once we have getInt16LE and getInt16BE support use the
2283 // appropriate getter instead of the host endian format used now.
2284 const char* kScriptChars = R"(
2285import 'dart:typed_data';
2286class Expect {
2287 static equals(a, b) {
2288 if (a != b) {
2289 throw 'not equal. expected: $a, got: $b';
2290 }
2291 }
2292}
2293@pragma("vm:external-name", "CreateExternalByteData")
2294external ByteData createExternalByteData();
2295ByteData main() {
2296 var length = 16;
2297 var a = createExternalByteData();
2298 Expect.equals(length, a.lengthInBytes);
2299 for (int i = 0; i < length; i+=2) {
2300 Expect.equals(0x4241, a.getInt16(i, Endian.little));
2301 }
2302 for (int i = 0; i < length; i+=2) {
2303 a.setInt8(i, 0x24);
2304 a.setInt8(i + 1, 0x28);
2305 }
2306 for (int i = 0; i < length; i+=2) {
2307 Expect.equals(0x2824, a.getInt16(i, Endian.little));
2308 }
2309 return a;
2310}
2311)";
2312 // Create a test library and Load up a test script in it.
2313 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2314
2318
2319 // Invoke 'main' function.
2320 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
2322
2323 for (intptr_t i = 0; i < kExtLength; i += 2) {
2324 EXPECT_EQ(0x24, data[i]);
2325 EXPECT_EQ(0x28, data[i + 1]);
2326 }
2327}
2328
2329static bool byte_data_finalizer_run = false;
2330void ByteDataFinalizer(void* isolate_data, void* peer) {
2332 free(peer);
2334}
2335
2336TEST_CASE(DartAPI_ExternalByteDataFinalizer) {
2337 // Check finalizer associated with the underlying array instead of the
2338 // wrapper.
2339 const char* kScriptChars =
2340 "var array;\n"
2341 "extractAndSaveArray(byteData) {\n"
2342 " array = byteData.buffer.asUint8List();\n"
2343 "}\n"
2344 "releaseArray() {\n"
2345 " array = null;\n"
2346 "}\n";
2347 // Create a test library and Load up a test script in it.
2348 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2349
2350 {
2352
2353 const intptr_t kBufferSize = 100;
2354 void* buffer = malloc(kBufferSize);
2355 // The buffer becomes readable by Dart, so ensure it is initialized to
2356 // satisfy our eager MSAN check.
2357 memset(buffer, 0, kBufferSize);
2361
2363 Dart_Invoke(lib, NewString("extractAndSaveArray"), 1, &byte_data);
2365
2366 // ByteData wrapper is still reachable from the scoped handle.
2368
2369 // The ByteData wrapper is now unreachable, but the underlying
2370 // ExternalUint8List is still alive.
2372 }
2373
2374 {
2377 }
2378
2380
2381 Dart_Handle result = Dart_Invoke(lib, NewString("releaseArray"), 0, nullptr);
2383
2384 {
2387 }
2388
2390}
2391
2392#ifndef PRODUCT
2393
2394static constexpr intptr_t kOptExtLength = 16;
2395static int8_t opt_data[kOptExtLength] = {
2396 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
2397 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
2398};
2399
2402 Dart_Handle external_byte_data =
2404 EXPECT_VALID(external_byte_data);
2405 EXPECT_EQ(Dart_TypedData_kByteData,
2406 Dart_GetTypeOfTypedData(external_byte_data));
2407 Dart_SetReturnValue(args, external_byte_data);
2409}
2410
2413 int arg_count,
2414 bool* auto_setup_scope) {
2415 ASSERT(auto_setup_scope != nullptr);
2416 *auto_setup_scope = true;
2418}
2419
2420TEST_CASE(DartAPI_OptimizedExternalByteDataAccess) {
2421 const char* kScriptChars = R"(
2422import 'dart:typed_data';
2423class Expect {
2424 static equals(a, b) {
2425 if (a != b) {
2426 throw 'not equal. expected: $a, got: $b';
2427 }
2428 }
2429}
2430@pragma("vm:external-name", "CreateExternalByteData")
2431external ByteData createExternalByteData();
2432access(ByteData a) {
2433 Expect.equals(0x04030201, a.getUint32(0, Endian.little));
2434 Expect.equals(0x08070605, a.getUint32(4, Endian.little));
2435 Expect.equals(0x0c0b0a09, a.getUint32(8, Endian.little));
2436 Expect.equals(0x100f0e0d, a.getUint32(12, Endian.little));
2437}
2438ByteData main() {
2439 var length = 16;
2440 var a = createExternalByteData();
2441 Expect.equals(length, a.lengthInBytes);
2442 for (int i = 0; i < 20; i++) {
2443 access(a);
2444 }
2445 return a;
2446}
2447)";
2448 // Create a test library and Load up a test script in it.
2449 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2450
2454
2455 // Invoke 'main' function.
2456 int old_oct = FLAG_optimization_counter_threshold;
2457 FLAG_optimization_counter_threshold = 5;
2458 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
2460 FLAG_optimization_counter_threshold = old_oct;
2461}
2462
2463#endif // !PRODUCT
2464
2468 EXPECT_VALID(byte_array);
2470 result = Dart_TypedDataAcquireData(byte_array, nullptr, nullptr, nullptr);
2472 "Dart_TypedDataAcquireData expects argument 'type'"
2473 " to be non-null.");
2475 result = Dart_TypedDataAcquireData(byte_array, &type, nullptr, nullptr);
2477 "Dart_TypedDataAcquireData expects argument 'data'"
2478 " to be non-null.");
2479 void* data;
2480 result = Dart_TypedDataAcquireData(byte_array, &type, &data, nullptr);
2482 "Dart_TypedDataAcquireData expects argument 'len'"
2483 " to be non-null.");
2484 intptr_t len;
2487 "Dart_TypedDataAcquireData expects argument 'object'"
2488 " to be non-null.");
2491 "Dart_TypedDataAcquireData expects argument 'object'"
2492 " to be of type 'TypedData'.");
2493
2496 "Dart_TypedDataReleaseData expects argument 'object'"
2497 " to be non-null.");
2500 "Dart_TypedDataReleaseData expects argument 'object'"
2501 " to be of type 'TypedData'.");
2502}
2503
2504TEST_CASE(DartAPI_TypedDataDirectAccessUnverified) {
2505 FLAG_verify_acquired_data = false;
2507}
2508
2509TEST_CASE(DartAPI_TypedDataDirectAccessVerified) {
2510 FLAG_verify_acquired_data = true;
2512}
2513
2515 Dart_Handle array,
2516 Dart_TypedData_Type expected_type,
2517 bool is_external) {
2519
2520 // Invoke the dart function that sets initial values.
2521 Dart_Handle dart_args[1];
2522 dart_args[0] = array;
2523 result = Dart_Invoke(lib, NewString("setMain"), 1, dart_args);
2525
2526 // Now Get a direct access to this typed data object and check it's contents.
2527 const int kLength = 10;
2529 void* data;
2530 intptr_t len;
2532 EXPECT(!Thread::Current()->IsAtSafepoint());
2534 EXPECT_EQ(expected_type, type);
2535 EXPECT_EQ(kLength, len);
2536 int8_t* dataP = reinterpret_cast<int8_t*>(data);
2537 for (int i = 0; i < kLength; i++) {
2538 EXPECT_EQ(i, dataP[i]);
2539 }
2540
2541 // Now try allocating a string with outstanding Acquires and it should
2542 // return an error.
2543 result = NewString("We expect an error here");
2544 EXPECT_ERROR(result, "Callbacks into the Dart VM are currently prohibited");
2545
2546 // Now modify the values in the directly accessible array and then check
2547 // it we see the changes back in dart.
2548 for (int i = 0; i < kLength; i++) {
2549 dataP[i] += 10;
2550 }
2551
2552 // Release direct access to the typed data object.
2553 EXPECT(!Thread::Current()->IsAtSafepoint());
2556
2557 // Invoke the dart function in order to check the modified values.
2558 result = Dart_Invoke(lib, NewString("testMain"), 1, dart_args);
2560}
2561
2563 public:
2564 BackgroundGCTask(IsolateGroup* isolate_group, Monitor* monitor, bool* done)
2565 : isolate_group_(isolate_group), monitor_(monitor), done_(done) {}
2566 virtual void Run() {
2567 const bool kBypassSafepoint = false;
2569 kBypassSafepoint);
2570 for (intptr_t i = 0; i < 10; i++) {
2572 }
2573 Thread::ExitIsolateGroupAsHelper(kBypassSafepoint);
2574 {
2575 MonitorLocker ml(monitor_);
2576 *done_ = true;
2577 ml.Notify();
2578 }
2579 }
2580
2581 private:
2582 IsolateGroup* isolate_group_;
2583 Monitor* monitor_;
2584 bool* done_;
2585};
2586
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 new Exception('not equal. expected: $a, got: $b');\n"
2594 " }\n"
2595 " }\n"
2596 "}\n"
2597 "void setMain(var a) {"
2598 " for (var i = 0; i < 10; i++) {"
2599 " a[i] = i;"
2600 " }"
2601 "}\n"
2602 "bool testMain(var list) {"
2603 " for (var i = 0; i < 10; i++) {"
2604 " Expect.equals((10 + i), list[i]);"
2605 " }\n"
2606 " return true;"
2607 "}\n"
2608 "List main() {"
2609 " var a = new Int8List(10);"
2610 " return a;"
2611 "}\n";
2612 // Create a test library and Load up a test script in it.
2613 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2614
2615 Monitor monitor;
2616 bool done = false;
2618 &done);
2619
2620 for (intptr_t i = 0; i < 10; i++) {
2621 // Test with an regular typed data object.
2622 Dart_Handle list_access_test_obj;
2623 list_access_test_obj = Dart_Invoke(lib, NewString("main"), 0, nullptr);
2624 EXPECT_VALID(list_access_test_obj);
2625 TestDirectAccess(lib, list_access_test_obj, Dart_TypedData_kInt8, false);
2626
2627 // Test with an external typed data object.
2628 uint8_t data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2629 intptr_t data_length = ARRAY_SIZE(data);
2630 Dart_Handle ext_list_access_test_obj;
2631 ext_list_access_test_obj =
2633 EXPECT_VALID(ext_list_access_test_obj);
2634 TestDirectAccess(lib, ext_list_access_test_obj, Dart_TypedData_kUint8,
2635 true);
2636 }
2637
2638 {
2639 MonitorLocker ml(&monitor);
2640 while (!done) {
2641 ml.Wait();
2642 }
2643 }
2644}
2645
2646TEST_CASE(DartAPI_TypedDataDirectAccess1Unverified) {
2647 FLAG_verify_acquired_data = false;
2649}
2650
2651TEST_CASE(DartAPI_TypedDataDirectAccess1Verified) {
2652 FLAG_verify_acquired_data = true;
2654}
2655
2657 const char* kScriptChars =
2658 "import 'dart:typed_data';\n"
2659 "class Expect {\n"
2660 " static equals(a, b) {\n"
2661 " if (a != b) {\n"
2662 " throw 'not equal. expected: $a, got: $b';\n"
2663 " }\n"
2664 " }\n"
2665 "}\n"
2666 "void setMain(var list) {"
2667 " Expect.equals(10, list.length);"
2668 " for (var i = 0; i < 10; i++) {"
2669 " list[i] = i;"
2670 " }"
2671 "}\n"
2672 "bool testMain(var list) {"
2673 " Expect.equals(10, list.length);"
2674 " for (var i = 0; i < 10; i++) {"
2675 " Expect.equals((10 + i), list[i]);"
2676 " }"
2677 " return true;"
2678 "}\n"
2679 "List main() {"
2680 " var a = new Int8List(100);"
2681 " var view = new Int8List.view(a.buffer, 50, 10);"
2682 " return view;"
2683 "}\n";
2684 // Create a test library and Load up a test script in it.
2685 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2686
2687 // Test with a typed data view object.
2688 Dart_Handle list_access_test_obj;
2689 list_access_test_obj = Dart_Invoke(lib, NewString("main"), 0, nullptr);
2690 EXPECT_VALID(list_access_test_obj);
2691 TestDirectAccess(lib, list_access_test_obj, Dart_TypedData_kInt8, false);
2692}
2693
2694TEST_CASE(DartAPI_TypedDataViewDirectAccessUnverified) {
2695 FLAG_verify_acquired_data = false;
2697}
2698
2699TEST_CASE(DartAPI_TypedDataViewDirectAccessVerified) {
2700 FLAG_verify_acquired_data = true;
2702}
2703
2705 const char* kScriptChars =
2706 "import 'dart:typed_data';\n"
2707 "List main() {"
2708 " var list = new Int8List(100);"
2709 " for (var i = 0; i < 100; i++) {"
2710 " list[i] = i;"
2711 " }"
2712 " return list.asUnmodifiableView();"
2713 "}\n";
2714 // Create a test library and Load up a test script in it.
2715 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2716
2717 // Test with a typed data view object.
2718 Dart_Handle view_obj;
2719 view_obj = Dart_Invoke(lib, NewString("main"), 0, nullptr);
2720 EXPECT_VALID(view_obj);
2721
2722 const int kLength = 100;
2724 void* data;
2725 intptr_t len;
2727 EXPECT(!Thread::Current()->IsAtSafepoint());
2729 EXPECT_EQ(Dart_TypedData_kInt8, type);
2730 EXPECT_EQ(kLength, len);
2731 int8_t* dataP = reinterpret_cast<int8_t*>(data);
2732 for (int i = 0; i < kLength; i++) {
2733 EXPECT_EQ(i, dataP[i]);
2734 }
2735
2736 // Now try allocating a string with outstanding Acquires and it should
2737 // return an error.
2738 result = NewString("We expect an error here");
2739 EXPECT_ERROR(result, "Callbacks into the Dart VM are currently prohibited");
2740
2741 // Release direct access to the typed data object.
2742 EXPECT(!Thread::Current()->IsAtSafepoint());
2745}
2746
2747TEST_CASE(DartAPI_UnmodifiableTypedDataViewDirectAccessUnverified) {
2748 FLAG_verify_acquired_data = false;
2750}
2751
2752TEST_CASE(DartAPI_UnmodifiableTypedDataViewDirectAccessVerified) {
2753 FLAG_verify_acquired_data = true;
2755}
2756
2758 const char* kScriptChars =
2759 "import 'dart:typed_data';\n"
2760 "class Expect {\n"
2761 " static equals(a, b) {\n"
2762 " if (a != b) {\n"
2763 " throw 'not equal. expected: $a, got: $b';\n"
2764 " }\n"
2765 " }\n"
2766 "}\n"
2767 "void setMain(var list) {"
2768 " Expect.equals(10, list.length);"
2769 " for (var i = 0; i < 10; i++) {"
2770 " list.setInt8(i, i);"
2771 " }"
2772 "}\n"
2773 "bool testMain(var list) {"
2774 " Expect.equals(10, list.length);"
2775 " for (var i = 0; i < 10; i++) {"
2776 " Expect.equals((10 + i), list.getInt8(i));"
2777 " }"
2778 " return true;"
2779 "}\n"
2780 "ByteData main() {"
2781 " var a = new Int8List(100);"
2782 " var view = new ByteData.view(a.buffer, 50, 10);"
2783 " return view;"
2784 "}\n";
2785 // Create a test library and Load up a test script in it.
2786 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2787
2788 // Test with a typed data view object.
2789 Dart_Handle list_access_test_obj;
2790 list_access_test_obj = Dart_Invoke(lib, NewString("main"), 0, nullptr);
2791 EXPECT_VALID(list_access_test_obj);
2792 TestDirectAccess(lib, list_access_test_obj, Dart_TypedData_kByteData, false);
2793}
2794
2795TEST_CASE(DartAPI_ByteDataDirectAccessUnverified) {
2796 FLAG_verify_acquired_data = false;
2798}
2799
2800TEST_CASE(DartAPI_ByteDataDirectAccessVerified) {
2801 FLAG_verify_acquired_data = true;
2803}
2804
2805TEST_CASE(DartAPI_NewUnmodifiableExternalTypedDataWithFinalizer) {
2806 const char* kScriptChars = R"(
2807class Expect {
2808 static equals(a, b) {
2809 if (a != b) {
2810 throw 'not equal. expected: $a, got: $b';
2811 }
2812 }
2813 static throws(block) {
2814 bool threw = false;
2815 try { block(); } catch (e) { threw = true; }
2816 if (!threw) throw 'did not throw';
2817 }
2818}
2819testList(data) {
2820 for (var i = 0; i < data.length; i++) {
2821 Expect.equals(i, data[i]);
2822 Expect.throws(() => data[i] = 0);
2823 }
2824}
2825testBytes(data) {
2826 for (var i = 0; i < data.length; i++) {
2827 Expect.equals(i, data.getUint8(i));
2828 Expect.throws(() => data.setUint8(i, 0));
2829 }
2830})";
2831 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2832
2833 {
2834 uint8_t data[] = {0, 1, 2, 3};
2836 Dart_TypedData_kUint8, &data[0], ARRAY_SIZE(data), nullptr, 0, nullptr);
2837 EXPECT_VALID(typed_data);
2838 EXPECT_EQ(Dart_TypedData_kUint8, Dart_GetTypeOfTypedData(typed_data));
2839 Dart_Handle args[1];
2840 args[0] = typed_data;
2842 Dart_Invoke(lib, NewString("testList"), ARRAY_SIZE(args), args);
2844 }
2845
2846 {
2847 int8_t data[] = {0, 1, 2, 3};
2849 Dart_TypedData_kInt8, &data[0], ARRAY_SIZE(data), nullptr, 0, nullptr);
2850 EXPECT_VALID(typed_data);
2851 EXPECT_EQ(Dart_TypedData_kInt8, Dart_GetTypeOfTypedData(typed_data));
2852 Dart_Handle args[1];
2853 args[0] = typed_data;
2855 Dart_Invoke(lib, NewString("testList"), ARRAY_SIZE(args), args);
2857 }
2858
2859 {
2860 uint16_t data[] = {0, 1, 2, 3};
2862 Dart_TypedData_kUint16, &data[0], ARRAY_SIZE(data), nullptr, 0,
2863 nullptr);
2864 EXPECT_VALID(typed_data);
2865 EXPECT_EQ(Dart_TypedData_kUint16, Dart_GetTypeOfTypedData(typed_data));
2866 Dart_Handle args[1];
2867 args[0] = typed_data;
2869 Dart_Invoke(lib, NewString("testList"), ARRAY_SIZE(args), args);
2871 }
2872
2873 {
2874 int16_t data[] = {0, 1, 2, 3};
2876 Dart_TypedData_kInt16, &data[0], ARRAY_SIZE(data), nullptr, 0, nullptr);
2877 EXPECT_VALID(typed_data);
2878 EXPECT_EQ(Dart_TypedData_kInt16, Dart_GetTypeOfTypedData(typed_data));
2879 Dart_Handle args[1];
2880 args[0] = typed_data;
2882 Dart_Invoke(lib, NewString("testList"), ARRAY_SIZE(args), args);
2884 }
2885
2886 {
2887 uint32_t data[] = {0, 1, 2, 3};
2889 Dart_TypedData_kUint32, &data[0], ARRAY_SIZE(data), nullptr, 0,
2890 nullptr);
2891 EXPECT_VALID(typed_data);
2892 EXPECT_EQ(Dart_TypedData_kUint32, Dart_GetTypeOfTypedData(typed_data));
2893 Dart_Handle args[1];
2894 args[0] = typed_data;
2896 Dart_Invoke(lib, NewString("testList"), ARRAY_SIZE(args), args);
2898 }
2899
2900 {
2901 int32_t data[] = {0, 1, 2, 3};
2903 Dart_TypedData_kInt32, &data[0], ARRAY_SIZE(data), nullptr, 0, nullptr);
2904 EXPECT_VALID(typed_data);
2905 EXPECT_EQ(Dart_TypedData_kInt32, Dart_GetTypeOfTypedData(typed_data));
2906 Dart_Handle args[1];
2907 args[0] = typed_data;
2909 Dart_Invoke(lib, NewString("testList"), ARRAY_SIZE(args), args);
2911 }
2912
2913 {
2914 uint64_t data[] = {0, 1, 2, 3};
2916 Dart_TypedData_kUint64, &data[0], ARRAY_SIZE(data), nullptr, 0,
2917 nullptr);
2918 EXPECT_VALID(typed_data);
2919 EXPECT_EQ(Dart_TypedData_kUint64, Dart_GetTypeOfTypedData(typed_data));
2920 Dart_Handle args[1];
2921 args[0] = typed_data;
2923 Dart_Invoke(lib, NewString("testList"), ARRAY_SIZE(args), args);
2925 }
2926
2927 {
2928 int64_t data[] = {0, 1, 2, 3};
2930 Dart_TypedData_kInt64, &data[0], ARRAY_SIZE(data), nullptr, 0, nullptr);
2931 EXPECT_VALID(typed_data);
2932 EXPECT_EQ(Dart_TypedData_kInt64, Dart_GetTypeOfTypedData(typed_data));
2933 Dart_Handle args[1];
2934 args[0] = typed_data;
2936 Dart_Invoke(lib, NewString("testList"), ARRAY_SIZE(args), args);
2938 }
2939
2940 {
2941 float data[] = {0.0f, 1.0f, 2.0f, 3.0f};
2943 Dart_TypedData_kFloat32, &data[0], ARRAY_SIZE(data), nullptr, 0,
2944 nullptr);
2945 EXPECT_VALID(typed_data);
2946 EXPECT_EQ(Dart_TypedData_kFloat32, Dart_GetTypeOfTypedData(typed_data));
2948 Dart_Invoke(lib, NewString("testList"), 1, &typed_data);
2951 }
2952
2953 {
2954 double data[] = {0.0, 1.0, 2.0, 3.0};
2956 Dart_TypedData_kFloat64, &data[0], ARRAY_SIZE(data), nullptr, 0,
2957 nullptr);
2958 EXPECT_VALID(typed_data);
2959 EXPECT_EQ(Dart_TypedData_kFloat64, Dart_GetTypeOfTypedData(typed_data));
2960 Dart_Handle args[1];
2961 args[0] = typed_data;
2963 Dart_Invoke(lib, NewString("testList"), ARRAY_SIZE(args), args);
2965 }
2966
2967 {
2968 uint8_t data[] = {0, 1, 2, 3};
2970 Dart_TypedData_kByteData, &data[0], ARRAY_SIZE(data), nullptr, 0,
2971 nullptr);
2972 EXPECT_VALID(typed_data);
2973 EXPECT_EQ(Dart_TypedData_kByteData, Dart_GetTypeOfTypedData(typed_data));
2974 Dart_Handle args[1];
2975 args[0] = typed_data;
2977 Dart_Invoke(lib, NewString("testBytes"), ARRAY_SIZE(args), args);
2979 }
2980}
2981
2982TEST_CASE(DartAPI_UnmodifiableTypedData_PassByReference) {
2983 const char* kScriptChars = R"(
2984import 'dart:isolate';
2985test(original) {
2986 var port = new RawReceivePort();
2987 port.handler = (msg) {
2988 port.close();
2989 if (!identical(original, msg)) throw "got a copy";
2990 };
2991 port.sendPort.send(original);
2992})";
2993 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
2994
2995 uint8_t data[] = {0, 1, 2, 3};
2997 Dart_TypedData_kUint8, &data[0], ARRAY_SIZE(data), nullptr, 0, nullptr);
2998 EXPECT_VALID(typed_data);
2999 EXPECT_EQ(Dart_TypedData_kUint8, Dart_GetTypeOfTypedData(typed_data));
3000 Dart_Handle args[1];
3001 args[0] = typed_data;
3003 Dart_Invoke(lib, NewString("test"), ARRAY_SIZE(args), args);
3005 result = Dart_RunLoop();
3007}
3008
3009static void NopCallback(void* isolate_callback_data, void* peer) {}
3010
3011TEST_CASE(DartAPI_ExternalAllocationDuringNoCallbackScope) {
3013 EXPECT_VALID(bytes);
3014
3015 intptr_t gc_count_before = Thread::Current()->heap()->Collections(Heap::kNew);
3016
3018 void* data;
3019 intptr_t len;
3022
3024 Dart_NewWeakPersistentHandle(bytes, nullptr, 100 * MB, NopCallback);
3025 EXPECT_VALID(reinterpret_cast<Dart_Handle>(weak));
3026
3027 EXPECT_EQ(gc_count_before,
3028 Thread::Current()->heap()->Collections(Heap::kNew));
3029
3032
3033 EXPECT_LT(gc_count_before,
3034 Thread::Current()->heap()->Collections(Heap::kNew));
3035}
3036
3038 Dart_TypedData_Type expected_type,
3039 uint8_t data[],
3040 intptr_t data_length) {
3041 EXPECT_VALID(obj);
3042 EXPECT_EQ(expected_type, Dart_GetTypeOfExternalTypedData(obj));
3043 EXPECT(Dart_IsList(obj));
3044
3045 void* raw_data = nullptr;
3046 intptr_t len;
3048 EXPECT_VALID(Dart_TypedDataAcquireData(obj, &type, &raw_data, &len));
3049 EXPECT(raw_data == data);
3050 EXPECT_EQ(data_length, len);
3051 EXPECT_EQ(expected_type, type);
3053
3054 intptr_t list_length = 0;
3055 EXPECT_VALID(Dart_ListLength(obj, &list_length));
3056 EXPECT_EQ(data_length, list_length);
3057
3058 // Load and check values from underlying array and API.
3059 for (intptr_t i = 0; i < list_length; ++i) {
3060 EXPECT_EQ(11 * i, data[i]);
3061 Dart_Handle elt = Dart_ListGetAt(obj, i);
3062 EXPECT_VALID(elt);
3063 int64_t value = 0;
3065 EXPECT_EQ(data[i], value);
3066 }
3067
3068 // Write values through the underlying array.
3069 for (intptr_t i = 0; i < data_length; ++i) {
3070 data[i] *= 2;
3071 }
3072 // Read them back through the API.
3073 for (intptr_t i = 0; i < list_length; ++i) {
3074 Dart_Handle elt = Dart_ListGetAt(obj, i);
3075 EXPECT_VALID(elt);
3076 int64_t value = 0;
3078 EXPECT_EQ(22 * i, value);
3079 }
3080
3081 // Write values through the API.
3082 for (intptr_t i = 0; i < list_length; ++i) {
3086 }
3087 // Read them back through the underlying array.
3088 for (intptr_t i = 0; i < data_length; ++i) {
3089 EXPECT_EQ(33 * i, data[i]);
3090 }
3091}
3092
3093TEST_CASE(DartAPI_ExternalTypedDataAccess) {
3094 uint8_t data[] = {0, 11, 22, 33, 44, 55, 66, 77};
3095 intptr_t data_length = ARRAY_SIZE(data);
3096
3097 Dart_Handle obj =
3100}
3101
3102TEST_CASE(DartAPI_ExternalClampedTypedDataAccess) {
3103 uint8_t data[] = {0, 11, 22, 33, 44, 55, 66, 77};
3104 intptr_t data_length = ARRAY_SIZE(data);
3105
3107 data, data_length);
3109 data_length);
3110}
3111
3112TEST_CASE(DartAPI_ExternalUint8ClampedArrayAccess) {
3113 const char* kScriptChars =
3114 "testClamped(List a) {\n"
3115 " if (a[1] != 11) return false;\n"
3116 " a[1] = 3;\n"
3117 " if (a[1] != 3) return false;\n"
3118 " a[1] = -12;\n"
3119 " if (a[1] != 0) return false;\n"
3120 " a[1] = 1200;\n"
3121 " if (a[1] != 255) return false;\n"
3122 " return true;\n"
3123 "}\n";
3124
3125 uint8_t data[] = {0, 11, 22, 33, 44, 55, 66, 77};
3126 intptr_t data_length = ARRAY_SIZE(data);
3128 data, data_length);
3129 EXPECT_VALID(obj);
3131 // Create a test library and Load up a test script in it.
3132 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
3133 Dart_Handle args[1];
3134 args[0] = obj;
3135 result = Dart_Invoke(lib, NewString("testClamped"), 1, args);
3136
3137 // Check that result is true.
3140 bool value = false;
3143 EXPECT(value);
3144}
3145
3146static void UnreachedCallback(void* isolate_callback_data, void* peer) {
3147 UNREACHABLE();
3148}
3149
3150static void ExternalTypedDataFinalizer(void* isolate_callback_data,
3151 void* peer) {
3152 *static_cast<int*>(peer) = 42;
3153}
3154
3155TEST_CASE(DartAPI_ExternalTypedDataCallback) {
3156 int peer = 0;
3157 {
3159 uint8_t data[] = {1, 2, 3, 4};
3161 Dart_TypedData_kUint8, data, ARRAY_SIZE(data), &peer, sizeof(data),
3163 EXPECT_VALID(obj);
3165 }
3166 {
3167 TransitionNativeToVM transition(thread);
3168 EXPECT(peer == 0);
3169 GCTestHelper::CollectNewSpace();
3170 EXPECT(peer == 42);
3171 }
3172}
3173
3174static void SlowFinalizer(void* isolate_callback_data, void* peer) {
3175 OS::Sleep(10);
3176 intptr_t* count = reinterpret_cast<intptr_t*>(peer);
3177 (*count)++;
3178}
3179
3180TEST_CASE(DartAPI_SlowFinalizer) {
3181 intptr_t count = 0;
3182 for (intptr_t i = 0; i < 10; i++) {
3184 Dart_Handle str1 = Dart_NewStringFromCString("Live fast");
3186 Dart_Handle str2 = Dart_NewStringFromCString("Die young");
3189
3190 {
3191 TransitionNativeToVM transition(thread);
3193 }
3194 }
3195
3196 EXPECT_EQ(20, count);
3197}
3198
3199static void SlowWeakPersistentHandle(void* isolate_callback_data, void* peer) {
3200 OS::Sleep(10);
3201 intptr_t* count = reinterpret_cast<intptr_t*>(peer);
3202 (*count)++;
3203}
3204
3205TEST_CASE(DartAPI_SlowWeakPersistentHandle) {
3206 Dart_WeakPersistentHandle handles[20];
3207 intptr_t count = 0;
3208
3209 for (intptr_t i = 0; i < 10; i++) {
3211 Dart_Handle str1 = Dart_NewStringFromCString("Live fast");
3212 handles[i] =
3214 Dart_Handle str2 = Dart_NewStringFromCString("Die young");
3215 handles[i + 10] =
3218
3219 {
3220 TransitionNativeToVM transition(thread);
3222 }
3223 }
3224
3225 EXPECT_EQ(20, count);
3226
3227 for (intptr_t i = 0; i < 20; i++) {
3229 }
3230}
3231
3233 void* raw_data = nullptr;
3234 intptr_t len;
3236 EXPECT_VALID(Dart_TypedDataAcquireData(obj, &type, &raw_data, &len));
3237 EXPECT_EQ(Dart_TypedData_kFloat32x4, type);
3238 EXPECT_EQ(len, 10);
3239 float* float_data = reinterpret_cast<float*>(raw_data);
3240 for (int i = 0; i < len * 4; i++) {
3241 EXPECT_EQ(0.0, float_data[i]);
3242 }
3244}
3245
3246TEST_CASE(DartAPI_Float32x4List) {
3247 const char* kScriptChars =
3248 "import 'dart:typed_data';\n"
3249 "Float32x4List float32x4() {\n"
3250 " return new Float32x4List(10);\n"
3251 "}\n";
3252 // Create a test library and Load up a test script in it.
3253 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
3254
3255 Dart_Handle obj = Dart_Invoke(lib, NewString("float32x4"), 0, nullptr);
3256 EXPECT_VALID(obj);
3257 CheckFloat32x4Data(obj);
3258
3260 EXPECT_VALID(obj);
3261 CheckFloat32x4Data(obj);
3262
3263 int peer = 0;
3264 float data[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
3265 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
3266 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
3267 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
3268 // Push a scope so that we can collect the local handle created as part of
3269 // Dart_NewExternalTypedData.
3271 {
3273 Dart_TypedData_kFloat32x4, data, 10, &peer, sizeof(data),
3275 CheckFloat32x4Data(lcl);
3276 }
3278 {
3279 TransitionNativeToVM transition(thread);
3280 GCTestHelper::CollectNewSpace();
3281 EXPECT(peer == 42);
3282 }
3283}
3284
3285// Unit test for entering a scope, creating a local handle and exiting
3286// the scope.
3287VM_UNIT_TEST_CASE(DartAPI_EnterExitScope) {
3288 TestIsolateScope __test_isolate__;
3289
3290 Thread* thread = Thread::Current();
3291 EXPECT(thread != nullptr);
3292 ApiLocalScope* scope = thread->api_top_scope();
3294 {
3295 EXPECT(thread->api_top_scope() != nullptr);
3296 TransitionNativeToVM transition(thread);
3297 HANDLESCOPE(thread);
3298 String& str1 = String::Handle();
3299 str1 = String::New("Test String");
3300 Dart_Handle ref = Api::NewHandle(thread, str1.ptr());
3301 String& str2 = String::Handle();
3302 str2 ^= Api::UnwrapHandle(ref);
3303 EXPECT(str1.Equals(str2));
3304 }
3306 EXPECT(scope == thread->api_top_scope());
3307}
3308
3309// Unit test for creating and deleting persistent handles.
3310VM_UNIT_TEST_CASE(DartAPI_PersistentHandles) {
3311 const char* kTestString1 = "Test String1";
3312 const char* kTestString2 = "Test String2";
3314 Thread* thread = Thread::Current();
3315 Isolate* isolate = thread->isolate();
3316 EXPECT(isolate != nullptr);
3317 ApiState* state = isolate->group()->api_state();
3318 EXPECT(state != nullptr);
3319 ApiLocalScope* scope = thread->api_top_scope();
3320
3321 const intptr_t handle_count_start = state->CountPersistentHandles();
3322
3323 Dart_PersistentHandle handles[2000];
3325 {
3326 CHECK_API_SCOPE(thread);
3327 Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
3328 for (int i = 0; i < 1000; i++) {
3329 handles[i] = Dart_NewPersistentHandle(ref1);
3330 }
3332 Dart_Handle ref2 = Dart_NewStringFromCString(kTestString2);
3333 for (int i = 1000; i < 2000; i++) {
3334 handles[i] = Dart_NewPersistentHandle(ref2);
3335 }
3336 for (int i = 500; i < 1500; i++) {
3338 }
3339 for (int i = 500; i < 1000; i++) {
3340 handles[i] = Dart_NewPersistentHandle(ref2);
3341 }
3342 for (int i = 1000; i < 1500; i++) {
3343 handles[i] = Dart_NewPersistentHandle(ref1);
3344 }
3346 }
3348 {
3349 TransitionNativeToVM transition(thread);
3350 StackZone zone(thread);
3351 for (int i = 0; i < 500; i++) {
3352 String& str = String::Handle();
3353 str ^= PersistentHandle::Cast(handles[i])->ptr();
3354 EXPECT(str.Equals(kTestString1));
3355 }
3356 for (int i = 500; i < 1000; i++) {
3357 String& str = String::Handle();
3358 str ^= PersistentHandle::Cast(handles[i])->ptr();
3359 EXPECT(str.Equals(kTestString2));
3360 }
3361 for (int i = 1000; i < 1500; i++) {
3362 String& str = String::Handle();
3363 str ^= PersistentHandle::Cast(handles[i])->ptr();
3364 EXPECT(str.Equals(kTestString1));
3365 }
3366 for (int i = 1500; i < 2000; i++) {
3367 String& str = String::Handle();
3368 str ^= PersistentHandle::Cast(handles[i])->ptr();
3369 EXPECT(str.Equals(kTestString2));
3370 }
3371 }
3372 EXPECT(scope == thread->api_top_scope());
3373 EXPECT_EQ(handle_count_start + 2000, state->CountPersistentHandles());
3375}
3376
3377// Test that we are able to create a persistent handle from a
3378// persistent handle.
3379VM_UNIT_TEST_CASE(DartAPI_NewPersistentHandle_FromPersistentHandle) {
3380 TestIsolateScope __test_isolate__;
3381
3382 Isolate* isolate = Isolate::Current();
3383 EXPECT(isolate != nullptr);
3384 ApiState* state = isolate->group()->api_state();
3385 EXPECT(state != nullptr);
3386 Thread* thread = Thread::Current();
3387 CHECK_API_SCOPE(thread);
3388
3389 // Start with a known persistent handle.
3391 EXPECT(state->IsValidPersistentHandle(obj1));
3392
3393 // And use it to allocate a second persistent handle.
3396 EXPECT(state->IsValidPersistentHandle(obj3));
3397
3398 // Make sure that the value transferred.
3400 EXPECT(Dart_IsBoolean(obj4));
3401 bool value = false;
3404 EXPECT(value);
3405}
3406
3407// Test that we can assign to a persistent handle.
3408VM_UNIT_TEST_CASE(DartAPI_AssignToPersistentHandle) {
3409 const char* kTestString1 = "Test String1";
3410 const char* kTestString2 = "Test String2";
3411 TestIsolateScope __test_isolate__;
3412
3415 Isolate* isolate = T->isolate();
3416 EXPECT(isolate != nullptr);
3417 ApiState* state = isolate->group()->api_state();
3418 EXPECT(state != nullptr);
3419
3420 // Start with a known persistent handle.
3421 Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
3423 EXPECT(state->IsValidPersistentHandle(obj));
3424 {
3425 TransitionNativeToVM transition(T);
3426 HANDLESCOPE(T);
3427 String& str = String::Handle();
3428 str ^= PersistentHandle::Cast(obj)->ptr();
3429 EXPECT(str.Equals(kTestString1));
3430 }
3431
3432 // Now create another local handle and assign it to the persistent handle.
3433 Dart_Handle ref2 = Dart_NewStringFromCString(kTestString2);
3434 Dart_SetPersistentHandle(obj, ref2);
3435 {
3436 TransitionNativeToVM transition(T);
3437 HANDLESCOPE(T);
3438 String& str = String::Handle();
3439 str ^= PersistentHandle::Cast(obj)->ptr();
3440 EXPECT(str.Equals(kTestString2));
3441 }
3442
3443 // Now assign Null to the persistent handle and check.
3445 EXPECT(Dart_IsNull(obj));
3446}
3447
3448static Dart_Handle AllocateNewString(const char* c_str) {
3449 Thread* thread = Thread::Current();
3450 TransitionNativeToVM transition(thread);
3451 return Api::NewHandle(thread, String::New(c_str, Heap::kNew));
3452}
3453
3454static Dart_Handle AllocateOldString(const char* c_str) {
3455 Thread* thread = Thread::Current();
3456 TransitionNativeToVM transition(thread);
3457 return Api::NewHandle(thread, String::New(c_str, Heap::kOld));
3458}
3459
3461 return Dart_HandleFromPersistent(weak);
3462}
3463
3465 return Dart_HandleFromWeakPersistent(weak);
3466}
3467
3468TEST_CASE(DartAPI_WeakPersistentHandle) {
3469 Dart_WeakPersistentHandle weak_new_ref = nullptr;
3470 Dart_WeakPersistentHandle weak_old_ref = nullptr;
3471
3472 {
3474
3475 Dart_Handle new_ref, old_ref;
3476 {
3477 // GCs due to allocations or weak handle creation can cause early
3478 // promotion and interfere with the scenario this test is verifying.
3479 ForceGrowthScope force_growth(thread);
3480
3481 // Create an object in new space.
3482 new_ref = AllocateNewString("new string");
3483 EXPECT_VALID(new_ref);
3484
3485 // Create an object in old space.
3486 old_ref = AllocateOldString("old string");
3487 EXPECT_VALID(old_ref);
3488
3489 // Create a weak ref to the new space object.
3490 weak_new_ref =
3491 Dart_NewWeakPersistentHandle(new_ref, nullptr, 0, NopCallback);
3492 EXPECT_VALID(AsHandle(weak_new_ref));
3493 EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
3494
3495 // Create a weak ref to the old space object.
3496 weak_old_ref =
3497 Dart_NewWeakPersistentHandle(old_ref, nullptr, 0, NopCallback);
3498
3499 EXPECT_VALID(AsHandle(weak_old_ref));
3500 EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
3501 }
3502
3503 {
3504 TransitionNativeToVM transition(thread);
3505 // Garbage collect new space.
3506 GCTestHelper::CollectNewSpace();
3507 }
3508
3509 // Nothing should be invalidated or cleared.
3510 EXPECT_VALID(new_ref);
3511 EXPECT(!Dart_IsNull(new_ref));
3512 EXPECT_VALID(old_ref);
3513 EXPECT(!Dart_IsNull(old_ref));
3514
3515 EXPECT_VALID(AsHandle(weak_new_ref));
3516 EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
3517 EXPECT(Dart_IdentityEquals(new_ref, AsHandle(weak_new_ref)));
3518
3519 EXPECT_VALID(AsHandle(weak_old_ref));
3520 EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
3521 EXPECT(Dart_IdentityEquals(old_ref, AsHandle(weak_old_ref)));
3522
3523 {
3524 TransitionNativeToVM transition(thread);
3525 // Garbage collect old space.
3526 GCTestHelper::CollectOldSpace();
3527 }
3528
3529 // Nothing should be invalidated or cleared.
3530 EXPECT_VALID(new_ref);
3531 EXPECT(!Dart_IsNull(new_ref));
3532 EXPECT_VALID(old_ref);
3533 EXPECT(!Dart_IsNull(old_ref));
3534
3535 EXPECT_VALID(AsHandle(weak_new_ref));
3536 EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
3537 EXPECT(Dart_IdentityEquals(new_ref, AsHandle(weak_new_ref)));
3538
3539 EXPECT_VALID(AsHandle(weak_old_ref));
3540 EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
3541 EXPECT(Dart_IdentityEquals(old_ref, AsHandle(weak_old_ref)));
3542
3543 // Delete local (strong) references.
3545 }
3546
3547 {
3548 TransitionNativeToVM transition(thread);
3549 // Garbage collect new space again.
3550 GCTestHelper::CollectNewSpace();
3551 }
3552
3553 {
3555 // Weak ref to new space object should now be cleared.
3556 EXPECT_VALID(AsHandle(weak_new_ref));
3557 EXPECT(Dart_IsNull(AsHandle(weak_new_ref)));
3558 EXPECT_VALID(AsHandle(weak_old_ref));
3559 EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
3561 }
3562
3563 {
3564 TransitionNativeToVM transition(thread);
3565 // Garbage collect old space again.
3566 GCTestHelper::CollectOldSpace();
3567 }
3568
3569 {
3571 // Weak ref to old space object should now be cleared.
3572 EXPECT_VALID(AsHandle(weak_new_ref));
3573 EXPECT(Dart_IsNull(AsHandle(weak_new_ref)));
3574 EXPECT_VALID(AsHandle(weak_old_ref));
3575 EXPECT(Dart_IsNull(AsHandle(weak_old_ref)));
3577 }
3578
3579 {
3580 TransitionNativeToVM transition(thread);
3581 // Garbage collect one last time to revisit deleted handles.
3583 }
3584
3585 Dart_DeleteWeakPersistentHandle(weak_new_ref);
3586 Dart_DeleteWeakPersistentHandle(weak_old_ref);
3587}
3588
3593
3594static void FinalizableHandleCallback(void* isolate_callback_data, void* peer) {
3595 if (peer == finalizable_new_ref_peer) {
3597 finalizable_new_ref = nullptr;
3598 } else if (peer == finalizable_old_ref_peer) {
3600 finalizable_old_ref = nullptr;
3601 }
3602}
3603
3604TEST_CASE(DartAPI_FinalizableHandle) {
3605 void* peer = reinterpret_cast<void*>(0);
3606 Dart_Handle local_new_ref = Dart_Null();
3607 finalizable_new_ref = Dart_NewFinalizableHandle(local_new_ref, peer, 0,
3610
3611 peer = reinterpret_cast<void*>(1);
3612 Dart_Handle local_old_ref = Dart_Null();
3613 finalizable_old_ref = Dart_NewFinalizableHandle(local_old_ref, peer, 0,
3616
3617 {
3619
3620 Dart_Handle new_ref, old_ref;
3621 {
3622 // GCs due to allocations or weak handle creation can cause early
3623 // promotion and interfere with the scenario this test is verifying.
3624 ForceGrowthScope force_growth(thread);
3625
3626 // Create an object in new space.
3627 new_ref = AllocateNewString("new string");
3628 EXPECT_VALID(new_ref);
3629
3630 // Create an object in old space.
3631 old_ref = AllocateOldString("old string");
3632 EXPECT_VALID(old_ref);
3633
3634 // Create a weak ref to the new space object.
3635 peer = reinterpret_cast<void*>(2);
3637 new_ref, peer, 0, FinalizableHandleCallback);
3639
3640 // Create a weak ref to the old space object.
3641 peer = reinterpret_cast<void*>(3);
3643 old_ref, peer, 0, FinalizableHandleCallback);
3645 }
3646
3647 {
3648 TransitionNativeToVM transition(thread);
3649 // Garbage collect new space.
3650 GCTestHelper::CollectNewSpace();
3651 }
3652
3653 // Nothing should be invalidated or cleared.
3654 EXPECT_VALID(new_ref);
3655 EXPECT(!Dart_IsNull(new_ref));
3656 EXPECT_VALID(old_ref);
3657 EXPECT(!Dart_IsNull(old_ref));
3658
3659 {
3660 TransitionNativeToVM transition(thread);
3661 // Garbage collect old space.
3662 GCTestHelper::CollectOldSpace();
3663 }
3664
3665 // Nothing should be invalidated or cleared.
3666 EXPECT_VALID(new_ref);
3667 EXPECT(!Dart_IsNull(new_ref));
3668 EXPECT_VALID(old_ref);
3669 EXPECT(!Dart_IsNull(old_ref));
3670
3671 // Delete local (strong) references.
3673 }
3674
3675 {
3676 TransitionNativeToVM transition(thread);
3677 // Garbage collect new space again.
3678 GCTestHelper::CollectNewSpace();
3679 }
3680
3681 {
3683 // Weak ref to new space object should now be cleared.
3684 EXPECT(finalizable_new_ref == nullptr);
3686 }
3687
3688 {
3689 TransitionNativeToVM transition(thread);
3690 // Garbage collect old space again.
3691 GCTestHelper::CollectOldSpace();
3692 }
3693
3694 {
3696 // Weak ref to old space object should now be cleared.
3697 EXPECT(finalizable_new_ref == nullptr);
3698 EXPECT(finalizable_old_ref == nullptr);
3700 }
3701
3702 {
3703 TransitionNativeToVM transition(thread);
3705 }
3706}
3707
3708TEST_CASE(DartAPI_WeakPersistentHandleErrors) {
3710
3711 // nullptr callback.
3712 Dart_Handle obj1 = NewString("new string");
3713 EXPECT_VALID(obj1);
3715 Dart_NewWeakPersistentHandle(obj1, nullptr, 0, nullptr);
3716 EXPECT_EQ(ref1, static_cast<void*>(nullptr));
3717
3718 // Immediate object.
3719 Dart_Handle obj2 = Dart_NewInteger(0);
3720 EXPECT_VALID(obj2);
3722 Dart_NewWeakPersistentHandle(obj2, nullptr, 0, NopCallback);
3723 EXPECT_EQ(ref2, static_cast<void*>(nullptr));
3724
3725 // Pointer object.
3726 Dart_Handle ffi_lib = Dart_LookupLibrary(NewString("dart:ffi"));
3727 Dart_Handle pointer_type =
3728 Dart_GetNonNullableType(ffi_lib, NewString("Pointer"), 0, nullptr);
3729 Dart_Handle obj3 = Dart_Allocate(pointer_type);
3730 EXPECT_VALID(obj3);
3733 EXPECT_EQ(ref3, static_cast<void*>(nullptr));
3734
3735 // Subtype of Struct or Union object.
3736 const char* kScriptChars = R"(
3737 import 'dart:ffi';
3738
3739 final class MyStruct extends Struct {
3740 external Pointer notEmpty;
3741 }
3742
3743 final class MyUnion extends Union {
3744 external Pointer notEmpty;
3745 }
3746 )";
3747 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
3748
3749 Dart_Handle my_struct_type =
3750 Dart_GetNonNullableType(lib, NewString("MyStruct"), 0, nullptr);
3751 Dart_Handle obj4 = Dart_Allocate(my_struct_type);
3752 EXPECT_VALID(obj4);
3755 EXPECT_EQ(ref4, static_cast<void*>(nullptr));
3756
3757 Dart_Handle my_union_type =
3758 Dart_GetNonNullableType(lib, NewString("MyUnion"), 0, nullptr);
3759 Dart_Handle obj5 = Dart_Allocate(my_union_type);
3760 EXPECT_VALID(obj5);
3763 EXPECT_EQ(ref5, static_cast<void*>(nullptr));
3764
3766}
3767
3768TEST_CASE(DartAPI_FinalizableHandleErrors) {
3770
3771 // nullptr callback.
3772 Dart_Handle obj1 = NewString("new string");
3773 EXPECT_VALID(obj1);
3775 Dart_NewFinalizableHandle(obj1, nullptr, 0, nullptr);
3776 EXPECT_EQ(ref1, static_cast<void*>(nullptr));
3777
3778 // Immediate object.
3779 Dart_Handle obj2 = Dart_NewInteger(0);
3780 EXPECT_VALID(obj2);
3783 EXPECT_EQ(ref2, static_cast<void*>(nullptr));
3784
3785 // Pointer object.
3786 Dart_Handle ffi_lib = Dart_LookupLibrary(NewString("dart:ffi"));
3787 Dart_Handle pointer_type =
3788 Dart_GetNonNullableType(ffi_lib, NewString("Pointer"), 0, nullptr);
3789 Dart_Handle obj3 = Dart_Allocate(pointer_type);
3790 EXPECT_VALID(obj3);
3793 EXPECT_EQ(ref3, static_cast<void*>(nullptr));
3794
3795 // Subtype of Struct or Union object.
3796 const char* kScriptChars = R"(
3797 import 'dart:ffi';
3798
3799 final class MyStruct extends Struct {
3800 external Pointer notEmpty;
3801 }
3802
3803 final class MyUnion extends Union {
3804 external Pointer notEmpty;
3805 }
3806 )";
3807 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
3808
3809 Dart_Handle my_struct_type =
3810 Dart_GetNonNullableType(lib, NewString("MyStruct"), 0, nullptr);
3811 Dart_Handle obj4 = Dart_Allocate(my_struct_type);
3812 EXPECT_VALID(obj4);
3815 EXPECT_EQ(ref4, static_cast<void*>(nullptr));
3816
3817 Dart_Handle my_union_type =
3818 Dart_GetNonNullableType(lib, NewString("MyUnion"), 0, nullptr);
3819 Dart_Handle obj5 = Dart_Allocate(my_union_type);
3820 EXPECT_VALID(obj5);
3823 EXPECT_EQ(ref5, static_cast<void*>(nullptr));
3824
3826}
3827
3831
3833 void* isolate_callback_data,
3834 void* peer) {
3835 ASSERT(IsolateGroup::Current() != nullptr);
3836}
3837
3838TEST_CASE(DartAPI_WeakPersistentHandleCleanupFinalizerAtShutdown) {
3839 const char* kTestString1 = "Test String1";
3840 int peer3 = 0;
3842 CHECK_API_SCOPE(thread);
3843 Dart_Handle ref3 = Dart_NewStringFromCString(kTestString1);
3847}
3848
3850 void* isolate_callback_data,
3851 void* peer) {
3854 *static_cast<int*>(peer) = 42;
3855}
3856
3857TEST_CASE(DartAPI_WeakPersistentHandleCleanupFinalizer) {
3858 Heap* heap = IsolateGroup::Current()->heap();
3859
3860 const char* kTestString1 = "Test String1";
3862 CHECK_API_SCOPE(thread);
3863 Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
3865 Dart_Handle ref2 = Dart_NewStringFromCString(kTestString1);
3866 int peer2 = 0;
3868 Dart_NewWeakPersistentHandle(ref2, &peer2, 0, NopCallback);
3869 int peer3 = 0;
3870 {
3872 Dart_Handle ref3 = Dart_NewStringFromCString(kTestString1);
3876 }
3877 {
3878 TransitionNativeToVM transition(thread);
3880 EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
3881 EXPECT(peer3 == 42);
3882 }
3884
3886}
3887
3889
3890static void FinalizableHandlePeerCleanupFinalizer(void* isolate_callback_data,
3891 void* peer) {
3894 *static_cast<int*>(peer) = 42;
3895}
3896
3897TEST_CASE(DartAPI_FinalizableHandleCleanupFinalizer) {
3898 Heap* heap = IsolateGroup::Current()->heap();
3899
3900 const char* kTestString1 = "Test String1";
3902 CHECK_API_SCOPE(thread);
3903 Dart_Handle ref1 = Dart_NewStringFromCString(kTestString1);
3905 Dart_Handle ref2 = Dart_NewStringFromCString(kTestString1);
3906 int peer2 = 0;
3908 Dart_NewWeakPersistentHandle(ref2, &peer2, 0, NopCallback);
3909 int peer3 = 0;
3910 {
3912 Dart_Handle ref3 = Dart_NewStringFromCString(kTestString1);
3914 ref3, &peer3, 0, FinalizableHandlePeerCleanupFinalizer);
3916 }
3917 {
3918 TransitionNativeToVM transition(thread);
3920 EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
3921 EXPECT(peer3 == 42);
3922 }
3924}
3925
3926static void WeakPersistentHandlePeerFinalizer(void* isolate_callback_data,
3927 void* peer) {
3928 *static_cast<int*>(peer) = 42;
3929}
3930
3931TEST_CASE(DartAPI_WeakPersistentHandleCallback) {
3932 Dart_WeakPersistentHandle weak_ref = nullptr;
3933 int peer = 0;
3934 {
3936 Dart_Handle obj = NewString("new string");
3937 EXPECT_VALID(obj);
3938 weak_ref = Dart_NewWeakPersistentHandle(obj, &peer, 0,
3940 EXPECT_VALID(AsHandle(weak_ref));
3941 EXPECT(peer == 0);
3943 }
3944 {
3945 TransitionNativeToVM transition(thread);
3946 GCTestHelper::CollectNewSpace();
3947 EXPECT(peer == 42);
3948 }
3950}
3951
3952static void FinalizableHandlePeerFinalizer(void* isolate_callback_data,
3953 void* peer) {
3954 *static_cast<int*>(peer) = 42;
3955}
3956
3957TEST_CASE(DartAPI_FinalizableHandleCallback) {
3958 int peer = 0;
3959 {
3961 Dart_Handle obj = NewString("new string");
3962 EXPECT_VALID(obj);
3964 EXPECT(peer == 0);
3966 }
3967 {
3968 TransitionNativeToVM transition(thread);
3969 GCTestHelper::CollectNewSpace();
3970 EXPECT(peer == 42);
3971 }
3972}
3973
3974TEST_CASE(DartAPI_WeakPersistentHandleNoCallback) {
3975 Dart_WeakPersistentHandle weak_ref = nullptr;
3976 int peer = 0;
3977 {
3979 Dart_Handle obj = NewString("new string");
3980 EXPECT_VALID(obj);
3981 weak_ref = Dart_NewWeakPersistentHandle(obj, &peer, 0,
3984 }
3985 // A finalizer is not invoked on a deleted handle. Therefore, the
3986 // peer value should not change after the referent is collected.
3988 EXPECT(peer == 0);
3989 {
3990 TransitionNativeToVM transition(thread);
3991 GCTestHelper::CollectOldSpace();
3992 EXPECT(peer == 0);
3993 GCTestHelper::CollectNewSpace();
3994 EXPECT(peer == 0);
3995 }
3996}
3997
3998TEST_CASE(DartAPI_FinalizableHandleNoCallback) {
3999 Dart_FinalizableHandle weak_ref = nullptr;
4000 Dart_PersistentHandle strong_ref = nullptr;
4001 int peer = 0;
4002 {
4004 Dart_Handle obj = NewString("new string");
4005 EXPECT_VALID(obj);
4006 weak_ref = Dart_NewFinalizableHandle(obj, &peer, 0,
4008 strong_ref = Dart_NewPersistentHandle(obj);
4010 }
4011 // A finalizer is not invoked on a deleted handle. Therefore, the
4012 // peer value should not change after the referent is collected.
4013 Dart_DeleteFinalizableHandle(weak_ref, strong_ref);
4014 Dart_DeletePersistentHandle(strong_ref);
4015 EXPECT(peer == 0);
4016 {
4017 TransitionNativeToVM transition(thread);
4018 GCTestHelper::CollectOldSpace();
4019 EXPECT(peer == 0);
4020 GCTestHelper::CollectNewSpace();
4021 EXPECT(peer == 0);
4022 }
4023}
4024
4026
4027static void DeleteWeakHandleOnFinalization(void* isolate_callback_data,
4028 void* peer) {
4029 *static_cast<int*>(peer) = 42;
4031 delete_on_finalization = nullptr;
4032}
4033
4034static void DontDeleteWeakHandleOnFinalization(void* isolate_callback_data,
4035 void* peer) {
4036 *static_cast<int*>(peer) = 42;
4037 delete_on_finalization = nullptr;
4038}
4039
4040// Mimicking the old handle behavior by deleting the handle itself in the
4041// finalizer.
4042TEST_CASE(DartAPI_WeakPersistentHandleCallbackSelfDelete) {
4043 int peer = 0;
4044 {
4046 Dart_Handle obj = NewString("new string");
4047 EXPECT_VALID(obj);
4049 obj, &peer, 0, DeleteWeakHandleOnFinalization);
4051 EXPECT(peer == 0);
4053 }
4054 {
4055 TransitionNativeToVM transition(thread);
4056 GCTestHelper::CollectNewSpace();
4057 EXPECT(peer == 42);
4058 ASSERT(delete_on_finalization == nullptr);
4059 }
4060}
4061
4062// Checking that the finalizer gets run on shutdown, but that the delete
4063// handle does not get invoked. (The handles have already been deleted by
4064// releasing the LocalApiState.)
4065VM_UNIT_TEST_CASE(DartAPI_WeakPersistentHandlesCallbackShutdown) {
4068 Dart_Handle ref = Dart_True();
4069 int peer = 1234;
4071 ref, &peer, 0, DontDeleteWeakHandleOnFinalization);
4074 EXPECT(peer == 42);
4075}
4076
4077VM_UNIT_TEST_CASE(DartAPI_FinalizableHandlesCallbackShutdown) {
4080 Dart_Handle ref = Dart_True();
4081 int peer = 1234;
4085 EXPECT(peer == 42);
4086}
4087
4088TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSize) {
4089 Heap* heap = IsolateGroup::Current()->heap();
4090 EXPECT_EQ(heap->ExternalInWords(Heap::kNew), 0);
4091 EXPECT_EQ(heap->ExternalInWords(Heap::kOld), 0);
4093 const intptr_t kWeak1ExternalSize = 1 * KB;
4094 {
4096 Dart_Handle obj = NewString("weakly referenced string");
4097 EXPECT_VALID(obj);
4098 weak1 = Dart_NewWeakPersistentHandle(obj, nullptr, kWeak1ExternalSize,
4099 NopCallback);
4102 }
4103 Dart_PersistentHandle strong_ref = nullptr;
4105 const intptr_t kWeak2ExternalSize = 2 * KB;
4106 {
4108 Dart_Handle obj = NewString("strongly referenced string");
4109 EXPECT_VALID(obj);
4110 strong_ref = Dart_NewPersistentHandle(obj);
4111 weak2 = Dart_NewWeakPersistentHandle(obj, nullptr, kWeak2ExternalSize,
4112 NopCallback);
4113 EXPECT_VALID(AsHandle(strong_ref));
4116 }
4117 {
4118 TransitionNativeToVM transition(thread);
4119 EXPECT_EQ(heap->ExternalInWords(Heap::kNew),
4120 (kWeak1ExternalSize + kWeak2ExternalSize) / kWordSize);
4121 EXPECT_EQ(heap->ExternalInWords(Heap::kOld), 0);
4122 // Collect weakly referenced string.
4123 GCTestHelper::CollectNewSpace();
4124 EXPECT_EQ(heap->ExternalInWords(Heap::kNew),
4125 kWeak2ExternalSize / kWordSize);
4126 EXPECT_EQ(heap->ExternalInWords(Heap::kOld), 0);
4127 // Promote strongly referenced string.
4128 GCTestHelper::CollectNewSpace();
4129 EXPECT_EQ(heap->ExternalInWords(Heap::kNew), 0);
4130 EXPECT_EQ(heap->ExternalInWords(Heap::kOld),
4131 kWeak2ExternalSize / kWordSize);
4132 }
4133 Dart_DeletePersistentHandle(strong_ref);
4134 {
4135 TransitionNativeToVM transition(thread);
4136 GCTestHelper::CollectOldSpace();
4137 EXPECT_EQ(heap->ExternalInWords(Heap::kNew), 0);
4138 EXPECT_EQ(heap->ExternalInWords(Heap::kOld), 0);
4139 }
4142}
4143
4144TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSize) {
4145 Heap* heap = IsolateGroup::Current()->heap();
4146 EXPECT_EQ(heap->ExternalInWords(Heap::kNew), 0);
4147 EXPECT_EQ(heap->ExternalInWords(Heap::kOld), 0);
4148 const intptr_t kWeak1ExternalSize = 1 * KB;
4149 {
4151 Dart_Handle obj = NewString("weakly referenced string");
4152 EXPECT_VALID(obj);
4153 Dart_NewFinalizableHandle(obj, nullptr, kWeak1ExternalSize, NopCallback);
4155 }
4156 Dart_PersistentHandle strong_ref = nullptr;
4157 const intptr_t kWeak2ExternalSize = 2 * KB;
4158 {
4160 Dart_Handle obj = NewString("strongly referenced string");
4161 EXPECT_VALID(obj);
4162 strong_ref = Dart_NewPersistentHandle(obj);
4163 Dart_NewFinalizableHandle(obj, nullptr, kWeak2ExternalSize, NopCallback);
4164 EXPECT_VALID(AsHandle(strong_ref));
4166 }
4167 {
4168 TransitionNativeToVM transition(thread);
4169 EXPECT_EQ(heap->ExternalInWords(Heap::kNew),
4170 (kWeak1ExternalSize + kWeak2ExternalSize) / kWordSize);
4171 EXPECT_EQ(heap->ExternalInWords(Heap::kOld), 0);
4172 // Collect weakly referenced string.
4173 GCTestHelper::CollectNewSpace();
4174 EXPECT_EQ(heap->ExternalInWords(Heap::kNew),
4175 kWeak2ExternalSize / kWordSize);
4176 EXPECT_EQ(heap->ExternalInWords(Heap::kOld), 0);
4177 // Promote strongly referenced string.
4178 GCTestHelper::CollectNewSpace();
4179 EXPECT_EQ(heap->ExternalInWords(Heap::kNew), 0);
4180 EXPECT_EQ(heap->ExternalInWords(Heap::kOld),
4181 kWeak2ExternalSize / kWordSize);
4182 }
4183 Dart_DeletePersistentHandle(strong_ref);
4184 {
4185 TransitionNativeToVM transition(thread);
4186 GCTestHelper::CollectOldSpace();
4187 EXPECT_EQ(heap->ExternalInWords(Heap::kNew), 0);
4188 EXPECT_EQ(heap->ExternalInWords(Heap::kOld), 0);
4189 }
4190}
4191
4192TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSizeNewspaceGC) {
4193 Heap* heap = IsolateGroup::Current()->heap();
4195 // Large enough to exceed any new space limit. Not actually allocated.
4196 const intptr_t kWeak1ExternalSize = 500 * MB;
4197 {
4199 Dart_Handle obj = NewString("weakly referenced string");
4200 EXPECT_VALID(obj);
4201 // Triggers a scavenge immediately, since kWeak1ExternalSize is above limit.
4202 weak1 = Dart_NewWeakPersistentHandle(obj, nullptr, kWeak1ExternalSize,
4203 NopCallback);
4205 // ... but the object is still alive and not yet promoted, so external size
4206 // in new space is still above the limit. Thus, even the following tiny
4207 // external allocation will trigger another scavenge.
4209 Dart_NewWeakPersistentHandle(obj, nullptr, 1, NopCallback);
4210 EXPECT_VALID(AsHandle(trigger));
4212 // After the two scavenges above, 'obj' should now be promoted, hence its
4213 // external size charged to old space.
4214 {
4215 CHECK_API_SCOPE(thread);
4216 TransitionNativeToVM transition(thread);
4217 HANDLESCOPE(thread);
4218 String& handle = String::Handle(thread->zone());
4219 handle ^= Api::UnwrapHandle(obj);
4220 EXPECT(handle.IsOld());
4221 }
4222 EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
4223 EXPECT(heap->ExternalInWords(Heap::kOld) == kWeak1ExternalSize / kWordSize);
4225 }
4227 {
4228 TransitionNativeToVM transition(thread);
4229 GCTestHelper::CollectOldSpace();
4230 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
4231 }
4232}
4233
4234TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSizeNewspaceGC) {
4235 Heap* heap = IsolateGroup::Current()->heap();
4236 Dart_FinalizableHandle weak1 = nullptr;
4237 Dart_PersistentHandle strong1 = nullptr;
4238 // Large enough to exceed any new space limit. Not actually allocated.
4239 const intptr_t kWeak1ExternalSize = 500 * MB;
4240 {
4242 Dart_Handle obj = NewString("weakly referenced string");
4243 EXPECT_VALID(obj);
4244 // Triggers a scavenge immediately, since kWeak1ExternalSize is above limit.
4245 weak1 = Dart_NewFinalizableHandle(obj, nullptr, kWeak1ExternalSize,
4246 NopCallback);
4247 strong1 = Dart_NewPersistentHandle(obj);
4248 // ... but the object is still alive and not yet promoted, so external size
4249 // in new space is still above the limit. Thus, even the following tiny
4250 // external allocation will trigger another scavenge.
4251 Dart_FinalizableHandle trigger =
4252 Dart_NewFinalizableHandle(obj, nullptr, 1, NopCallback);
4253 Dart_DeleteFinalizableHandle(trigger, obj);
4254 // After the two scavenges above, 'obj' should now be promoted, hence its
4255 // external size charged to old space.
4256 {
4257 CHECK_API_SCOPE(thread);
4258 TransitionNativeToVM transition(thread);
4259 HANDLESCOPE(thread);
4260 String& handle = String::Handle(thread->zone());
4261 handle ^= Api::UnwrapHandle(obj);
4262 EXPECT(handle.IsOld());
4263 }
4264 EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
4265 EXPECT(heap->ExternalInWords(Heap::kOld) == kWeak1ExternalSize / kWordSize);
4267 }
4270 {
4271 TransitionNativeToVM transition(thread);
4272 GCTestHelper::CollectOldSpace();
4273 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
4274 }
4275}
4276
4277TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSizeOldspaceGC) {
4278 // Check that external allocation in old space can trigger GC.
4279 Heap* heap = IsolateGroup::Current()->heap();
4281 Dart_Handle live = AllocateOldString("live");
4282 EXPECT_VALID(live);
4283 Dart_WeakPersistentHandle weak = nullptr;
4284 {
4285 TransitionNativeToVM transition(thread);
4286 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
4287 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
4288 }
4289 const intptr_t kSmallExternalSize = 1 * KB;
4290 {
4292 Dart_Handle dead = AllocateOldString("dead");
4293 EXPECT_VALID(dead);
4294 weak = Dart_NewWeakPersistentHandle(dead, nullptr, kSmallExternalSize,
4295 NopCallback);
4296 EXPECT_VALID(AsHandle(weak));
4298 }
4299 {
4300 TransitionNativeToVM transition(thread);
4301 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
4302 EXPECT_EQ(kSmallExternalSize,
4304 }
4305 // Large enough to trigger GC in old space. Not actually allocated.
4306 const intptr_t kHugeExternalSize = (kWordSize == 4) ? 513 * MB : 1025 * MB;
4308 live, nullptr, kHugeExternalSize, NopCallback);
4309 {
4310 TransitionNativeToVM transition(thread);
4311 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
4312 // Expect small garbage to be collected.
4313 EXPECT_EQ(kHugeExternalSize, heap->ExternalInWords(Heap::kOld) * kWordSize);
4314 }
4318}
4319
4320TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSizeOldspaceGC) {
4321 // Check that external allocation in old space can trigger GC.
4322 Heap* heap = IsolateGroup::Current()->heap();
4324 Dart_Handle live = AllocateOldString("live");
4325 EXPECT_VALID(live);
4326 {
4327 TransitionNativeToVM transition(thread);
4328 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
4329 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
4330 }
4331 const intptr_t kSmallExternalSize = 1 * KB;
4332 {
4334 Dart_Handle dead = AllocateOldString("dead");
4335 EXPECT_VALID(dead);
4336 Dart_NewFinalizableHandle(dead, nullptr, kSmallExternalSize, NopCallback);
4338 }
4339 {
4340 TransitionNativeToVM transition(thread);
4341 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
4342 EXPECT_EQ(kSmallExternalSize,
4344 }
4345 // Large enough to trigger GC in old space. Not actually allocated.
4346 const intptr_t kHugeExternalSize = (kWordSize == 4) ? 513 * MB : 1025 * MB;
4347 Dart_NewFinalizableHandle(live, nullptr, kHugeExternalSize, NopCallback);
4348 {
4349 TransitionNativeToVM transition(thread);
4350 GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
4351 // Expect small garbage to be collected.
4352 EXPECT_EQ(kHugeExternalSize, heap->ExternalInWords(Heap::kOld) * kWordSize);
4353 }
4355}
4356
4357TEST_CASE(DartAPI_WeakPersistentHandleExternalAllocationSizeOddReferents) {
4358 Heap* heap = IsolateGroup::Current()->heap();
4360 const intptr_t kWeak1ExternalSize = 1 * KB;
4362 const intptr_t kWeak2ExternalSize = 2 * KB;
4363 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
4364 {
4366 Dart_Handle dart_true = Dart_True(); // VM heap object.
4367 EXPECT_VALID(dart_true);
4368 weak1 = Dart_NewWeakPersistentHandle(dart_true, nullptr, kWeak1ExternalSize,
4371 Dart_Handle zero = Dart_False(); // VM heap object.
4372 EXPECT_VALID(zero);
4373 weak2 = Dart_NewWeakPersistentHandle(zero, nullptr, kWeak2ExternalSize,
4376 // Both should be charged to old space.
4378 (kWeak1ExternalSize + kWeak2ExternalSize) / kWordSize);
4380 }
4383 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
4384 {
4385 TransitionNativeToVM transition(thread);
4386 GCTestHelper::CollectOldSpace();
4387 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
4388 }
4389}
4390
4391TEST_CASE(DartAPI_FinalizableHandleExternalAllocationSizeOddReferents) {
4392 Heap* heap = IsolateGroup::Current()->heap();
4393 Dart_FinalizableHandle weak1 = nullptr;
4394 Dart_PersistentHandle strong1 = nullptr;
4395 const intptr_t kWeak1ExternalSize = 1 * KB;
4396 Dart_FinalizableHandle weak2 = nullptr;
4397 Dart_PersistentHandle strong2 = nullptr;
4398 const intptr_t kWeak2ExternalSize = 2 * KB;
4399 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
4400 {
4402 Dart_Handle dart_true = Dart_True(); // VM heap object.
4403 EXPECT_VALID(dart_true);
4404 weak1 = Dart_NewFinalizableHandle(dart_true, nullptr, kWeak1ExternalSize,
4406 strong1 = Dart_NewPersistentHandle(dart_true);
4407 Dart_Handle zero = Dart_False(); // VM heap object.
4408 EXPECT_VALID(zero);
4409 weak2 = Dart_NewFinalizableHandle(zero, nullptr, kWeak2ExternalSize,
4411 strong2 = Dart_NewPersistentHandle(zero);
4412 // Both should be charged to old space.
4414 (kWeak1ExternalSize + kWeak2ExternalSize) / kWordSize);
4416 }
4421 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
4422 {
4423 TransitionNativeToVM transition(thread);
4424 GCTestHelper::CollectOldSpace();
4425 EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
4426 }
4427}
4428
4430 Dart_Handle receiver = Dart_GetNativeArgument(native_args, 0);
4431 int64_t secret = 0;
4432 Dart_GetNativeIntegerArgument(native_args, 1, &secret);
4433 EXPECT_VALID(Dart_SetNativeInstanceField(receiver, 0, secret));
4434}
4435
4437 int argument_count,
4438 bool* auto_setup_scope) {
4439 return reinterpret_cast<Dart_NativeFunction>(Builtin_SecretKeeper_KeepSecret);
4440}
4441
4442static intptr_t ReturnPtrAsInt(void* ptr) {
4443 return reinterpret_cast<intptr_t>(ptr);
4444}
4445
4446static void* SecretKeeperFfiNativeResolver(const char* name, uintptr_t argn) {
4447 if (strcmp(name, "returnPtrAsInt") == 0 && argn == 1) {
4448 return reinterpret_cast<void*>(&ReturnPtrAsInt);
4449 }
4450 return nullptr;
4451}
4452
4453TEST_CASE(DartAPI_NativeFieldAccess) {
4454 const char* kScriptChars = R"(
4455 import 'dart:ffi';
4456 import 'dart:nativewrappers';
4457 base class SecretKeeper extends NativeFieldWrapperClass1 {
4458 SecretKeeper(int secret) { _keepSecret(secret); }
4459 @pragma("vm:external-name", "SecretKeeper_KeepSecret")
4460 external void _keepSecret(int secret);
4461 }
4462 // Argument auto-conversion will wrap `o` in `_getNativeField()`.
4463 @Native<IntPtr Function(Pointer<Void>)>(symbol: 'returnPtrAsInt')
4464 external int returnPtrAsInt(NativeFieldWrapperClass1 o);
4465 main() => returnPtrAsInt(SecretKeeper(321));
4466 )";
4467
4469 Dart_Handle lib =
4471
4474
4475 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
4476
4479 int64_t value = 0;
4482 EXPECT_EQ(321, value);
4483}
4484
4485// Test that trying to access an unset native field (internally through
4486// _getNativeField(..)) will result in a Dart exception (and not crash).
4487TEST_CASE(DartAPI_NativeFieldAccess_Throws) {
4488 const char* kScriptChars = R"(
4489 import 'dart:ffi';
4490 import 'dart:nativewrappers';
4491 base class ForgetfulSecretKeeper extends NativeFieldWrapperClass1 {
4492 ForgetfulSecretKeeper(int secret) { /* Forget to init. native field. */ }
4493 }
4494 // Argument auto-conversion will wrap `o` in `_getNativeField()`.
4495 @Native<IntPtr Function(Pointer<Void>)>(symbol: 'returnPtrAsInt')
4496 external int returnPtrAsInt(NativeFieldWrapperClass1 o);
4497 main() => returnPtrAsInt(ForgetfulSecretKeeper(321));
4498 )";
4499
4501 Dart_Handle lib =
4503
4506
4507 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
4508
4511}
4512
4516
4517static void ImplicitReferencesCallback(void* isolate_callback_data,
4518 void* peer) {
4519 if (peer == &weak1) {
4520 weak1 = nullptr;
4521 } else if (peer == &weak2) {
4522 weak2 = nullptr;
4523 } else if (peer == &weak3) {
4524 weak3 = nullptr;
4525 }
4526}
4527
4528TEST_CASE(DartAPI_ImplicitReferencesOldSpace) {
4529 Dart_PersistentHandle strong = nullptr;
4530 Dart_WeakPersistentHandle strong_weak = nullptr;
4531
4533 {
4534 CHECK_API_SCOPE(thread);
4535
4536 Dart_Handle local = AllocateOldString("strongly reachable");
4538 strong_weak = Dart_NewWeakPersistentHandle(local, nullptr, 0, NopCallback);
4539
4540 EXPECT(!Dart_IsNull(AsHandle(strong)));
4541 EXPECT_VALID(AsHandle(strong));
4542 EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
4543 EXPECT_VALID(AsHandle(strong_weak));
4544 EXPECT(Dart_IdentityEquals(AsHandle(strong), AsHandle(strong_weak)))
4545
4546 weak1 =
4547 Dart_NewWeakPersistentHandle(AllocateOldString("weakly reachable 1"),
4551
4552 weak2 =
4553 Dart_NewWeakPersistentHandle(AllocateOldString("weakly reachable 2"),
4557
4558 weak3 =
4559 Dart_NewWeakPersistentHandle(AllocateOldString("weakly reachable 3"),
4563 }
4565
4566 {
4568 EXPECT_VALID(AsHandle(strong_weak));
4573 }
4574
4575 {
4576 TransitionNativeToVM transition(thread);
4577 GCTestHelper::CollectNewSpace();
4578 }
4579
4580 {
4582 // New space collection should not affect old space objects
4583 EXPECT_VALID(AsHandle(strong_weak));
4588 }
4589
4594}
4595
4596TEST_CASE(DartAPI_ImplicitReferencesNewSpace) {
4597 Dart_PersistentHandle strong = nullptr;
4598 Dart_WeakPersistentHandle strong_weak = nullptr;
4599
4601 {
4602 CHECK_API_SCOPE(thread);
4603
4604 Dart_Handle local = AllocateOldString("strongly reachable");
4606 strong_weak = Dart_NewWeakPersistentHandle(local, nullptr, 0, NopCallback);
4607
4608 EXPECT(!Dart_IsNull(AsHandle(strong)));
4609 EXPECT_VALID(AsHandle(strong));
4610 EXPECT(!Dart_IsNull(AsHandle(strong_weak)));
4611 EXPECT_VALID(AsHandle(strong_weak));
4612 EXPECT(Dart_IdentityEquals(AsHandle(strong), AsHandle(strong_weak)))
4613
4614 weak1 =
4615 Dart_NewWeakPersistentHandle(AllocateNewString("weakly reachable 1"),
4619
4620 weak2 =
4621 Dart_NewWeakPersistentHandle(AllocateNewString("weakly reachable 2"),
4625
4626 weak3 =
4627 Dart_NewWeakPersistentHandle(AllocateNewString("weakly reachable 3"),
4631 }
4633
4634 {
4636 EXPECT_VALID(AsHandle(strong_weak));
4641 }
4642
4647}
4648
4649// Unit test for creating multiple scopes and local handles within them.
4650// Ensure that the local handles get all cleaned out when exiting the
4651// scope.
4652VM_UNIT_TEST_CASE(DartAPI_LocalHandles) {
4654 Thread* thread = Thread::Current();
4655 Isolate* isolate = thread->isolate();
4656 EXPECT(isolate != nullptr);
4657 ApiLocalScope* scope = thread->api_top_scope();
4658 Dart_Handle handles[300];
4659 {
4660 TransitionNativeToVM transition1(thread);
4661 StackZone zone(thread);
4662 Smi& val = Smi::Handle();
4663 TransitionVMToNative transition2(thread);
4664
4665 // Start a new scope and allocate some local handles.
4667 {
4668 TransitionNativeToVM transition3(thread);
4669 for (int i = 0; i < 100; i++) {
4670 handles[i] = Api::NewHandle(thread, Smi::New(i));
4671 }
4672 EXPECT_EQ(100, thread->CountLocalHandles());
4673 for (int i = 0; i < 100; i++) {
4674 val ^= Api::UnwrapHandle(handles[i]);
4675 EXPECT_EQ(i, val.Value());
4676 }
4677 }
4678 // Start another scope and allocate some more local handles.
4679 {
4681 {
4682 TransitionNativeToVM transition3(thread);
4683 for (int i = 100; i < 200; i++) {
4684 handles[i] = Api::NewHandle(thread, Smi::New(i));
4685 }
4686 EXPECT_EQ(200, thread->CountLocalHandles());
4687 for (int i = 100; i < 200; i++) {
4688 val ^= Api::UnwrapHandle(handles[i]);
4689 EXPECT_EQ(i, val.Value());
4690 }
4691 }
4692
4693 // Start another scope and allocate some more local handles.
4694 {
4696 {
4697 TransitionNativeToVM transition3(thread);
4698 for (int i = 200; i < 300; i++) {
4699 handles[i] = Api::NewHandle(thread, Smi::New(i));
4700 }
4701 EXPECT_EQ(300, thread->CountLocalHandles());
4702 for (int i = 200; i < 300; i++) {
4703 val ^= Api::UnwrapHandle(handles[i]);
4704 EXPECT_EQ(i, val.Value());
4705 }
4706 EXPECT_EQ(300, thread->CountLocalHandles());
4707 }
4709 }
4710 EXPECT_EQ(200, thread->CountLocalHandles());
4712 }
4713 EXPECT_EQ(100, thread->CountLocalHandles());
4715 }
4716 EXPECT_EQ(0, thread->CountLocalHandles());
4717 EXPECT(scope == thread->api_top_scope());
4719}
4720
4721// Unit test for creating multiple scopes and allocating objects in the
4722// zone for the scope. Ensure that the memory is freed when the scope
4723// exits.
4724VM_UNIT_TEST_CASE(DartAPI_LocalZoneMemory) {
4726 Thread* thread = Thread::Current();
4727 EXPECT(thread != nullptr);
4728 ApiLocalScope* scope = thread->api_top_scope();
4729 EXPECT_EQ(0, thread->ZoneSizeInBytes());
4730 {
4731 // Start a new scope and allocate some memory.
4733 EXPECT_EQ(0, thread->ZoneSizeInBytes());
4734 for (int i = 0; i < 100; i++) {
4736 }
4737 EXPECT_EQ(1600, thread->ZoneSizeInBytes());
4738 // Start another scope and allocate some more memory.
4739 {
4741 for (int i = 0; i < 100; i++) {
4743 }
4744 EXPECT_EQ(3200, thread->ZoneSizeInBytes());
4745 {
4746 // Start another scope and allocate some more memory.
4747 {
4749 for (int i = 0; i < 200; i++) {
4751 }
4752 EXPECT_EQ(6400, thread->ZoneSizeInBytes());
4754 }
4755 }
4756 EXPECT_EQ(3200, thread->ZoneSizeInBytes());
4758 }
4759 EXPECT_EQ(1600, thread->ZoneSizeInBytes());
4761 }
4762 EXPECT_EQ(0, thread->ZoneSizeInBytes());
4763 EXPECT(scope == thread->api_top_scope());
4765}
4766
4767VM_UNIT_TEST_CASE(DartAPI_Isolates) {
4768 // This test currently assumes that the Dart_Isolate type is an opaque
4769 // representation of Isolate*.
4771 EXPECT_EQ(iso_1, Api::CastIsolate(Isolate::Current()));
4773 EXPECT_EQ(iso_1, isolate);
4775 EXPECT_NULLPTR(Dart_CurrentIsolate());
4777 EXPECT_EQ(iso_2, Dart_CurrentIsolate());
4779 EXPECT_NULLPTR(Dart_CurrentIsolate());
4780 Dart_EnterIsolate(iso_2);
4781 EXPECT_EQ(iso_2, Dart_CurrentIsolate());
4783 EXPECT_NULLPTR(Dart_CurrentIsolate());
4784 Dart_EnterIsolate(iso_1);
4785 EXPECT_EQ(iso_1, Dart_CurrentIsolate());
4787 EXPECT_NULLPTR(Dart_CurrentIsolate());
4788}
4789
4790VM_UNIT_TEST_CASE(DartAPI_IsolateGroups) {
4792 EXPECT_NOTNULL(Dart_CurrentIsolateGroup());
4794 EXPECT_NULLPTR(Dart_CurrentIsolateGroup());
4796 EXPECT_NOTNULL(Dart_CurrentIsolateGroup());
4798 EXPECT_NULLPTR(Dart_CurrentIsolateGroup());
4799 Dart_EnterIsolate(iso_2);
4800 EXPECT_NOTNULL(Dart_CurrentIsolateGroup());
4802 EXPECT_NULLPTR(Dart_CurrentIsolateGroup());
4803 Dart_EnterIsolate(iso_1);
4804 EXPECT_NOTNULL(Dart_CurrentIsolateGroup());
4806 EXPECT_NULLPTR(Dart_CurrentIsolateGroup());
4807}
4808
4809VM_UNIT_TEST_CASE(DartAPI_CurrentIsolateData) {
4811 Dart_IsolateGroupCleanupCallback saved_cleanup =
4815
4816 intptr_t mydata = 12345;
4817 Dart_Isolate isolate =
4818 TestCase::CreateTestIsolate(nullptr, reinterpret_cast<void*>(mydata));
4819 EXPECT(isolate != nullptr);
4820 EXPECT_EQ(mydata, reinterpret_cast<intptr_t>(Dart_CurrentIsolateGroupData()));
4821 EXPECT_EQ(mydata, reinterpret_cast<intptr_t>(Dart_IsolateGroupData(isolate)));
4823
4824 Isolate::SetShutdownCallback(saved_shutdown);
4825 Isolate::SetGroupCleanupCallback(saved_cleanup);
4826}
4827
4828static Dart_Handle LoadScript(const char* url_str, const char* source) {
4829 const uint8_t* kernel_buffer = nullptr;
4830 intptr_t kernel_buffer_size = 0;
4832 url_str, source, &kernel_buffer, &kernel_buffer_size);
4833 if (error != nullptr) {
4834 return Dart_NewApiError(error);
4835 }
4836 TestCaseBase::AddToKernelBuffers(kernel_buffer);
4837 return Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
4838}
4839
4840TEST_CASE(DartAPI_DebugName) {
4841 Dart_Handle debug_name = Dart_DebugName();
4842 EXPECT_VALID(debug_name);
4843 EXPECT(Dart_IsString(debug_name));
4844}
4845
4846TEST_CASE(DartAPI_IsolateServiceID) {
4848 const char* id = Dart_IsolateServiceId(isolate);
4849 EXPECT(id != nullptr);
4850 int64_t main_port = Dart_GetMainPortId();
4851 EXPECT_STREQ(ZONE_STR("isolates/%" Pd64, main_port), id);
4852 free(const_cast<char*>(id));
4853}
4854
4855static void MyMessageNotifyCallback(Dart_Isolate dest_isolate) {}
4856
4857VM_UNIT_TEST_CASE(DartAPI_SetMessageCallbacks) {
4860 Isolate* isolate = reinterpret_cast<Isolate*>(dart_isolate);
4861 EXPECT_EQ(&MyMessageNotifyCallback, isolate->message_notify_callback());
4863}
4864
4865TEST_CASE(DartAPI_SetStickyError) {
4866 const char* kScriptChars = "main() => throw 'HI';";
4867 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
4868 Dart_Handle retobj = Dart_Invoke(lib, NewString("main"), 0, nullptr);
4869 EXPECT(Dart_IsError(retobj));
4873 Dart_SetStickyError(retobj);
4879}
4880
4881TEST_CASE(DartAPI_TypeGetNonParametricTypes) {
4882 const char* kScriptChars =
4883 "class MyClass0 {\n"
4884 "}\n"
4885 "\n"
4886 "class MyClass1 implements MyInterface1 {\n"
4887 "}\n"
4888 "\n"
4889 "class MyClass2 implements MyInterface0, MyInterface1 {\n"
4890 "}\n"
4891 "\n"
4892 "abstract class MyInterface0 {\n"
4893 "}\n"
4894 "\n"
4895 "abstract class MyInterface1 implements MyInterface0 {\n"
4896 "}\n"
4897 "MyClass0 getMyClass0() { return new MyClass0(); }\n"
4898 "MyClass1 getMyClass1() { return new MyClass1(); }\n"
4899 "MyClass2 getMyClass2() { return new MyClass2(); }\n"
4900 "Type getMyClass0Type() { return new MyClass0().runtimeType; }\n"
4901 "Type getMyClass1Type() { return new MyClass1().runtimeType; }\n"
4902 "Type getMyClass2Type() { return new MyClass2().runtimeType; }\n";
4903 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
4904 bool instanceOf = false;
4905
4906 // First get the type objects of these non parameterized types.
4907 Dart_Handle type0 =
4908 Dart_GetNonNullableType(lib, NewString("MyClass0"), 0, nullptr);
4909 EXPECT_VALID(type0);
4910 Dart_Handle type1 =
4911 Dart_GetNonNullableType(lib, NewString("MyClass1"), 0, nullptr);
4912 EXPECT_VALID(type1);
4913 Dart_Handle type2 =
4914 Dart_GetNonNullableType(lib, NewString("MyClass2"), 0, nullptr);
4915 EXPECT_VALID(type2);
4916 Dart_Handle type3 =
4917 Dart_GetNonNullableType(lib, NewString("MyInterface0"), 0, nullptr);
4918 EXPECT_VALID(type3);
4919 Dart_Handle type4 =
4920 Dart_GetNonNullableType(lib, NewString("MyInterface1"), 0, nullptr);
4921 EXPECT_VALID(type4);
4922
4923 // Now create objects of these non parameterized types and check
4924 // that the validity of the type of the created object.
4925 // MyClass0 type.
4926 Dart_Handle type0_obj =
4927 Dart_Invoke(lib, NewString("getMyClass0"), 0, nullptr);
4928 EXPECT_VALID(type0_obj);
4929 EXPECT_VALID(Dart_ObjectIsType(type0_obj, type0, &instanceOf));
4930 EXPECT(instanceOf);
4931 EXPECT_VALID(Dart_ObjectIsType(type0_obj, type1, &instanceOf));
4932 EXPECT(!instanceOf);
4933 EXPECT_VALID(Dart_ObjectIsType(type0_obj, type2, &instanceOf));
4934 EXPECT(!instanceOf);
4935 EXPECT_VALID(Dart_ObjectIsType(type0_obj, type3, &instanceOf));
4936 EXPECT(!instanceOf);
4937 EXPECT_VALID(Dart_ObjectIsType(type0_obj, type4, &instanceOf));
4938 EXPECT(!instanceOf);
4939 type0_obj = Dart_Invoke(lib, NewString("getMyClass0Type"), 0, nullptr);
4940 EXPECT_VALID(type0_obj);
4941 EXPECT(Dart_IdentityEquals(type0, type0_obj));
4942
4943 // MyClass1 type.
4944 Dart_Handle type1_obj =
4945 Dart_Invoke(lib, NewString("getMyClass1"), 0, nullptr);
4946 EXPECT_VALID(type1_obj);
4947 EXPECT_VALID(Dart_ObjectIsType(type1_obj, type1, &instanceOf));
4948 EXPECT(instanceOf);
4949 EXPECT_VALID(Dart_ObjectIsType(type1_obj, type0, &instanceOf));
4950 EXPECT(!instanceOf);
4951 EXPECT_VALID(Dart_ObjectIsType(type1_obj, type2, &instanceOf));
4952 EXPECT(!instanceOf);
4953 EXPECT_VALID(Dart_ObjectIsType(type1_obj, type3, &instanceOf));
4954 EXPECT(instanceOf);
4955 EXPECT_VALID(Dart_ObjectIsType(type1_obj, type4, &instanceOf));
4956 EXPECT(instanceOf);
4957 type1_obj = Dart_Invoke(lib, NewString("getMyClass1Type"), 0, nullptr);
4958 EXPECT_VALID(type1_obj);
4959 EXPECT(Dart_IdentityEquals(type1, type1_obj));
4960
4961 // MyClass2 type.
4962 Dart_Handle type2_obj =
4963 Dart_Invoke(lib, NewString("getMyClass2"), 0, nullptr);
4964 EXPECT_VALID(type2_obj);
4965 EXPECT_VALID(Dart_ObjectIsType(type2_obj, type2, &instanceOf));
4966 EXPECT(instanceOf);
4967 EXPECT_VALID(Dart_ObjectIsType(type2_obj, type0, &instanceOf));
4968 EXPECT(!instanceOf);
4969 EXPECT_VALID(Dart_ObjectIsType(type2_obj, type1, &instanceOf));
4970 EXPECT(!instanceOf);
4971 EXPECT_VALID(Dart_ObjectIsType(type2_obj, type3, &instanceOf));
4972 EXPECT(instanceOf);
4973 EXPECT_VALID(Dart_ObjectIsType(type2_obj, type4, &instanceOf));
4974 EXPECT(instanceOf);
4975 type2_obj = Dart_Invoke(lib, NewString("getMyClass2Type"), 0, nullptr);
4976 EXPECT_VALID(type2_obj);
4977 EXPECT(Dart_IdentityEquals(type2, type2_obj));
4978}
4979
4980TEST_CASE(DartAPI_TypeGetParameterizedTypes) {
4981 const char* kScriptChars =
4982 "class MyClass0<A, B> {\n"
4983 "}\n"
4984 "\n"
4985 "class MyClass1<A, C> {\n"
4986 "}\n"
4987 "Type type<T>() => T;"
4988 "MyClass0 getMyClass0() {\n"
4989 " return new MyClass0<int, double>();\n"
4990 "}\n"
4991 "Type getMyClass0Type() {\n"
4992 " return type<MyClass0<int, double>>();\n"
4993 "}\n"
4994 "MyClass1 getMyClass1() {\n"
4995 " return new MyClass1<List<int>, List>();\n"
4996 "}\n"
4997 "Type getMyClass1Type() {\n"
4998 " return type<MyClass1<List<int>, List>>();\n"
4999 "}\n"
5000 "MyClass0 getMyClass0_1() {\n"
5001 " return new MyClass0<double, int>();\n"
5002 "}\n"
5003 "Type getMyClass0_1Type() {\n"
5004 " return type<MyClass0<double, int>>();\n"
5005 "}\n"
5006 "MyClass1 getMyClass1_1() {\n"
5007 " return new MyClass1<List<int>, List<double>>();\n"
5008 "}\n"
5009 "Type getMyClass1_1Type() {\n"
5010 " return type<MyClass1<List<int>, List<double>>>();\n"
5011 "}\n"
5012 "Type getIntType() { return int; }\n"
5013 "Type getDoubleType() { return double; }\n"
5014 "Type getListIntType() { return type<List<int>>(); }\n"
5015 "Type getListType() { return List; }\n";
5016
5017 Dart_Handle corelib = Dart_LookupLibrary(NewString("dart:core"));
5018 EXPECT_VALID(corelib);
5019
5020 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5021
5022 // Now instantiate MyClass0 and MyClass1 types with the same type arguments
5023 // used in the code above.
5024 Dart_Handle type_args = Dart_NewList(2);
5025 Dart_Handle int_type = Dart_Invoke(lib, NewString("getIntType"), 0, nullptr);
5026 EXPECT_VALID(int_type);
5027 EXPECT_VALID(Dart_ListSetAt(type_args, 0, int_type));
5028 Dart_Handle double_type =
5029 Dart_Invoke(lib, NewString("getDoubleType"), 0, nullptr);
5030 EXPECT_VALID(double_type);
5031 EXPECT_VALID(Dart_ListSetAt(type_args, 1, double_type));
5032 Dart_Handle myclass0_type =
5033 Dart_GetNonNullableType(lib, NewString("MyClass0"), 2, &type_args);
5034 EXPECT_VALID(myclass0_type);
5035
5036 type_args = Dart_NewList(2);
5037 Dart_Handle list_int_type =
5038 Dart_Invoke(lib, NewString("getListIntType"), 0, nullptr);
5039 EXPECT_VALID(list_int_type);
5040 EXPECT_VALID(Dart_ListSetAt(type_args, 0, list_int_type));
5041 Dart_Handle list_type =
5042 Dart_Invoke(lib, NewString("getListType"), 0, nullptr);
5043 EXPECT_VALID(list_type);
5044 EXPECT_VALID(Dart_ListSetAt(type_args, 1, list_type));
5045 Dart_Handle myclass1_type =
5046 Dart_GetNonNullableType(lib, NewString("MyClass1"), 2, &type_args);
5047 EXPECT_VALID(myclass1_type);
5048
5049 // Now create objects of the type and validate the object type matches
5050 // the one returned above. Also get the runtime type of the object and
5051 // verify that it matches the type returned above. Note: we use
5052 // Dart_ObjectEquals instead of Dart_IdentityEquals since we are comparing
5053 // type literals with non-literals which would fail in unsound null safety
5054 // mode.
5055 // MyClass0<int, double> type.
5056 Dart_Handle type0_obj =
5057 Dart_Invoke(lib, NewString("getMyClass0"), 0, nullptr);
5058 EXPECT_VALID(type0_obj);
5059 bool instanceOf = false;
5060 EXPECT_VALID(Dart_ObjectIsType(type0_obj, myclass0_type, &instanceOf));
5061 EXPECT(instanceOf);
5062 type0_obj = Dart_Invoke(lib, NewString("getMyClass0Type"), 0, nullptr);
5063 EXPECT_VALID(type0_obj);
5064
5065 bool equal = false;
5066 EXPECT_VALID(Dart_ObjectEquals(type0_obj, myclass0_type, &equal));
5067 EXPECT(equal);
5068
5069 // MyClass1<List<int>, List> type.
5070 Dart_Handle type1_obj =
5071 Dart_Invoke(lib, NewString("getMyClass1"), 0, nullptr);
5072 EXPECT_VALID(type1_obj);
5073 EXPECT_VALID(Dart_ObjectIsType(type1_obj, myclass1_type, &instanceOf));
5074 EXPECT(instanceOf);
5075 type1_obj = Dart_Invoke(lib, NewString("getMyClass1Type"), 0, nullptr);
5076 EXPECT_VALID(type1_obj);
5077
5078 EXPECT_VALID(Dart_ObjectEquals(type1_obj, myclass1_type, &equal));
5079 EXPECT(equal);
5080
5081 // MyClass0<double, int> type.
5082 type0_obj = Dart_Invoke(lib, NewString("getMyClass0_1"), 0, nullptr);
5083 EXPECT_VALID(type0_obj);
5084 EXPECT_VALID(Dart_ObjectIsType(type0_obj, myclass0_type, &instanceOf));
5085 EXPECT(!instanceOf);
5086 type0_obj = Dart_Invoke(lib, NewString("getMyClass0_1Type"), 0, nullptr);
5087 EXPECT_VALID(type0_obj);
5088 EXPECT_VALID(Dart_ObjectEquals(type0_obj, myclass0_type, &equal));
5089 EXPECT(!equal);
5090
5091 // MyClass1<List<int>, List<double>> type.
5092 type1_obj = Dart_Invoke(lib, NewString("getMyClass1_1"), 0, nullptr);
5093 EXPECT_VALID(type1_obj);
5094 EXPECT_VALID(Dart_ObjectIsType(type1_obj, myclass1_type, &instanceOf));
5095 EXPECT(instanceOf);
5096 type1_obj = Dart_Invoke(lib, NewString("getMyClass1_1Type"), 0, nullptr);
5097 EXPECT_VALID(type1_obj);
5098 EXPECT_VALID(Dart_ObjectEquals(type1_obj, myclass1_type, &equal));
5099 EXPECT(!equal);
5100}
5101
5102static void TestFieldOk(Dart_Handle container,
5104 bool final,
5105 const char* initial_value) {
5107
5108 // Make sure we have the right initial value.
5109 result = Dart_GetField(container, name);
5111 const char* value = "";
5113 EXPECT_STREQ(initial_value, value);
5114
5115 // Use a unique expected value.
5116 static int counter = 0;
5117 char buffer[256];
5118 Utils::SNPrint(buffer, 256, "Expected%d", ++counter);
5119
5120 // Try to change the field value.
5121 result = Dart_SetField(container, name, NewString(buffer));
5122 if (final) {
5124 } else {
5126 }
5127
5128 // Make sure we have the right final value.
5129 result = Dart_GetField(container, name);
5132 if (final) {
5133 EXPECT_STREQ(initial_value, value);
5134 } else {
5135 EXPECT_STREQ(buffer, value);
5136 }
5137}
5138
5140 EXPECT_ERROR(Dart_GetField(container, name), "NoSuchMethodError");
5142 "NoSuchMethodError");
5143}
5144
5145TEST_CASE(DartAPI_FieldAccess) {
5146 const char* kScriptChars =
5147 "class BaseFields {\n"
5148 " BaseFields()\n"
5149 " : this.inherited_fld = 'inherited' {\n"
5150 " }\n"
5151 " var inherited_fld;\n"
5152 " static var non_inherited_fld;\n"
5153 "}\n"
5154 "\n"
5155 "class Fields extends BaseFields {\n"
5156 " Fields()\n"
5157 " : this.instance_fld = 'instance',\n"
5158 " this._instance_fld = 'hidden instance',\n"
5159 " this.final_instance_fld = 'final instance',\n"
5160 " this._final_instance_fld = 'hidden final instance' {\n"
5161 " instance_getset_fld = 'instance getset';\n"
5162 " _instance_getset_fld = 'hidden instance getset';\n"
5163 " }\n"
5164 "\n"
5165 " static Init() {\n"
5166 " static_fld = 'static';\n"
5167 " _static_fld = 'hidden static';\n"
5168 " static_getset_fld = 'static getset';\n"
5169 " _static_getset_fld = 'hidden static getset';\n"
5170 " }\n"
5171 "\n"
5172 " var instance_fld;\n"
5173 " var _instance_fld;\n"
5174 " final final_instance_fld;\n"
5175 " final _final_instance_fld;\n"
5176 " static var static_fld;\n"
5177 " static var _static_fld;\n"
5178 " static const const_static_fld = 'const static';\n"
5179 " static const _const_static_fld = 'hidden const static';\n"
5180 "\n"
5181 " get instance_getset_fld { return _gs_fld1; }\n"
5182 " void set instance_getset_fld(var value) { _gs_fld1 = value; }\n"
5183 " get _instance_getset_fld { return _gs_fld2; }\n"
5184 " void set _instance_getset_fld(var value) { _gs_fld2 = value; }\n"
5185 " var _gs_fld1;\n"
5186 " var _gs_fld2;\n"
5187 "\n"
5188 " static get static_getset_fld { return _gs_fld3; }\n"
5189 " static void set static_getset_fld(var value) { _gs_fld3 = value; }\n"
5190 " static get _static_getset_fld { return _gs_fld4; }\n"
5191 " static void set _static_getset_fld(var value) { _gs_fld4 = value; }\n"
5192 " static var _gs_fld3;\n"
5193 " static var _gs_fld4;\n"
5194 "}\n"
5195 "var top_fld;\n"
5196 "var _top_fld;\n"
5197 "const const_top_fld = 'const top';\n"
5198 "const _const_top_fld = 'hidden const top';\n"
5199 "\n"
5200 "get top_getset_fld { return _gs_fld5; }\n"
5201 "void set top_getset_fld(var value) { _gs_fld5 = value; }\n"
5202 "get _top_getset_fld { return _gs_fld6; }\n"
5203 "void set _top_getset_fld(var value) { _gs_fld6 = value; }\n"
5204 "var _gs_fld5;\n"
5205 "var _gs_fld6;\n"
5206 "\n"
5207 "Fields test() {\n"
5208 " Fields.Init();\n"
5209 " top_fld = 'top';\n"
5210 " _top_fld = 'hidden top';\n"
5211 " top_getset_fld = 'top getset';\n"
5212 " _top_getset_fld = 'hidden top getset';\n"
5213 " return new Fields();\n"
5214 "}\n";
5215 const char* kImportedScriptChars =
5216 "library library_name;\n"
5217 "var imported_fld = 'imported';\n"
5218 "var _imported_fld = 'hidden imported';\n"
5219 "get imported_getset_fld { return _gs_fld1; }\n"
5220 "void set imported_getset_fld(var value) { _gs_fld1 = value; }\n"
5221 "get _imported_getset_fld { return _gs_fld2; }\n"
5222 "void set _imported_getset_fld(var value) { _gs_fld2 = value; }\n"
5223 "var _gs_fld1;\n"
5224 "var _gs_fld2;\n"
5225 "void test2() {\n"
5226 " imported_getset_fld = 'imported getset';\n"
5227 " _imported_getset_fld = 'hidden imported getset';\n"
5228 "}\n";
5229
5230 // Shared setup.
5231 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5233 Dart_GetNonNullableType(lib, NewString("Fields"), 0, nullptr);
5235 Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, nullptr);
5238
5239 // Load imported lib.
5240 Dart_Handle imported_lib =
5241 TestCase::LoadTestLibrary("library_url", kImportedScriptChars);
5242 EXPECT_VALID(imported_lib);
5245 result = Dart_Invoke(imported_lib, NewString("test2"), 0, nullptr);
5247
5248 // Instance field.
5249 name = NewString("instance_fld");
5250 TestFieldNotFound(lib, name);
5252 TestFieldOk(instance, name, false, "instance");
5253
5254 // Hidden instance field.
5255 name = NewString("_instance_fld");
5256 TestFieldNotFound(lib, name);
5258 TestFieldOk(instance, name, false, "hidden instance");
5259
5260 // Final instance field.
5261 name = NewString("final_instance_fld");
5262 TestFieldNotFound(lib, name);
5264 TestFieldOk(instance, name, true, "final instance");
5265
5266 // Hidden final instance field.
5267 name = NewString("_final_instance_fld");
5268 TestFieldNotFound(lib, name);
5270 TestFieldOk(instance, name, true, "hidden final instance");
5271
5272 // Inherited field.
5273 name = NewString("inherited_fld");
5274 TestFieldNotFound(lib, name);
5276 TestFieldOk(instance, name, false, "inherited");
5277
5278 // Instance get/set field.
5279 name = NewString("instance_getset_fld");
5280 TestFieldNotFound(lib, name);
5282 TestFieldOk(instance, name, false, "instance getset");
5283
5284 // Hidden instance get/set field.
5285 name = NewString("_instance_getset_fld");
5286 TestFieldNotFound(lib, name);
5288 TestFieldOk(instance, name, false, "hidden instance getset");
5289
5290 // Static field.
5291 name = NewString("static_fld");
5292 TestFieldNotFound(lib, name);
5294 TestFieldOk(type, name, false, "static");
5295
5296 // Hidden static field.
5297 name = NewString("_static_fld");
5298 TestFieldNotFound(lib, name);
5300 TestFieldOk(type, name, false, "hidden static");
5301
5302 // Static final field.
5303 name = NewString("const_static_fld");
5304 TestFieldNotFound(lib, name);
5306 TestFieldOk(type, name, true, "const static");
5307
5308 // Hidden static const field.
5309 name = NewString("_const_static_fld");
5310 TestFieldNotFound(lib, name);
5312 TestFieldOk(type, name, true, "hidden const static");
5313
5314 // Static non-inherited field. Not found at any level.
5315 name = NewString("non_inherited_fld");
5316 TestFieldNotFound(lib, name);
5319
5320 // Static get/set field.
5321 name = NewString("static_getset_fld");
5322 TestFieldNotFound(lib, name);
5324 TestFieldOk(type, name, false, "static getset");
5325
5326 // Hidden static get/set field.
5327 name = NewString("_static_getset_fld");
5328 TestFieldNotFound(lib, name);
5330 TestFieldOk(type, name, false, "hidden static getset");
5331
5332 // Top-Level field.
5333 name = NewString("top_fld");
5336 TestFieldOk(lib, name, false, "top");
5337
5338 // Hidden top-level field.
5339 name = NewString("_top_fld");
5342 TestFieldOk(lib, name, false, "hidden top");
5343
5344 // Top-Level final field.
5345 name = NewString("const_top_fld");
5348 TestFieldOk(lib, name, true, "const top");
5349
5350 // Hidden top-level final field.
5351 name = NewString("_const_top_fld");
5354 TestFieldOk(lib, name, true, "hidden const top");
5355
5356 // Top-Level get/set field.
5357 name = NewString("top_getset_fld");
5360 TestFieldOk(lib, name, false, "top getset");
5361
5362 // Hidden top-level get/set field.
5363 name = NewString("_top_getset_fld");
5366 TestFieldOk(lib, name, false, "hidden top getset");
5367
5368 // Imported top-Level field.
5369 name = NewString("imported_fld");
5372 TestFieldNotFound(lib, name);
5373
5374 // Hidden imported top-level field. Not found at any level.
5375 name = NewString("_imported_fld");
5378 TestFieldNotFound(lib, name);
5379
5380 // Imported top-Level get/set field.
5381 name = NewString("imported_getset_fld");
5384 TestFieldNotFound(lib, name);
5385
5386 // Hidden imported top-level get/set field. Not found at any level.
5387 name = NewString("_imported_getset_fld");
5390 TestFieldNotFound(lib, name);
5391}
5392
5393TEST_CASE(DartAPI_SetField_FunnyValue) {
5394 const char* kScriptChars = "var top;\n";
5395
5396 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5397 Dart_Handle name = NewString("top");
5398 bool value;
5399
5400 // Test that you can set the field to a good value.
5406 EXPECT(value);
5407
5408 // Test that you can set the field to null
5410 result = Dart_GetField(lib, name);
5413
5414 // Pass a non-instance handle.
5415 result = Dart_SetField(lib, name, lib);
5417 result, "Dart_SetField expects argument 'value' to be of type Instance.");
5418
5419 // Pass an error handle. The error is contagious.
5420 result = Dart_SetField(lib, name, Api::NewError("myerror"));
5422 EXPECT_STREQ("myerror", Dart_GetError(result));
5423}
5424
5425TEST_CASE(DartAPI_SetField_BadType) {
5426 const char* kScriptChars = "late int foo;\n";
5427 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5428 Dart_Handle name = NewString("foo");
5431 EXPECT_SUBSTRING("type 'bool' is not a subtype of type 'int' of 'foo'",
5433}
5434
5436 UNREACHABLE();
5437}
5438
5440 int argument_count,
5441 bool* auto_setup_scope) {
5442 ASSERT(auto_setup_scope != nullptr);
5443 *auto_setup_scope = false;
5444 return NativeFieldLookup;
5445}
5446
5447TEST_CASE(DartAPI_InjectNativeFields2) {
5448 // clang-format off
5449 const char* kScriptChars =
5450 "class NativeFields extends NativeFieldsWrapper {\n"
5451 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5452 " int fld1;\n"
5453 " final int fld;\n"
5454 " static int? fld3;\n"
5455 " static const int fld4 = 10;\n"
5456 "}\n"
5457 "NativeFields testMain() {\n"
5458 " NativeFields obj = new NativeFields(10, 20);\n"
5459 " return obj;\n"
5460 "}\n";
5461 // clang-format on
5462
5464 // Create a test library and Load up a test script in it.
5465 Dart_Handle lib =
5466 TestCase::LoadTestScript(kScriptChars, nullptr, USER_TEST_URI, false);
5467
5468 // Invoke a function which returns an object of type NativeFields.
5469 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5470
5471 // We expect this to fail as class "NativeFields" extends
5472 // "NativeFieldsWrapper" and there is no definition of it either
5473 // in the dart code or through the native field injection mechanism.
5475}
5476
5477TEST_CASE(DartAPI_InjectNativeFields3) {
5478 // clang-format off
5479 const char* kScriptChars =
5480 "import 'dart:nativewrappers';"
5481 "final class NativeFields "
5482 "extends NativeFieldWrapperClass2 {\n"
5483 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5484 " int fld1;\n"
5485 " final int fld2;\n"
5486 " static int? fld3;\n"
5487 " static const int fld4 = 10;\n"
5488 "}\n"
5489 "NativeFields testMain() {\n"
5490 " NativeFields obj = new NativeFields(10, 20);\n"
5491 " return obj;\n"
5492 "}\n";
5493 // clang-format on
5495 const int kNumNativeFields = 2;
5496
5497 // Load up a test script in the test library.
5499
5500 // Invoke a function which returns an object of type NativeFields.
5501 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5503 CHECK_API_SCOPE(thread);
5504 TransitionNativeToVM transition(thread);
5505 HANDLESCOPE(thread);
5506 Instance& obj = Instance::Handle();
5507 obj ^= Api::UnwrapHandle(result);
5508 const Class& cls = Class::Handle(obj.clazz());
5509 // We expect the newly created "NativeFields" object to have
5510 // 2 dart instance fields (fld1, fld2) and a reference to the native fields.
5511 // Hence the size of an instance of "NativeFields" should be
5512 // (1 + 2) * kWordSize + size of object header.
5513 // We check to make sure the instance size computed by the VM matches
5514 // our expectations.
5515 intptr_t header_size = sizeof(UntaggedObject);
5516 EXPECT_EQ(
5517 Utils::RoundUp(((1 + 2) * kWordSize) + header_size, kObjectAlignment),
5518 cls.host_instance_size());
5519 EXPECT_EQ(kNumNativeFields, cls.num_native_fields());
5520}
5521
5522TEST_CASE(DartAPI_InjectNativeFields4) {
5523 // clang-format off
5524 const char* kScriptChars =
5525 "class NativeFields extends NativeFieldsWrapperClass2 {\n"
5526 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5527 " int fld1;\n"
5528 " final int fld;\n"
5529 " static int? fld3;\n"
5530 " static const int fld4 = 10;\n"
5531 "}\n"
5532 "NativeFields testMain() {\n"
5533 " NativeFields obj = new NativeFields(10, 20);\n"
5534 " return obj;\n"
5535 "}\n";
5536 // clang-format on
5538 // Load up a test script in the test library.
5539 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5540
5541 // Invoke a function which returns an object of type NativeFields.
5542 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5543
5544 USE(result);
5545#if 0
5546 // TODO(12455) Need better validation.
5547 // We expect the test script to fail finalization with the error below:
5549 Dart_Handle expected_error = DartUtils::NewError(
5550 "'dart:test-lib': Error: line 1 pos 36: "
5551 "class 'NativeFields' is trying to extend a native fields class, "
5552 "but library '%s' has no native resolvers",
5553 TestCase::url());
5554 EXPECT_SUBSTRING(Dart_GetError(expected_error), Dart_GetError(result));
5555#endif
5556}
5557
5558static constexpr int kTestNumNativeFields = 2;
5559static constexpr intptr_t kNativeField1Value = 30;
5560static constexpr intptr_t kNativeField2Value = 40;
5561
5566}
5567
5569 intptr_t field_values[kTestNumNativeFields];
5571 args, 0, kTestNumNativeFields, field_values);
5573 EXPECT_EQ(kNativeField1Value, field_values[0]);
5574 EXPECT_EQ(kNativeField2Value, field_values[1]);
5576 field_values);
5578 EXPECT_EQ(0, field_values[0]);
5579 EXPECT_EQ(0, field_values[1]);
5580}
5581
5583 intptr_t field_values[kTestNumNativeFields];
5585 args, 0, kTestNumNativeFields, field_values);
5587 "Dart_GetNativeFieldsOfArgument: "
5588 "expected 0 'num_fields' but was passed in 2");
5589}
5590
5592 int argument_count,
5593 bool* auto_scope) {
5594 ASSERT(auto_scope != nullptr);
5595 *auto_scope = true;
5598 if (!obj.IsString()) {
5599 return nullptr;
5600 }
5601 const char* function_name = obj.ToCString();
5602 ASSERT(function_name != nullptr);
5603 if (strcmp(function_name, "TestNativeFieldsAccess_init") == 0) {
5605 } else if (strcmp(function_name, "TestNativeFieldsAccess_access") == 0) {
5607 } else if (strcmp(function_name, "TestNativeFieldsAccess_invalidAccess") ==
5608 0) {
5610 } else {
5611 return nullptr;
5612 }
5613}
5614
5615TEST_CASE(DartAPI_TestNativeFieldsAccess) {
5616 // clang-format off
5617 const char* kScriptChars = R"(
5618 import 'dart:nativewrappers';
5619 base class NativeFields extends NativeFieldWrapperClass2 {
5620 NativeFields(int i, int j) : fld1 = i, fld2 = j {}
5621 int fld1;
5622 final int fld2;
5623 static int? fld3;
5624 static const int fld4 = 10;
5625 @pragma('vm:external-name', 'TestNativeFieldsAccess_init')
5626 external int? initNativeFlds();
5627 @pragma('vm:external-name', 'TestNativeFieldsAccess_access')
5628 external int? accessNativeFlds(int? i);
5629 }
5630 class NoNativeFields {
5631 int neitherATypedDataNorNull = 0;
5632 @pragma('vm:external-name', 'TestNativeFieldsAccess_invalidAccess')
5633 external invalidAccess();
5634 }
5635 NativeFields testMain() {
5636 NativeFields obj = new NativeFields(10, 20);
5637 obj.initNativeFlds();
5638 obj.accessNativeFlds(null);
5639 new NoNativeFields().invalidAccess();
5640 return obj;
5641 }
5642 )";
5643 // clang-format on
5644
5645 // Load up a test script in the test library.
5646 Dart_Handle lib =
5648
5649 // Invoke a function which returns an object of type NativeFields.
5650 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5652}
5653
5654TEST_CASE(DartAPI_InjectNativeFieldsSuperClass) {
5655 const char* kScriptChars =
5656 "import 'dart:nativewrappers';"
5657 "base class NativeFieldsSuper extends NativeFieldWrapperClass1 {\n"
5658 " NativeFieldsSuper() : fld1 = 42 {}\n"
5659 " int fld1;\n"
5660 "}\n"
5661 "base class NativeFields extends NativeFieldsSuper {\n"
5662 " fld() => fld1;\n"
5663 "}\n"
5664 "int testMain() {\n"
5665 " NativeFields obj = new NativeFields();\n"
5666 " return obj.fld();\n"
5667 "}\n";
5669 // Load up a test script in the test library.
5671
5672 // Invoke a function which returns an object of type NativeFields.
5673 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5674
5677 int64_t value = 0;
5680 EXPECT_EQ(42, value);
5681}
5682
5683static void TestNativeFields(Dart_Handle retobj) {
5684 // Access and set various instance fields of the object.
5685 Dart_Handle result = Dart_GetField(retobj, NewString("fld3"));
5687 result = Dart_GetField(retobj, NewString("fld0"));
5690 result = Dart_GetField(retobj, NewString("fld1"));
5692 int64_t value = 0;
5694 EXPECT_EQ(10, value);
5695 result = Dart_GetField(retobj, NewString("fld2"));
5698 EXPECT_EQ(20, value);
5699 result = Dart_SetField(retobj, NewString("fld2"), Dart_NewInteger(40));
5701 result = Dart_SetField(retobj, NewString("fld1"), Dart_NewInteger(40));
5703 result = Dart_GetField(retobj, NewString("fld1"));
5706 EXPECT_EQ(40, value);
5707
5708 // Now access and set various native instance fields of the returned object.
5709 const int kNativeFld0 = 0;
5710 const int kNativeFld1 = 1;
5711 const int kNativeFld2 = 2;
5712 const int kNativeFld3 = 3;
5713 const int kNativeFld4 = 4;
5714 int field_count = 0;
5715 intptr_t field_value = 0;
5716 EXPECT_VALID(Dart_GetNativeInstanceFieldCount(retobj, &field_count));
5717 EXPECT_EQ(4, field_count);
5718 result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &field_value);
5720 result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &field_value);
5722 EXPECT_EQ(0, field_value);
5723 result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &field_value);
5725 EXPECT_EQ(0, field_value);
5726 result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &field_value);
5728 EXPECT_EQ(0, field_value);
5729 result = Dart_GetNativeInstanceField(retobj, kNativeFld3, &field_value);
5731 EXPECT_EQ(0, field_value);
5732 result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
5734 result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 4);
5736 result = Dart_SetNativeInstanceField(retobj, kNativeFld1, 40);
5738 result = Dart_SetNativeInstanceField(retobj, kNativeFld2, 400);
5740 result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 4000);
5742 result = Dart_GetNativeInstanceField(retobj, kNativeFld3, &field_value);
5744 EXPECT_EQ(4000, field_value);
5745
5746 // Now re-access various dart instance fields of the returned object
5747 // to ensure that there was no corruption while setting native fields.
5748 result = Dart_GetField(retobj, NewString("fld1"));
5751 EXPECT_EQ(40, value);
5752 result = Dart_GetField(retobj, NewString("fld2"));
5755 EXPECT_EQ(20, value);
5756}
5757
5758TEST_CASE(DartAPI_ImplicitNativeFieldAccess) {
5759 // clang-format off
5760 const char* kScriptChars =
5761 "import 'dart:nativewrappers';"
5762 "final class NativeFields extends "
5763 "NativeFieldWrapperClass4 {\n"
5764 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5765 " int? fld0;\n"
5766 " int fld1;\n"
5767 " final int fld2;\n"
5768 " static int? fld3;\n"
5769 " static const int fld4 = 10;\n"
5770 "}\n"
5771 "NativeFields testMain() {\n"
5772 " NativeFields obj = new NativeFields(10, 20);\n"
5773 " return obj;\n"
5774 "}\n";
5775 // clang-format on
5776 // Load up a test script in the test library.
5778
5779 // Invoke a function which returns an object of type NativeFields.
5780 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5781 EXPECT_VALID(retobj);
5782
5783 // Now access and set various instance fields of the returned object.
5784 TestNativeFields(retobj);
5785}
5786
5787TEST_CASE(DartAPI_NegativeNativeFieldAccess) {
5788 // clang-format off
5789 const char* kScriptChars =
5790 "import 'dart:nativewrappers';\n"
5791 "class NativeFields {\n"
5792 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5793 " int fld1;\n"
5794 " final int fld2;\n"
5795 " static int? fld3;\n"
5796 " static const int fld4 = 10;\n"
5797 "}\n"
5798 "NativeFields testMain1() {\n"
5799 " NativeFields obj = new NativeFields(10, 20);\n"
5800 " return obj;\n"
5801 "}\n"
5802 "Function testMain2() {\n"
5803 " return () {};\n"
5804 "}\n";
5805 // clang-format on
5806
5808 CHECK_API_SCOPE(thread);
5809
5810 // Create a test library and Load up a test script in it.
5811 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5812
5813 // Invoke a function which returns an object of type NativeFields.
5814 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain1"), 0, nullptr);
5815 EXPECT_VALID(retobj);
5816
5817 // Now access and set various native instance fields of the returned object.
5818 // All of these tests are expected to return failure as there are no
5819 // native fields in an instance of NativeFields.
5820 const int kNativeFld0 = 0;
5821 const int kNativeFld1 = 1;
5822 const int kNativeFld2 = 2;
5823 const int kNativeFld3 = 3;
5824 const int kNativeFld4 = 4;
5825 intptr_t value = 0;
5826 result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &value);
5828 result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &value);
5830 result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &value);
5832 result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &value);
5834 result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
5836 result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 40);
5838 result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 400);
5840
5841 // Invoke a function which returns a closure object.
5842 retobj = Dart_Invoke(lib, NewString("testMain2"), 0, nullptr);
5843 EXPECT_VALID(retobj);
5844
5845 result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &value);
5847 result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &value);
5849 result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &value);
5851 result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &value);
5853 result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
5855 result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 40);
5857 result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 400);
5859}
5860
5861TEST_CASE(DartAPI_GetStaticField_RunsInitializer) {
5862 const char* kScriptChars =
5863 "class TestClass {\n"
5864 " static const int fld1 = 7;\n"
5865 " static int fld2 = 11;\n"
5866 " static void testMain() {\n"
5867 " }\n"
5868 "}\n";
5870 // Create a test library and Load up a test script in it.
5871 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5873 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, nullptr);
5875
5876 // Invoke a function which returns an object.
5877 result = Dart_Invoke(type, NewString("testMain"), 0, nullptr);
5879
5880 // For uninitialized fields, the getter is returned
5881 result = Dart_GetField(type, NewString("fld1"));
5883 int64_t value = 0;
5885 EXPECT_EQ(7, value);
5886
5887 result = Dart_GetField(type, NewString("fld2"));
5890 EXPECT_EQ(11, value);
5891
5892 // Overwrite fld2
5895
5896 // We now get the new value for fld2, not the initializer
5897 result = Dart_GetField(type, NewString("fld2"));
5900 EXPECT_EQ(13, value);
5901}
5902
5903TEST_CASE(DartAPI_GetField_CheckIsolate) {
5904 const char* kScriptChars =
5905 "class TestClass {\n"
5906 " static int fld2 = 11;\n"
5907 " static void testMain() {\n"
5908 " }\n"
5909 "}\n";
5911 int64_t value = 0;
5912
5913 // Create a test library and Load up a test script in it.
5914 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5916 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, nullptr);
5918
5919 result = Dart_GetField(type, NewString("fld2"));
5922 EXPECT_EQ(11, value);
5923}
5924
5925TEST_CASE(DartAPI_SetField_CheckIsolate) {
5926 const char* kScriptChars =
5927 "class TestClass {\n"
5928 " static int fld2 = 11;\n"
5929 " static void testMain() {\n"
5930 " }\n"
5931 "}\n";
5933 int64_t value = 0;
5934
5935 // Create a test library and Load up a test script in it.
5936 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5938 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, nullptr);
5940
5943
5944 result = Dart_GetField(type, NewString("fld2"));
5947 EXPECT_EQ(13, value);
5948}
5949
5950TEST_CASE(DartAPI_New) {
5951 const char* kScriptChars =
5952 "class MyClass implements MyExtraHop {\n"
5953 " MyClass() : foo = 7 {}\n"
5954 " MyClass.named(value) : foo = value {}\n"
5955 " MyClass._hidden(value) : foo = -value {}\n"
5956 " MyClass.exception(value) : foo = value {\n"
5957 " throw 'ConstructorDeath';\n"
5958 " }\n"
5959 " factory MyClass.multiply(value) {\n"
5960 " return new MyClass.named(value * 100);\n"
5961 " }\n"
5962 " var foo;\n"
5963 "}\n"
5964 "\n"
5965 "abstract class MyExtraHop implements MyInterface {\n"
5966 " factory MyExtraHop.hop(value) = MyClass.named;\n"
5967 "}\n"
5968 "\n"
5969 "abstract class MyInterface {\n"
5970 " factory MyInterface.named(value) = MyExtraHop.hop;\n"
5971 " factory MyInterface.multiply(value) = MyClass.multiply;\n"
5972 " MyInterface.notfound(value);\n"
5973 "}\n"
5974 "\n"
5975 "class _MyClass {\n"
5976 " _MyClass._() : foo = 7 {}\n"
5977 " var foo;\n"
5978 "}\n"
5979 "\n";
5980
5981 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5983 Dart_GetNonNullableType(lib, NewString("MyClass"), 0, nullptr);
5985 Dart_Handle intf =
5986 Dart_GetNonNullableType(lib, NewString("MyInterface"), 0, nullptr);
5987 EXPECT_VALID(intf);
5988 Dart_Handle private_type =
5989 Dart_GetNonNullableType(lib, NewString("_MyClass"), 0, nullptr);
5990 EXPECT_VALID(private_type);
5991
5992 Dart_Handle args[1];
5993 args[0] = Dart_NewInteger(11);
5994 Dart_Handle bad_args[1];
5995 bad_args[0] = Dart_NewApiError("myerror");
5996
5997 // Allocate and Invoke the unnamed constructor passing in Dart_Null.
5998 Dart_Handle result = Dart_New(type, Dart_Null(), 0, nullptr);
6000 bool instanceOf = false;
6001 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6002 EXPECT(instanceOf);
6003 int64_t int_value = 0;
6005 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6006 EXPECT_EQ(7, int_value);
6007
6008 // Allocate without a constructor.
6010 EXPECT_VALID(obj);
6011 instanceOf = false;
6012 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
6013 EXPECT(instanceOf);
6014 foo = Dart_GetField(obj, NewString("foo"));
6015 EXPECT(Dart_IsNull(foo));
6016
6017 // Allocate and Invoke the unnamed constructor passing in an empty string.
6018 result = Dart_New(type, Dart_EmptyString(), 0, nullptr);
6020 instanceOf = false;
6021 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6022 EXPECT(instanceOf);
6023 int_value = 0;
6024 foo = Dart_GetField(result, NewString("foo"));
6025 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6026 EXPECT_EQ(7, int_value);
6027
6028 // Allocate object and invoke the unnamed constructor with an empty string.
6029 obj = Dart_Allocate(type);
6030 EXPECT_VALID(obj);
6031 instanceOf = false;
6032 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
6033 EXPECT(instanceOf);
6034 // Use the empty string to invoke the unnamed constructor.
6035 result = Dart_InvokeConstructor(obj, Dart_EmptyString(), 0, nullptr);
6037 int_value = 0;
6038 foo = Dart_GetField(result, NewString("foo"));
6039 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6040 EXPECT_EQ(7, int_value);
6041 // use Dart_Null to invoke the unnamed constructor.
6042 result = Dart_InvokeConstructor(obj, Dart_Null(), 0, nullptr);
6044 int_value = 0;
6045 foo = Dart_GetField(result, NewString("foo"));
6046 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6047 EXPECT_EQ(7, int_value);
6048
6049 // Invoke a named constructor.
6050 result = Dart_New(type, NewString("named"), 1, args);
6052 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6053 EXPECT(instanceOf);
6054 int_value = 0;
6055 foo = Dart_GetField(result, NewString("foo"));
6056 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6057 EXPECT_EQ(11, int_value);
6058
6059 // Allocate object and invoke a named constructor.
6060 obj = Dart_Allocate(type);
6061 EXPECT_VALID(obj);
6062 instanceOf = false;
6063 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
6064 EXPECT(instanceOf);
6065 result = Dart_InvokeConstructor(obj, NewString("named"), 1, args);
6067 int_value = 0;
6068 foo = Dart_GetField(result, NewString("foo"));
6069 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6070 EXPECT_EQ(11, int_value);
6071
6072 // Invoke a hidden named constructor.
6073 result = Dart_New(type, NewString("_hidden"), 1, args);
6075 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6076 EXPECT(instanceOf);
6077 int_value = 0;
6078 foo = Dart_GetField(result, NewString("foo"));
6079 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6080 EXPECT_EQ(-11, int_value);
6081
6082 // Invoke a hidden named constructor on a hidden type.
6083 result = Dart_New(private_type, NewString("_"), 0, nullptr);
6085 int_value = 0;
6086 foo = Dart_GetField(result, NewString("foo"));
6087 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6088 EXPECT_EQ(7, int_value);
6089
6090 // Allocate object and invoke a hidden named constructor.
6091 obj = Dart_Allocate(type);
6092 EXPECT_VALID(obj);
6093 instanceOf = false;
6094 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
6095 EXPECT(instanceOf);
6096 result = Dart_InvokeConstructor(obj, NewString("_hidden"), 1, args);
6098 int_value = 0;
6099 foo = Dart_GetField(result, NewString("foo"));
6100 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6101 EXPECT_EQ(-11, int_value);
6102
6103 // Allocate object and Invoke a constructor which throws an exception.
6104 obj = Dart_Allocate(type);
6105 EXPECT_VALID(obj);
6106 instanceOf = false;
6107 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
6108 EXPECT(instanceOf);
6109 result = Dart_InvokeConstructor(obj, NewString("exception"), 1, args);
6110 EXPECT_ERROR(result, "ConstructorDeath");
6111
6112 // Invoke a factory constructor.
6113 result = Dart_New(type, NewString("multiply"), 1, args);
6115 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6116 EXPECT(instanceOf);
6117 int_value = 0;
6118 foo = Dart_GetField(result, NewString("foo"));
6119 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6120 EXPECT_EQ(1100, int_value);
6121
6122 // Pass an error class object. Error is passed through.
6123 result = Dart_New(Dart_NewApiError("myerror"), NewString("named"), 1, args);
6124 EXPECT_ERROR(result, "myerror");
6125
6126 // Pass a bad class object.
6127 result = Dart_New(Dart_Null(), NewString("named"), 1, args);
6128 EXPECT_ERROR(result, "Dart_New expects argument 'type' to be non-null.");
6129
6130 // Pass a negative arg count.
6131 result = Dart_New(type, NewString("named"), -1, args);
6133 result,
6134 "Dart_New expects argument 'number_of_arguments' to be non-negative.");
6135
6136 // Pass the wrong arg count.
6137 result = Dart_New(type, NewString("named"), 0, nullptr);
6139 result,
6140 "Dart_New: wrong argument count for constructor 'MyClass.named': "
6141 "0 passed, 1 expected.");
6142
6143 // Pass a bad argument. Error is passed through.
6144 result = Dart_New(type, NewString("named"), 1, bad_args);
6145 EXPECT_ERROR(result, "myerror");
6146
6147 // Pass a bad constructor name.
6150 result,
6151 "Dart_New expects argument 'constructor_name' to be of type String.");
6152
6153 // Invoke a missing constructor.
6154 result = Dart_New(type, NewString("missing"), 1, args);
6156 "Dart_New: could not find constructor 'MyClass.missing'.");
6157
6158 // Invoke a constructor which throws an exception.
6159 result = Dart_New(type, NewString("exception"), 1, args);
6160 EXPECT_ERROR(result, "ConstructorDeath");
6161
6162 // Invoke a constructor that is missing in the interface.
6163 result = Dart_New(intf, Dart_Null(), 0, nullptr);
6164 EXPECT_ERROR(result, "Dart_New: could not find constructor 'MyInterface.'.");
6165
6166 // Invoke abstract constructor that is present in the interface.
6167 result = Dart_New(intf, NewString("notfound"), 1, args);
6169 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6170 EXPECT(!instanceOf);
6171}
6172
6173// These two cases below currently fail because of issue
6174// https://github.com/dart-lang/sdk/issues/42939
6175TEST_CASE(DartAPI_New_Issue42939) {
6176 const char* kScriptChars =
6177 "class MyClass implements MyExtraHop {\n"
6178 " MyClass() : foo = 7 {}\n"
6179 " MyClass.named(value) : foo = value {}\n"
6180 " MyClass._hidden(value) : foo = -value {}\n"
6181 " MyClass.exception(value) : foo = value {\n"
6182 " throw 'ConstructorDeath';\n"
6183 " }\n"
6184 " factory MyClass.multiply(value) {\n"
6185 " return new MyClass.named(value * 100);\n"
6186 " }\n"
6187 " var foo;\n"
6188 "}\n"
6189 "\n"
6190 "abstract class MyExtraHop implements MyInterface {\n"
6191 " factory MyExtraHop.hop(value) = MyClass.named;\n"
6192 "}\n"
6193 "\n"
6194 "abstract class MyInterface {\n"
6195 " factory MyInterface.named(value) = MyExtraHop.hop;\n"
6196 " factory MyInterface.multiply(value) = MyClass.multiply;\n"
6197 " MyInterface.notfound(value);\n"
6198 "}\n"
6199 "\n";
6200
6201 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6203 Dart_GetNonNullableType(lib, NewString("MyClass"), 0, nullptr);
6205 Dart_Handle intf =
6206 Dart_GetNonNullableType(lib, NewString("MyInterface"), 0, nullptr);
6207 EXPECT_VALID(intf);
6208
6209 Dart_Handle args[1];
6210 args[0] = Dart_NewInteger(11);
6211
6212 // Invoke two-hop redirecting factory constructor.
6213 bool instanceOf = false;
6214 Dart_Handle result = Dart_New(intf, NewString("named"), 1, args);
6216 if (!Dart_IsError(result)) {
6217 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6218 EXPECT(instanceOf);
6219 int64_t int_value = 0;
6221 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6222 EXPECT_EQ(11, int_value);
6223 }
6224
6225 // Invoke one-hop redirecting factory constructor.
6226 result = Dart_New(intf, NewString("multiply"), 1, args);
6228 if (!Dart_IsError(result)) {
6229 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6230 EXPECT(instanceOf);
6231 int64_t int_value = 0;
6233 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6234 EXPECT_EQ(1100, int_value);
6235 }
6236}
6237
6238TEST_CASE(DartAPI_New_Issue44205) {
6239 const char* kScriptChars =
6240 "class MyIntClass {\n"
6241 " MyIntClass(this.value);\n"
6242 " int value;\n"
6243 "}\n"
6244 "\n"
6245 "class MyClass<T> {\n"
6246 " T value;\n"
6247 " MyClass(this.value);\n"
6248 " factory MyClass.foo(T x) => MyClass<T>(x);\n"
6249 "}\n"
6250 "\n"
6251 "Type getIntType() { return int; }\n"
6252 "\n";
6253
6254 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6255 EXPECT_VALID(lib);
6256 Dart_Handle int_wrapper_type =
6257 Dart_GetNonNullableType(lib, NewString("MyIntClass"), 0, nullptr);
6258 EXPECT_VALID(int_wrapper_type);
6259
6260 Dart_Handle args[1];
6261 args[0] = Dart_EmptyString();
6262
6263 Dart_Handle result = Dart_New(int_wrapper_type, Dart_EmptyString(), 1, args);
6264 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'value'");
6265
6266 Dart_Handle int_type = Dart_Invoke(lib, NewString("getIntType"), 0, args);
6267 EXPECT_VALID(int_type);
6268 Dart_Handle type_args = Dart_NewList(1);
6269 EXPECT_VALID(type_args);
6270 EXPECT_VALID(Dart_ListSetAt(type_args, 0, int_type));
6271 Dart_Handle my_class_type =
6272 Dart_GetNonNullableType(lib, NewString("MyClass"), 1, &type_args);
6273 EXPECT_VALID(my_class_type);
6274
6275 // Generic generative constructor
6276 args[0] = Dart_EmptyString();
6277 result = Dart_New(my_class_type, Dart_EmptyString(), 1, args);
6278 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'value'");
6279
6280 // Generic factory constructor
6281 result = Dart_New(my_class_type, NewString("foo"), 1, args);
6282 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'x'");
6283}
6284
6285TEST_CASE(DartAPI_InvokeConstructor_Issue44205) {
6286 const char* kScriptChars =
6287 "class MyIntClass {\n"
6288 " MyIntClass(this.value);\n"
6289 " int value;\n"
6290 "}\n"
6291 "\n"
6292 "class MyClass<T> {\n"
6293 " T value;\n"
6294 " MyClass(this.value);\n"
6295 "}\n"
6296 "\n"
6297 "Type getIntType() { return int; }\n"
6298 "\n";
6299
6300 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6301 EXPECT_VALID(lib);
6302 Dart_Handle int_wrapper_type =
6303 Dart_GetNonNullableType(lib, NewString("MyIntClass"), 0, nullptr);
6304 EXPECT_VALID(int_wrapper_type);
6305
6306 Dart_Handle args[1];
6307 args[0] = Dart_EmptyString();
6308 Dart_Handle result = Dart_Allocate(int_wrapper_type);
6310
6312 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'value'");
6313
6314 Dart_Handle int_type = Dart_Invoke(lib, NewString("getIntType"), 0, args);
6315 EXPECT_VALID(int_type);
6316 Dart_Handle type_args = Dart_NewList(1);
6317 EXPECT_VALID(type_args);
6318 EXPECT_VALID(Dart_ListSetAt(type_args, 0, int_type));
6319 Dart_Handle my_class_type =
6320 Dart_GetNonNullableType(lib, NewString("MyClass"), 1, &type_args);
6321 EXPECT_VALID(my_class_type);
6322
6323 result = Dart_Allocate(my_class_type);
6326 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'value'");
6327}
6328
6329TEST_CASE(DartAPI_InvokeClosure_Issue44205) {
6330 const char* kScriptChars =
6331 "class InvokeClosure {\n"
6332 " InvokeClosure(int i, int j) : fld1 = i, fld2 = j {}\n"
6333 " Function method1(int i) {\n"
6334 " f(int j) => j + i + fld1 + fld2 + fld4; \n"
6335 " return f;\n"
6336 " }\n"
6337 " int fld1;\n"
6338 " final int fld2;\n"
6339 " static const int fld4 = 10;\n"
6340 "}\n"
6341 "Function testMain1() {\n"
6342 " InvokeClosure obj = new InvokeClosure(10, 20);\n"
6343 " return obj.method1(10);\n"
6344 "}\n";
6346 CHECK_API_SCOPE(thread);
6347
6348 // Create a test library and Load up a test script in it.
6349 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6350 EXPECT_VALID(lib);
6351
6352 // Invoke a function which returns a closure.
6353 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain1"), 0, nullptr);
6354 EXPECT_VALID(retobj);
6355
6356 // Now invoke the closure and check the result.
6357 Dart_Handle dart_arguments[1];
6358 dart_arguments[0] = Dart_EmptyString();
6359 result = Dart_InvokeClosure(retobj, 1, dart_arguments);
6360 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'j'");
6361}
6362
6363TEST_CASE(DartAPI_NewListOfType) {
6364 const char* kScriptChars =
6365 "class ZXHandle {}\n"
6366 "class ChannelReadResult {\n"
6367 " final List<ZXHandle?> handles;\n"
6368 " ChannelReadResult(this.handles);\n"
6369 "}\n"
6370 "void expectListOfString(List<String> _) {}\n"
6371 "void expectListOfDynamic(List<dynamic> _) {}\n"
6372 "void expectListOfVoid(List<void> _) {}\n"
6373 "void expectListOfNever(List<Never> _) {}\n";
6374 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6375
6376 Dart_Handle zxhandle_type =
6377 Dart_GetNullableType(lib, NewString("ZXHandle"), 0, nullptr);
6378 EXPECT_VALID(zxhandle_type);
6379
6380 Dart_Handle zxhandle = Dart_New(zxhandle_type, Dart_Null(), 0, nullptr);
6381 EXPECT_VALID(zxhandle);
6382
6383 Dart_Handle zxhandle_list = Dart_NewListOfType(zxhandle_type, 1);
6384 EXPECT_VALID(zxhandle_list);
6385
6386 EXPECT_VALID(Dart_ListSetAt(zxhandle_list, 0, zxhandle));
6387
6388 Dart_Handle readresult_type =
6389 Dart_GetNonNullableType(lib, NewString("ChannelReadResult"), 0, nullptr);
6390 EXPECT_VALID(zxhandle_type);
6391
6392 const int kNumArgs = 1;
6393 Dart_Handle args[kNumArgs];
6394 args[0] = zxhandle_list;
6395 EXPECT_VALID(Dart_New(readresult_type, Dart_Null(), kNumArgs, args));
6396
6399 "Dart_NewListOfType expects argument 'element_type' to be non-null.");
6402 "Dart_NewListOfType expects argument 'element_type' to be of type Type.");
6403
6404 Dart_Handle dart_core = Dart_LookupLibrary(NewString("dart:core"));
6405 EXPECT_VALID(dart_core);
6406
6407 Dart_Handle string_type =
6408 Dart_GetNonNullableType(dart_core, NewString("String"), 0, nullptr);
6409 EXPECT_VALID(string_type);
6410 Dart_Handle string_list = Dart_NewListOfType(string_type, 0);
6411 EXPECT_VALID(string_list);
6412 args[0] = string_list;
6414 Dart_Invoke(lib, NewString("expectListOfString"), kNumArgs, args));
6415
6416 Dart_Handle dynamic_type = Dart_TypeDynamic();
6417 EXPECT_VALID(dynamic_type);
6418 Dart_Handle dynamic_list = Dart_NewListOfType(dynamic_type, 0);
6419 EXPECT_VALID(dynamic_list);
6420 args[0] = dynamic_list;
6422 Dart_Invoke(lib, NewString("expectListOfDynamic"), kNumArgs, args));
6423
6424 Dart_Handle void_type = Dart_TypeVoid();
6425 EXPECT_VALID(void_type);
6426 Dart_Handle void_list = Dart_NewListOfType(void_type, 0);
6427 EXPECT_VALID(void_list);
6428 args[0] = void_list;
6429 EXPECT_VALID(Dart_Invoke(lib, NewString("expectListOfVoid"), kNumArgs, args));
6430
6431 Dart_Handle never_type = Dart_TypeNever();
6432 EXPECT_VALID(never_type);
6433 Dart_Handle never_list = Dart_NewListOfType(never_type, 0);
6434 EXPECT_VALID(never_list);
6435 args[0] = never_list;
6437 Dart_Invoke(lib, NewString("expectListOfNever"), kNumArgs, args));
6438}
6439
6440TEST_CASE(DartAPI_NewListOfTypeFilled) {
6441 const char* kScriptChars =
6442 "class ZXHandle {}\n"
6443 "class ChannelReadResult {\n"
6444 " final List<ZXHandle> handles;\n"
6445 " ChannelReadResult(this.handles);\n"
6446 "}\n";
6447 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6448
6449 Dart_Handle zxhandle_type =
6450 Dart_GetNonNullableType(lib, NewString("ZXHandle"), 0, nullptr);
6451 EXPECT_VALID(zxhandle_type);
6452
6453 Dart_Handle nullable_zxhandle_type =
6454 Dart_GetNullableType(lib, NewString("ZXHandle"), 0, nullptr);
6455 EXPECT_VALID(nullable_zxhandle_type);
6456
6457 Dart_Handle integer = Dart_NewInteger(42);
6458 EXPECT_VALID(integer);
6459
6460 Dart_Handle zxhandle = Dart_New(zxhandle_type, Dart_Null(), 0, nullptr);
6461 EXPECT_VALID(zxhandle);
6462
6463 Dart_Handle zxhandle_list =
6464 Dart_NewListOfTypeFilled(zxhandle_type, zxhandle, 1);
6465 EXPECT_VALID(zxhandle_list);
6466
6467 Dart_Handle result = Dart_ListGetAt(zxhandle_list, 0);
6469
6470 EXPECT(Dart_IdentityEquals(result, zxhandle));
6471
6472 Dart_Handle readresult_type =
6473 Dart_GetNonNullableType(lib, NewString("ChannelReadResult"), 0, nullptr);
6474 EXPECT_VALID(zxhandle_type);
6475
6476 const int kNumArgs = 1;
6477 Dart_Handle args[kNumArgs];
6478 args[0] = zxhandle_list;
6479 EXPECT_VALID(Dart_New(readresult_type, Dart_Null(), kNumArgs, args));
6480
6482 "Dart_NewListOfTypeFilled expects argument 'element_type' to be "
6483 "non-null.");
6485 "Dart_NewListOfTypeFilled expects argument 'element_type' to be "
6486 "of type Type.");
6488 Dart_NewListOfTypeFilled(zxhandle_type, Dart_Null(), 1),
6489 "Dart_NewListOfTypeFilled expects argument 'fill_object' to be non-null"
6490 " for a non-nullable 'element_type'");
6492 Dart_NewListOfTypeFilled(zxhandle_type, integer, 1),
6493 "Dart_NewListOfTypeFilled expects argument 'fill_object' to have the same"
6494 " type as 'element_type'.");
6495
6497 Dart_NewListOfTypeFilled(nullable_zxhandle_type, Dart_Null(), 1));
6498
6499 // Null is always valid as the fill argument if we're creating an empty list.
6500 EXPECT_VALID(Dart_NewListOfTypeFilled(zxhandle_type, Dart_Null(), 0));
6501
6502 // Test creation of a non nullable list of strings.
6503 Dart_Handle corelib = Dart_LookupLibrary(NewString("dart:core"));
6504 EXPECT_VALID(corelib);
6505 Dart_Handle string_type =
6506 Dart_GetNonNullableType(corelib, NewString("String"), 0, nullptr);
6508}
6509
6510static Dart_Handle PrivateLibName(Dart_Handle lib, const char* str) {
6511 EXPECT(Dart_IsLibrary(lib));
6512 Thread* thread = Thread::Current();
6513 TransitionNativeToVM transition(thread);
6514 const Library& library_obj = Api::UnwrapLibraryHandle(thread->zone(), lib);
6515 const String& name = String::Handle(String::New(str));
6516 return Api::NewHandle(thread, library_obj.PrivateName(name));
6517}
6518
6519TEST_CASE(DartAPI_Invoke) {
6520 const char* kScriptChars =
6521 "class BaseMethods {\n"
6522 " inheritedMethod(arg) => 'inherited $arg';\n"
6523 " static nonInheritedMethod(arg) => 'noninherited $arg';\n"
6524 "}\n"
6525 "\n"
6526 "class Methods extends BaseMethods {\n"
6527 " instanceMethod(arg) => 'instance $arg';\n"
6528 " _instanceMethod(arg) => 'hidden instance $arg';\n"
6529 " static staticMethod(arg) => 'static $arg';\n"
6530 " static _staticMethod(arg) => 'hidden static $arg';\n"
6531 "}\n"
6532 "\n"
6533 "topMethod(arg) => 'top $arg';\n"
6534 "_topMethod(arg) => 'hidden top $arg';\n"
6535 "\n"
6536 "Methods test() {\n"
6537 " return new Methods();\n"
6538 "}\n";
6539
6540 // Shared setup.
6541 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6543 Dart_GetNonNullableType(lib, NewString("Methods"), 0, nullptr);
6545 Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, nullptr);
6547 Dart_Handle args[1];
6548 args[0] = NewString("!!!");
6549 Dart_Handle bad_args[2];
6550 bad_args[0] = NewString("bad1");
6551 bad_args[1] = NewString("bad2");
6554 const char* str;
6555
6556 // Instance method.
6557 name = NewString("instanceMethod");
6563 EXPECT_STREQ("instance !!!", str);
6564
6565 // Instance method, wrong arg count.
6566 EXPECT_ERROR(Dart_Invoke(instance, name, 2, bad_args),
6567 "Class 'Methods' has no instance method 'instanceMethod'"
6568 " with matching arguments");
6569
6570 name = PrivateLibName(lib, "_instanceMethod");
6576 EXPECT_STREQ("hidden instance !!!", str);
6577
6578 // Inherited method.
6579 name = NewString("inheritedMethod");
6585 EXPECT_STREQ("inherited !!!", str);
6586
6587 // Static method.
6588 name = NewString("staticMethod");
6594 EXPECT_STREQ("static !!!", str);
6595
6596 // Static method, wrong arg count.
6597 EXPECT_ERROR(Dart_Invoke(type, name, 2, bad_args),
6598 "NoSuchMethodError: No static method 'staticMethod' with "
6599 "matching arguments");
6600
6601 // Hidden static method.
6602 name = NewString("_staticMethod");
6608 EXPECT_STREQ("hidden static !!!", str);
6609
6610 // Static non-inherited method. Not found at any level.
6611 name = NewString("non_inheritedMethod");
6615
6616 // Top-Level method.
6617 name = NewString("topMethod");
6620 result = Dart_Invoke(lib, name, 1, args);
6623 EXPECT_STREQ("top !!!", str);
6624
6625 // Top-level method, wrong arg count.
6626 EXPECT_ERROR(Dart_Invoke(lib, name, 2, bad_args),
6627 "NoSuchMethodError: No top-level method 'topMethod' with "
6628 "matching arguments");
6629
6630 // Hidden top-level method.
6631 name = NewString("_topMethod");
6634 result = Dart_Invoke(lib, name, 1, args);
6637 EXPECT_STREQ("hidden top !!!", str);
6638}
6639
6640TEST_CASE(DartAPI_Invoke_PrivateStatic) {
6641 const char* kScriptChars =
6642 "class Methods {\n"
6643 " static _staticMethod(arg) => 'hidden static $arg';\n"
6644 "}\n"
6645 "\n";
6646
6647 // Shared setup.
6648 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6650 Dart_GetNonNullableType(lib, NewString("Methods"), 0, nullptr);
6653 Dart_Handle name = NewString("_staticMethod");
6655
6656 Dart_Handle args[1];
6657 args[0] = NewString("!!!");
6660
6661 const char* str = nullptr;
6663 EXPECT_STREQ("hidden static !!!", str);
6664}
6665
6666TEST_CASE(DartAPI_Invoke_FunnyArgs) {
6667 const char* kScriptChars = "test(arg) => 'hello $arg';\n";
6668
6669 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6670 Dart_Handle func_name = NewString("test");
6671 Dart_Handle args[1];
6672 const char* str;
6673
6674 // Make sure that valid args yield valid results.
6675 args[0] = NewString("!!!");
6676 Dart_Handle result = Dart_Invoke(lib, func_name, 1, args);
6679 EXPECT_STREQ("hello !!!", str);
6680
6681 // Make sure that null is legal.
6682 args[0] = Dart_Null();
6683 result = Dart_Invoke(lib, func_name, 1, args);
6686 EXPECT_STREQ("hello null", str);
6687
6688 // Pass an error handle as the target. The error is propagated.
6689 result = Dart_Invoke(Api::NewError("myerror"), func_name, 1, args);
6691 EXPECT_STREQ("myerror", Dart_GetError(result));
6692
6693 // Pass an error handle as the function name. The error is propagated.
6694 result = Dart_Invoke(lib, Api::NewError("myerror"), 1, args);
6696 EXPECT_STREQ("myerror", Dart_GetError(result));
6697
6698 // Pass a non-instance handle as a parameter..
6699 args[0] = lib;
6700 result = Dart_Invoke(lib, func_name, 1, args);
6702 EXPECT_STREQ("Dart_Invoke expects arguments[0] to be an Instance handle.",
6704
6705 // Pass an error handle as a parameter. The error is propagated.
6706 args[0] = Api::NewError("myerror");
6707 result = Dart_Invoke(lib, func_name, 1, args);
6709 EXPECT_STREQ("myerror", Dart_GetError(result));
6710}
6711
6712TEST_CASE(DartAPI_Invoke_BadArgs) {
6713 const char* kScriptChars =
6714 "class BaseMethods {\n"
6715 " inheritedMethod(int arg) => 'inherited $arg';\n"
6716 " static nonInheritedMethod(int arg) => 'noninherited $arg';\n"
6717 "}\n"
6718 "\n"
6719 "class Methods extends BaseMethods {\n"
6720 " instanceMethod(int arg) => 'instance $arg';\n"
6721 " _instanceMethod(int arg) => 'hidden instance $arg';\n"
6722 " static staticMethod(int arg) => 'static $arg';\n"
6723 " static _staticMethod(int arg) => 'hidden static $arg';\n"
6724 "}\n"
6725 "\n"
6726 "topMethod(int arg) => 'top $arg';\n"
6727 "_topMethod(int arg) => 'hidden top $arg';\n"
6728 "\n"
6729 "Methods test() {\n"
6730 " return new Methods();\n"
6731 "}\n";
6732
6733#if defined(PRODUCT)
6734 const char* error_msg =
6735 "type '_OneByteString' is not a subtype of type 'int' of 'arg'";
6736#else
6737 const char* error_msg =
6738 "type 'String' is not a subtype of type 'int' of 'arg'";
6739#endif // defined(PRODUCT)
6740
6741 // Shared setup.
6742 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6744 Dart_GetNonNullableType(lib, NewString("Methods"), 0, nullptr);
6746 Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, nullptr);
6748 Dart_Handle args[1];
6749 args[0] = NewString("!!!");
6752
6753 // Instance method.
6754 name = NewString("instanceMethod");
6757 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6758
6759 name = PrivateLibName(lib, "_instanceMethod");
6762 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6763
6764 // Inherited method.
6765 name = NewString("inheritedMethod");
6768 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6769
6770 // Static method.
6771 name = NewString("staticMethod");
6774 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6775
6776 // Hidden static method.
6777 name = NewString("_staticMethod");
6780 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6781
6782 // Top-Level method.
6783 name = NewString("topMethod");
6784 result = Dart_Invoke(lib, name, 1, args);
6786 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6787
6788 // Hidden top-level method.
6789 name = NewString("_topMethod");
6790 result = Dart_Invoke(lib, name, 1, args);
6792 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6793}
6794
6795TEST_CASE(DartAPI_Invoke_Null) {
6797 Dart_Invoke(Dart_Null(), NewString("toString"), 0, nullptr);
6800
6801 const char* value = "";
6803 EXPECT_STREQ("null", value);
6804
6806 result = Dart_Invoke(Dart_Null(), function_name, 0, nullptr);
6809
6810 result = Dart_GetField(Dart_Null(), NewString("toString"));
6813
6814 result =
6815 Dart_SetField(Dart_Null(), NewString("nullHasNoSetters"), Dart_Null());
6816 // Not that Dart_SetField expects a non-null receiver.
6818 result,
6819 "NoSuchMethodError: The setter 'nullHasNoSetters=' was called on null");
6820}
6821
6822TEST_CASE(DartAPI_InvokeNoSuchMethod) {
6823 const char* kScriptChars =
6824 "class Expect {\n"
6825 " static equals(a, b) {\n"
6826 " if (a != b) {\n"
6827 " throw 'not equal. expected: $a, got: $b';\n"
6828 " }\n"
6829 " }\n"
6830 "}\n"
6831 "class TestClass {\n"
6832 " static int fld1 = 0;\n"
6833 " void noSuchMethod(Invocation invocation) {\n"
6834 // This relies on the Symbol.toString() method returning a String of the
6835 // form 'Symbol("name")'. This is to avoid having to import
6836 // dart:_internal just to get access to the name of the symbol.
6837 " var name = invocation.memberName.toString();\n"
6838 " name = name.split('\"')[1];\n"
6839 " if (name == 'fld') {\n"
6840 " Expect.equals(true, invocation.isGetter);\n"
6841 " Expect.equals(false, invocation.isMethod);\n"
6842 " Expect.equals(false, invocation.isSetter);\n"
6843 " } else if (name == 'setfld') {\n"
6844 " Expect.equals(true, invocation.isSetter);\n"
6845 " Expect.equals(false, invocation.isMethod);\n"
6846 " Expect.equals(false, invocation.isGetter);\n"
6847 " } else if (name == 'method') {\n"
6848 " Expect.equals(true, invocation.isMethod);\n"
6849 " Expect.equals(false, invocation.isSetter);\n"
6850 " Expect.equals(false, invocation.isGetter);\n"
6851 " }\n"
6852 " TestClass.fld1 += 1;\n"
6853 " }\n"
6854 " static TestClass testMain() {\n"
6855 " return new TestClass();\n"
6856 " }\n"
6857 "}\n";
6860 // Create a test library and Load up a test script in it.
6861 // The test library must have a dart: url so it can import dart:_internal.
6862 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6864 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, nullptr);
6866
6867 // Invoke a function which returns an object.
6868 instance = Dart_Invoke(type, NewString("testMain"), 0, nullptr);
6870
6871 // Try to get a field that does not exist, should call noSuchMethod.
6874
6875 // Try to set a field that does not exist, should call noSuchMethod.
6878
6879 // Try to invoke a method that does not exist, should call noSuchMethod.
6880 result = Dart_Invoke(instance, NewString("method"), 0, nullptr);
6882
6883 result = Dart_GetField(type, NewString("fld1"));
6885 int64_t value = 0;
6887 EXPECT_EQ(3, value);
6888}
6889
6890TEST_CASE(DartAPI_InvokeClosure) {
6891 const char* kScriptChars =
6892 "class InvokeClosure {\n"
6893 " InvokeClosure(int i, int j) : fld1 = i, fld2 = j {}\n"
6894 " Function method1(int i) {\n"
6895 " f(int j) => j + i + fld1 + fld2 + fld4; \n"
6896 " return f;\n"
6897 " }\n"
6898 " static Function method2(int i) {\n"
6899 " n(int j) { throw new Exception('I am an exception'); return 1; }\n"
6900 " return n;\n"
6901 " }\n"
6902 " int fld1;\n"
6903 " final int fld2;\n"
6904 " static const int fld4 = 10;\n"
6905 "}\n"
6906 "Function testMain1() {\n"
6907 " InvokeClosure obj = new InvokeClosure(10, 20);\n"
6908 " return obj.method1(10);\n"
6909 "}\n"
6910 "Function testMain2() {\n"
6911 " return InvokeClosure.method2(10);\n"
6912 "}\n";
6914 CHECK_API_SCOPE(thread);
6915
6916 // Create a test library and Load up a test script in it.
6917 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6918
6919 // Invoke a function which returns a closure.
6920 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain1"), 0, nullptr);
6921 EXPECT_VALID(retobj);
6922
6923 EXPECT(Dart_IsClosure(retobj));
6925
6926 // Now invoke the closure and check the result.
6927 Dart_Handle dart_arguments[1];
6928 dart_arguments[0] = Dart_NewInteger(1);
6929 result = Dart_InvokeClosure(retobj, 1, dart_arguments);
6932 int64_t value = 0;
6934 EXPECT_EQ(51, value);
6935
6936 // Invoke closure with wrong number of args, should result in exception.
6937 result = Dart_InvokeClosure(retobj, 0, nullptr);
6940
6941 // Invoke a function which returns a closure.
6942 retobj = Dart_Invoke(lib, NewString("testMain2"), 0, nullptr);
6943 EXPECT_VALID(retobj);
6944
6945 EXPECT(Dart_IsClosure(retobj));
6946 EXPECT(!Dart_IsClosure(NewString("abcdef")));
6947
6948 // Now invoke the closure and check the result (should be an exception).
6949 dart_arguments[0] = Dart_NewInteger(1);
6950 result = Dart_InvokeClosure(retobj, 1, dart_arguments);
6953}
6954
6957 Dart_ThrowException(NewString("Hello from ExceptionNative!"));
6958 UNREACHABLE();
6959}
6960
6962 int argument_count,
6963 bool* auto_setup_scope) {
6964 ASSERT(auto_setup_scope != nullptr);
6965 *auto_setup_scope = true;
6966 return ExceptionNative;
6967}
6968
6969TEST_CASE(DartAPI_ThrowException) {
6970 const char* kScriptChars =
6971 R"(
6972 @pragma('vm:external-name', 'ThrowException_native')
6973 external int test();
6974 )";
6975
6977 intptr_t size = thread->ZoneSizeInBytes();
6978 Dart_EnterScope(); // Start a Dart API scope for invoking API functions.
6979
6980 // Load up a test script which extends the native wrapper class.
6982
6983 // Throwing an exception here should result in an error.
6984 result = Dart_ThrowException(NewString("This doesn't work"));
6985 EXPECT_ERROR(result, "No Dart frames on stack, cannot throw exception");
6987
6988 // Invoke 'test' and check for an uncaught exception.
6989 result = Dart_Invoke(lib, NewString("test"), 0, nullptr);
6990 EXPECT_ERROR(result, "Hello from ExceptionNative!");
6992
6993 Dart_ExitScope(); // Exit the Dart API scope.
6994 EXPECT_EQ(size, thread->ZoneSizeInBytes());
6997static intptr_t kNativeArgumentNativeField1Value = 30;
6998static intptr_t kNativeArgumentNativeField2Value = 40;
7002 Dart_GetNonNullableType(lib, NewString("MyObject"), 0, nullptr);
7004
7005 // Allocate without a constructor.
7006 const int num_native_fields = 2;
7007 const intptr_t native_fields[] = {kNativeArgumentNativeField1Value,
7009 // Allocate and Setup native fields.
7010 Dart_Handle obj =
7011 Dart_AllocateWithNativeFields(type, num_native_fields, native_fields);
7012 EXPECT_VALID(obj);
7013
7017}
7018
7020 const int kNumNativeFields = 2;
7021
7022 // Test different argument types with a valid descriptor set.
7023 {
7024 const char* cstr = nullptr;
7025 intptr_t native_fields1[kNumNativeFields];
7026 intptr_t native_fields2[kNumNativeFields];
7027 const Dart_NativeArgument_Descriptor arg_descriptors[9] = {
7037 };
7038 Dart_NativeArgument_Value arg_values[9];
7039 arg_values[0].as_native_fields.num_fields = kNumNativeFields;
7040 arg_values[0].as_native_fields.values = native_fields1;
7041 arg_values[7].as_native_fields.num_fields = kNumNativeFields;
7042 arg_values[7].as_native_fields.values = native_fields2;
7044 Dart_GetNativeArguments(args, 9, arg_descriptors, arg_values);
7046
7047 EXPECT(arg_values[0].as_native_fields.values[0] == 30);
7048 EXPECT(arg_values[0].as_native_fields.values[1] == 40);
7049
7050 EXPECT(arg_values[1].as_int32 == 77);
7051
7052 // When wrapped-around, this value should not fit into int32, because this
7053 // unit test verifies that getting it as int32 produces error.
7054 EXPECT(arg_values[2].as_uint64 == 0x8000000000000000LL);
7055
7056 EXPECT(arg_values[3].as_bool == true);
7057
7058 EXPECT(arg_values[4].as_double == 3.14);
7059
7060 EXPECT_VALID(arg_values[5].as_string.dart_str);
7061 EXPECT(Dart_IsString(arg_values[5].as_string.dart_str));
7062 EXPECT_VALID(Dart_StringToCString(arg_values[5].as_string.dart_str, &cstr));
7063 EXPECT_STREQ("abcdefg", cstr);
7064 EXPECT(arg_values[5].as_string.peer == nullptr);
7065
7066 EXPECT_VALID(arg_values[6].as_string.dart_str);
7067 EXPECT(Dart_IsString(arg_values[6].as_string.dart_str));
7068 EXPECT_VALID(Dart_StringToCString(arg_values[6].as_string.dart_str, &cstr));
7069 EXPECT_STREQ("string", cstr);
7070 EXPECT(arg_values[6].as_string.peer == nullptr);
7071
7072 EXPECT(arg_values[7].as_native_fields.values[0] == 60);
7073 EXPECT(arg_values[7].as_native_fields.values[1] == 80);
7074
7075 EXPECT_VALID(arg_values[8].as_instance);
7076 EXPECT(Dart_IsInstance(arg_values[8].as_instance));
7077 int field_count = 0;
7078 EXPECT_VALID(Dart_GetNativeInstanceFieldCount(arg_values[8].as_instance,
7079 &field_count));
7080 EXPECT(field_count == 2);
7081 }
7082
7083 // Test with an invalid descriptor set (invalid type).
7084 {
7085 const Dart_NativeArgument_Descriptor arg_descriptors[8] = {
7094 };
7095 Dart_NativeArgument_Value arg_values[8];
7097 Dart_GetNativeArguments(args, 8, arg_descriptors, arg_values);
7099 }
7100
7101 // Test with an invalid range error.
7102 {
7103 const Dart_NativeArgument_Descriptor arg_descriptors[8] = {
7112 };
7113 Dart_NativeArgument_Value arg_values[8];
7115 Dart_GetNativeArguments(args, 8, arg_descriptors, arg_values);
7117 }
7118
7120}
7121
7123 int argument_count,
7124 bool* auto_scope_setup) {
7125 TransitionNativeToVM transition(Thread::Current());
7126 const Object& obj = Object::Handle(Api::UnwrapHandle(name));
7127 if (!obj.IsString()) {
7128 return nullptr;
7129 }
7130 ASSERT(auto_scope_setup != nullptr);
7131 *auto_scope_setup = true;
7132 const char* function_name = obj.ToCString();
7133 ASSERT(function_name != nullptr);
7134 if (strcmp(function_name, "NativeArgument_Create") == 0) {
7135 return NativeArgumentCreate;
7136 } else if (strcmp(function_name, "NativeArgument_Access") == 0) {
7137 return NativeArgumentAccess;
7138 }
7139 return nullptr;
7140}
7141
7142TEST_CASE(DartAPI_GetNativeArguments) {
7143 const char* kScriptChars = R"(
7144import 'dart:nativewrappers';
7145base class MyObject extends NativeFieldWrapperClass2 {
7146 @pragma("vm:external-name", "NativeArgument_Create")
7147 external static MyObject createObject();
7148 @pragma("vm:external-name", "NativeArgument_Access")
7149 external int accessFields(int arg1,
7150 int arg2,
7151 bool arg3,
7152 double arg4,
7153 String arg5,
7154 String arg6,
7155 MyObject arg7);
7156}
7157int testMain(String extstr) {
7158 String str = 'abcdefg';
7159 MyObject obj1 = MyObject.createObject();
7160 MyObject obj2 = MyObject.createObject();
7161 return obj1.accessFields(77,
7162 0x8000000000000000,
7163 true,
7164 3.14,
7165 str,
7166 extstr,
7167 obj2);
7168})";
7169
7171
7172 const char* ascii_str = "string";
7173 intptr_t ascii_str_length = strlen(ascii_str);
7175 reinterpret_cast<const uint8_t*>(ascii_str), ascii_str_length);
7176
7177 Dart_Handle args[1];
7178 args[0] = str;
7179 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 1, args);
7182}
7183
7189}
7190
7192 int argument_count,
7193 bool* auto_setup_scope) {
7194 ASSERT(auto_setup_scope != nullptr);
7195 *auto_setup_scope = true;
7197}
7198
7199TEST_CASE(DartAPI_GetNativeArgumentCount) {
7200 const char* kScriptChars = R"(
7201class MyObject {
7202 @pragma("vm:external-name", "Name_Does_Not_Matter")
7203 external int method1(int i, int j);
7204}
7205testMain() {
7206 MyObject obj = new MyObject();
7207 return obj.method1(77, 125);
7208})";
7209
7211
7212 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
7215
7216 int64_t value = 0;
7219 EXPECT_EQ(3, value);
7220}
7221
7222TEST_CASE(DartAPI_TypeToNullability) {
7223 const char* kScriptChars =
7224 "library testlib;\n"
7225 "class Class {\n"
7226 " static var name = 'Class';\n"
7227 "}\n";
7228
7229 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7230
7231 const Dart_Handle name = NewString("Class");
7232 // Lookup the legacy type for Class.
7233 Dart_Handle type = Dart_GetType(lib, name, 0, nullptr);
7235 "Cannot use legacy types with --sound-null-safety enabled. "
7236 "Use Dart_GetNullableType or Dart_GetNonNullableType instead.");
7237
7238 Dart_Handle nonNullableType = Dart_GetNonNullableType(lib, name, 0, nullptr);
7239 EXPECT_VALID(nonNullableType);
7240 Dart_Handle nullableType = Dart_GetNullableType(lib, name, 0, nullptr);
7241 EXPECT_VALID(nullableType);
7242
7243 // Nullable -> Non-Nullable
7245 nonNullableType,
7247
7248 // Non-Nullable -> Nullable
7250 nullableType,
7252}
7253
7254TEST_CASE(DartAPI_GetNullableType) {
7255 const char* kScriptChars =
7256 "library testlib;\n"
7257 "class Class {\n"
7258 " static var name = 'Class';\n"
7259 "}\n"
7260 "\n"
7261 "class _Class {\n"
7262 " static var name = '_Class';\n"
7263 "}\n";
7264
7265 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7266
7267 // Lookup a class.
7268 Dart_Handle type = Dart_GetNullableType(lib, NewString("Class"), 0, nullptr);
7270 bool result = false;
7272 EXPECT(result);
7275 const char* name_cstr = "";
7277 EXPECT_STREQ("Class?", name_cstr);
7278
7279 name = Dart_GetField(type, NewString("name"));
7282 EXPECT_STREQ("Class", name_cstr);
7283
7284 // Lookup a private class.
7285 type = Dart_GetNullableType(lib, NewString("_Class"), 0, nullptr);
7287 result = false;
7289
7290 name = Dart_GetField(type, NewString("name"));
7292 name_cstr = "";
7294 EXPECT_STREQ("_Class", name_cstr);
7295
7296 // Lookup a class that does not exist.
7297 type = Dart_GetNullableType(lib, NewString("DoesNotExist"), 0, nullptr);
7299 EXPECT_STREQ("Type 'DoesNotExist' not found in library 'testlib'.",
7301
7302 // Lookup a class from an error library. The error propagates.
7303 type = Dart_GetNullableType(Api::NewError("myerror"), NewString("Class"), 0,
7304 nullptr);
7306 EXPECT_STREQ("myerror", Dart_GetError(type));
7307
7308 // Lookup a type using an error class name. The error propagates.
7309 type = Dart_GetNullableType(lib, Api::NewError("myerror"), 0, nullptr);
7311 EXPECT_STREQ("myerror", Dart_GetError(type));
7312}
7313
7314TEST_CASE(DartAPI_GetNonNullableType) {
7315 const char* kScriptChars =
7316 "library testlib;\n"
7317 "class Class {\n"
7318 " static var name = 'Class';\n"
7319 "}\n"
7320 "\n"
7321 "class _Class {\n"
7322 " static var name = '_Class';\n"
7323 "}\n";
7324
7325 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7326
7327 // Lookup a class.
7329 Dart_GetNonNullableType(lib, NewString("Class"), 0, nullptr);
7331 bool result = false;
7333 EXPECT(result);
7336 const char* name_cstr = "";
7338 EXPECT_STREQ("Class", name_cstr);
7339
7340 name = Dart_GetField(type, NewString("name"));
7343 EXPECT_STREQ("Class", name_cstr);
7344
7345 // Lookup a private class.
7346 type = Dart_GetNonNullableType(lib, NewString("_Class"), 0, nullptr);
7348 result = false;
7350 EXPECT(result);
7351
7352 name = Dart_GetField(type, NewString("name"));
7354 name_cstr = "";
7356 EXPECT_STREQ("_Class", name_cstr);
7357
7358 // Lookup a class that does not exist.
7359 type = Dart_GetNonNullableType(lib, NewString("DoesNotExist"), 0, nullptr);
7361 EXPECT_STREQ("Type 'DoesNotExist' not found in library 'testlib'.",
7363
7364 // Lookup a class from an error library. The error propagates.
7365 type = Dart_GetNonNullableType(Api::NewError("myerror"), NewString("Class"),
7366 0, nullptr);
7368 EXPECT_STREQ("myerror", Dart_GetError(type));
7369
7370 // Lookup a type using an error class name. The error propagates.
7371 type = Dart_GetNonNullableType(lib, Api::NewError("myerror"), 0, nullptr);
7373 EXPECT_STREQ("myerror", Dart_GetError(type));
7374}
7375
7376TEST_CASE(DartAPI_InstanceOf) {
7377 const char* kScriptChars =
7378 "class OtherClass {\n"
7379 " static returnNull() { return null; }\n"
7380 "}\n"
7381 "class InstanceOfTest {\n"
7382 " InstanceOfTest() {}\n"
7383 " static InstanceOfTest testMain() {\n"
7384 " return new InstanceOfTest();\n"
7385 " }\n"
7386 "}\n";
7388 // Create a test library and Load up a test script in it.
7389 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7390
7391 // Fetch InstanceOfTest class.
7393 Dart_GetNonNullableType(lib, NewString("InstanceOfTest"), 0, nullptr);
7395
7396 // Invoke a function which returns an object of type InstanceOf..
7397 Dart_Handle instanceOfTestObj =
7398 Dart_Invoke(type, NewString("testMain"), 0, nullptr);
7399 EXPECT_VALID(instanceOfTestObj);
7400
7401 // Now check instanceOfTestObj reported as an instance of
7402 // InstanceOfTest class.
7403 bool is_instance = false;
7404 result = Dart_ObjectIsType(instanceOfTestObj, type, &is_instance);
7406 EXPECT(is_instance);
7407
7408 // Fetch OtherClass and check if instanceOfTestObj is instance of it.
7409 Dart_Handle otherType =
7410 Dart_GetNonNullableType(lib, NewString("OtherClass"), 0, nullptr);
7411 EXPECT_VALID(otherType);
7412
7413 result = Dart_ObjectIsType(instanceOfTestObj, otherType, &is_instance);
7415 EXPECT(!is_instance);
7416
7417 // Check that primitives are not instances of InstanceOfTest class.
7418 result = Dart_ObjectIsType(NewString("a string"), otherType, &is_instance);
7420 EXPECT(!is_instance);
7421
7422 result = Dart_ObjectIsType(Dart_NewInteger(42), otherType, &is_instance);
7424 EXPECT(!is_instance);
7425
7426 result = Dart_ObjectIsType(Dart_NewBoolean(true), otherType, &is_instance);
7428 EXPECT(!is_instance);
7429
7430 // Check that null is not an instance of InstanceOfTest class.
7431 Dart_Handle null =
7432 Dart_Invoke(otherType, NewString("returnNull"), 0, nullptr);
7433 EXPECT_VALID(null);
7434
7435 result = Dart_ObjectIsType(null, otherType, &is_instance);
7437 EXPECT(!is_instance);
7438
7439 // Check that error is returned if null is passed as a class argument.
7440 result = Dart_ObjectIsType(null, null, &is_instance);
7442}
7443
7444TEST_CASE(DartAPI_RootLibrary) {
7445 const char* kScriptChars =
7446 "library testlib;"
7447 "main() {"
7448 " return 12345;"
7449 "}";
7450
7451 Dart_Handle root_lib = Dart_RootLibrary();
7452 EXPECT_VALID(root_lib);
7453 EXPECT(Dart_IsNull(root_lib));
7454
7455 // Load a script.
7456 EXPECT_VALID(LoadScript(TestCase::url(), kScriptChars));
7457
7458 root_lib = Dart_RootLibrary();
7459 Dart_Handle lib_uri = Dart_LibraryUrl(root_lib);
7460 EXPECT_VALID(lib_uri);
7461 EXPECT(!Dart_IsNull(lib_uri));
7462 const char* uri_cstr = "";
7463 EXPECT_VALID(Dart_StringToCString(lib_uri, &uri_cstr));
7464 EXPECT_STREQ(TestCase::url(), uri_cstr);
7465
7466 Dart_Handle core_uri = Dart_NewStringFromCString("dart:core");
7467 Dart_Handle core_lib = Dart_LookupLibrary(core_uri);
7468 EXPECT_VALID(core_lib);
7469 EXPECT(Dart_IsLibrary(core_lib));
7470
7471 Dart_Handle result = Dart_SetRootLibrary(core_uri); // Not a library.
7473 root_lib = Dart_RootLibrary();
7474 lib_uri = Dart_LibraryUrl(root_lib);
7475 EXPECT_VALID(Dart_StringToCString(lib_uri, &uri_cstr));
7476 EXPECT_STREQ(TestCase::url(), uri_cstr); // Root library didn't change.
7477
7478 result = Dart_SetRootLibrary(core_lib);
7480 root_lib = Dart_RootLibrary();
7481 lib_uri = Dart_LibraryUrl(root_lib);
7482 EXPECT_VALID(Dart_StringToCString(lib_uri, &uri_cstr));
7483 EXPECT_STREQ("dart:core", uri_cstr); // Root library did change.
7484
7487 root_lib = Dart_RootLibrary();
7488 EXPECT(Dart_IsNull(root_lib)); // Root library did change.
7489}
7490
7491TEST_CASE(DartAPI_LookupLibrary) {
7492 const char* kScriptChars =
7493 "import 'library1_dart';"
7494 "main() {}";
7495 const char* kLibrary1 = "file:///library1_dart";
7496 const char* kLibrary1Chars =
7497 "library library1;"
7498 "final x = 0;";
7499
7500 Dart_Handle url;
7502
7503 // Create a test library and load up a test script in it.
7504 TestCase::AddTestLib("file:///library1_dart", kLibrary1Chars);
7505 // LoadTestScript resets the LibraryTagHandler, which we don't want when
7506 // using the VM compiler, so we only use it with the Dart frontend for this
7507 // test.
7508 result = TestCase::LoadTestScript(kScriptChars, nullptr, TestCase::url());
7510
7511 url = NewString(kLibrary1);
7514
7517 "Dart_LookupLibrary expects argument 'url' to be non-null.");
7518
7521 result,
7522 "Dart_LookupLibrary expects argument 'url' to be of type String.");
7523
7524 result = Dart_LookupLibrary(Dart_NewApiError("incoming error"));
7526 EXPECT_STREQ("incoming error", Dart_GetError(result));
7527
7528 url = NewString("noodles.dart");
7530 EXPECT_ERROR(result, "Dart_LookupLibrary: library 'noodles.dart' not found.");
7531}
7532
7533TEST_CASE(DartAPI_LibraryUrl) {
7534 const char* kLibrary1Chars = "library library1_name;";
7535 Dart_Handle lib = TestCase::LoadTestLibrary("library1_url", kLibrary1Chars);
7536 Dart_Handle error = Dart_NewApiError("incoming error");
7537 EXPECT_VALID(lib);
7538
7541 "Dart_LibraryUrl expects argument 'library' to be non-null.");
7542
7545 result,
7546 "Dart_LibraryUrl expects argument 'library' to be of type Library.");
7547
7550 EXPECT_STREQ("incoming error", Dart_GetError(result));
7551
7552 result = Dart_LibraryUrl(lib);
7555 const char* cstr = nullptr;
7557 EXPECT_SUBSTRING("library1_url", cstr);
7558}
7559
7564}
7565
7570}
7571
7573 int arg_count,
7574 bool* auto_setup_scope) {
7575 ASSERT(auto_setup_scope != nullptr);
7576 *auto_setup_scope = false;
7578}
7579
7581 int arg_count,
7582 bool* auto_setup_scope) {
7583 ASSERT(auto_setup_scope != nullptr);
7584 *auto_setup_scope = false;
7586}
7587
7588TEST_CASE(DartAPI_SetNativeResolver) {
7589 const char* kScriptChars =
7590 R"(
7591 class Test {
7592 @pragma('vm:external-name', 'SomeNativeFunction')
7593 external static foo();
7594
7595 @pragma('vm:external-name', 'SomeNativeFunction2')
7596 external static bar();
7597
7598 @pragma('vm:external-name', 'SomeNativeFunction3')
7599 external static baz();
7600 }
7601 )";
7602 Dart_Handle error = Dart_NewApiError("incoming error");
7604
7605 // Load a test script.
7606 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7607 EXPECT_VALID(lib);
7610 EXPECT(Dart_IsLibrary(lib));
7612 Dart_GetNonNullableType(lib, NewString("Test"), 0, nullptr);
7614
7617 result,
7618 "Dart_SetNativeResolver expects argument 'library' to be non-null.");
7619
7622 "Dart_SetNativeResolver expects argument 'library' to be of "
7623 "type Library.");
7624
7627 EXPECT_STREQ("incoming error", Dart_GetError(result));
7628
7631
7632 // Call a function and make sure native resolution works.
7633 result = Dart_Invoke(type, NewString("foo"), 0, nullptr);
7636 int64_t value = 0;
7638 EXPECT_EQ(654321, value);
7639
7640 // A second call succeeds.
7643
7644 // 'foo' has already been resolved so gets the old value.
7645 result = Dart_Invoke(type, NewString("foo"), 0, nullptr);
7648 value = 0;
7650 EXPECT_EQ(654321, value);
7651
7652 // 'bar' has not yet been resolved so gets the new value.
7653 result = Dart_Invoke(type, NewString("bar"), 0, nullptr);
7656 value = 0;
7658 EXPECT_EQ(123456, value);
7659
7660 // A nullptr resolver is okay, but resolution will fail.
7661 result = Dart_SetNativeResolver(lib, nullptr, nullptr);
7663
7664 EXPECT_ERROR(Dart_Invoke(type, NewString("baz"), 0, nullptr),
7665 "native function 'SomeNativeFunction3' (0 arguments) "
7666 "cannot be found");
7667}
7668
7669// Test that an imported name does not clash with the same name defined
7670// in the importing library.
7671TEST_CASE(DartAPI_ImportLibrary2) {
7672 const char* kScriptChars =
7673 "import 'library1_dart';\n"
7674 "var foo;\n"
7675 "main() { foo = 0; }\n";
7676 const char* kLibrary1Chars =
7677 "library library1_dart;\n"
7678 "import 'library2_dart';\n"
7679 "var foo;\n";
7680 const char* kLibrary2Chars =
7681 "library library2_dart;\n"
7682 "import 'library1_dart';\n"
7683 "var foo;\n";
7685 Dart_Handle lib;
7686
7687 // Create a test library and Load up a test script in it.
7688 Dart_SourceFile sourcefiles[] = {
7689 {RESOLVED_USER_TEST_URI, kScriptChars},
7690 {"file:///library1_dart", kLibrary1Chars},
7691 {"file:///library2_dart", kLibrary2Chars},
7693 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7694 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, nullptr,
7695 true);
7696 EXPECT_VALID(lib);
7697
7700 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
7702}
7703
7704// Test that if the same name is imported from two libraries, it is
7705// an error if that name is referenced.
7706TEST_CASE(DartAPI_ImportLibrary3) {
7707 const char* kScriptChars =
7708 "import 'file:///library2_dart';\n"
7709 "import 'file:///library1_dart';\n"
7710 "var foo_top = 10; // foo has dup def. So should be an error.\n"
7711 "main() { foo = 0; }\n";
7712 const char* kLibrary1Chars =
7713 "library library1_dart;\n"
7714 "var foo;";
7715 const char* kLibrary2Chars =
7716 "library library2_dart;\n"
7717 "var foo;";
7719 Dart_Handle lib;
7720
7721 // Create a test library and Load up a test script in it.
7722 Dart_SourceFile sourcefiles[] = {
7723 {RESOLVED_USER_TEST_URI, kScriptChars},
7724 {"file:///library2_dart", kLibrary2Chars},
7725 {"file:///library1_dart", kLibrary1Chars},
7726 };
7727 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7728 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, nullptr,
7729 true);
7731 "Compilation failed /test-lib:4:10:"
7732 " Error: Setter not found: 'foo'");
7733 return;
7734
7737 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
7739 EXPECT_SUBSTRING("NoSuchMethodError", Dart_GetError(result));
7740}
7741
7742// Test that if the same name is imported from two libraries, it is
7743// not an error if that name is not used.
7744TEST_CASE(DartAPI_ImportLibrary4) {
7745 const char* kScriptChars =
7746 "import 'library2_dart';\n"
7747 "import 'library1_dart';\n"
7748 "main() { }\n";
7749 const char* kLibrary1Chars =
7750 "library library1_dart;\n"
7751 "var foo;";
7752 const char* kLibrary2Chars =
7753 "library library2_dart;\n"
7754 "var foo;";
7756 Dart_Handle lib;
7757
7758 // Create a test library and Load up a test script in it.
7759 Dart_SourceFile sourcefiles[] = {
7760 {RESOLVED_USER_TEST_URI, kScriptChars},
7761 {"file:///library2_dart", kLibrary2Chars},
7762 {"file:///library1_dart", kLibrary1Chars},
7763 };
7764 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7765 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, nullptr,
7766 true);
7767 EXPECT_VALID(lib);
7768
7771 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
7773}
7774
7775TEST_CASE(DartAPI_ImportLibrary5) {
7776 const char* kScriptChars =
7777 "import 'lib.dart';\n"
7778 "abstract class Y {\n"
7779 " void set handler(void callback(List<int> x));\n"
7780 "}\n"
7781 "void main() {}\n";
7782 const char* kLibraryChars =
7783 "library lib.dart;\n"
7784 "abstract class X {\n"
7785 " void set handler(void callback(List<int> x));\n"
7786 "}\n";
7788 Dart_Handle lib;
7789
7790 // Create a test library and Load up a test script in it.
7791 Dart_SourceFile sourcefiles[] = {
7792 {RESOLVED_USER_TEST_URI, kScriptChars},
7793 {"file:///lib.dart", kLibraryChars},
7794 };
7795 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7796 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, nullptr,
7797 true);
7798 EXPECT_VALID(lib);
7799
7802 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
7804}
7805
7806TEST_CASE(DartAPI_Multiroot_Valid) {
7807 const char* kScriptChars =
7808 "import 'lib.dart';\n"
7809 "void main() {}\n";
7810 const char* kLibraryChars = "library lib.dart;\n";
7812 Dart_Handle lib;
7813
7814 Dart_SourceFile sourcefiles[] = {
7815 {"file:///bar/main.dart", kScriptChars},
7816 {"file:///baz/lib.dart", kLibraryChars},
7817 {"file:///bar/.packages", ""},
7818 };
7819 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7821 sourcefiles_count, sourcefiles, nullptr, /* finalize= */ true,
7822 /* incrementally= */ true, /* allow_compile_errors= */ false,
7823 "foo:///main.dart",
7824 /* multiroot_filepaths= */ "/bar,/baz",
7825 /* multiroot_scheme= */ "foo");
7826 EXPECT_VALID(lib);
7827 {
7828 TransitionNativeToVM transition(thread);
7829 Library& lib_obj = Library::Handle();
7830 lib_obj ^= Api::UnwrapHandle(lib);
7831 EXPECT_STREQ("foo:///main.dart", String::Handle(lib_obj.url()).ToCString());
7832 const Array& lib_scripts = Array::Handle(lib_obj.LoadedScripts());
7833 Script& script = Script::Handle();
7835 for (intptr_t i = 0; i < lib_scripts.Length(); i++) {
7836 script ^= lib_scripts.At(i);
7837 uri = script.url();
7838 const char* uri_str = uri.ToCString();
7839 EXPECT(strstr(uri_str, "foo:///") == uri_str);
7840 }
7841 }
7844 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
7846}
7847
7848TEST_CASE(DartAPI_Multiroot_FailWhenUriIsWrong) {
7849 const char* kScriptChars =
7850 "import 'lib.dart';\n"
7851 "void main() {}\n";
7852 const char* kLibraryChars = "library lib.dart;\n";
7853 Dart_Handle lib;
7854
7855 Dart_SourceFile sourcefiles[] = {
7856 {"file:///bar/main.dart", kScriptChars},
7857 {"file:///baz/lib.dart", kLibraryChars},
7858 {"file:///bar/.packages", "untitled:/"},
7859 };
7860 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7862 sourcefiles_count, sourcefiles, nullptr, /* finalize= */ true,
7863 /* incrementally= */ true, /* allow_compile_errors= */ false,
7864 "foo1:///main.dart",
7865 /* multiroot_filepaths= */ "/bar,/baz",
7866 /* multiroot_scheme= */ "foo");
7867 EXPECT_ERROR(lib,
7868 "Compilation failed Invalid argument(s): Exception when reading "
7869 "'foo1:///.dart_tool");
7870}
7871
7872static void NewNativePort_send123(Dart_Port dest_port_id,
7874 // Gets a send port message.
7875 EXPECT_NOTNULL(message);
7876 EXPECT_EQ(Dart_CObject_kArray, message->type);
7877 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
7878
7879 // Post integer value.
7880 Dart_CObject* response =
7881 reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
7882 response->type = Dart_CObject_kInt32;
7883 response->value.as_int32 = 123;
7884 Dart_PostCObject(message->value.as_array.values[0]->value.as_send_port.id,
7885 response);
7886}
7887
7888static void NewNativePort_send321(Dart_Port dest_port_id,
7890 // Gets a null message.
7891 EXPECT_NOTNULL(message);
7892 EXPECT_EQ(Dart_CObject_kArray, message->type);
7893 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
7894
7895 // Post integer value.
7896 Dart_CObject* response =
7897 reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
7898 response->type = Dart_CObject_kInt32;
7899 response->value.as_int32 = 321;
7900 Dart_PostCObject(message->value.as_array.values[0]->value.as_send_port.id,
7901 response);
7903
7904TEST_CASE(DartAPI_IllegalNewSendPort) {
7908}
7909
7910TEST_CASE(DartAPI_IllegalPost) {
7912 bool success = Dart_Post(ILLEGAL_PORT, message);
7913 EXPECT(!success);
7914}
7915
7916static void UnreachableFinalizer(void* isolate_callback_data, void* peer) {
7917 UNREACHABLE();
7918}
7919
7920TEST_CASE(DartAPI_PostCObject_DoesNotRunFinalizerOnFailure) {
7921 char* my_str =
7922 Utils::StrDup("Ownership of this memory remains with the caller");
7923
7926 message.value.as_external_typed_data.type = Dart_TypedData_kUint8;
7927 message.value.as_external_typed_data.length = strlen(my_str);
7928 message.value.as_external_typed_data.data =
7929 reinterpret_cast<uint8_t*>(my_str);
7930 message.value.as_external_typed_data.peer = my_str;
7931 message.value.as_external_typed_data.callback = UnreachableFinalizer;
7932
7933 bool success = Dart_PostCObject(ILLEGAL_PORT, &message);
7934 EXPECT(!success);
7935
7936 free(my_str); // Never a double-free.
7937}
7938
7939VM_UNIT_TEST_CASE(DartAPI_NewNativePort) {
7940 // Create a port with a bogus handler.
7941 Dart_Port error_port = Dart_NewNativePort("Foo", nullptr, true);
7942 EXPECT_EQ(ILLEGAL_PORT, error_port);
7943
7944 // Create the port w/o a current isolate, just to make sure that works.
7945 Dart_Port port_id1 =
7946 Dart_NewNativePort("Port123", NewNativePort_send123, true);
7947
7948 TestIsolateScope __test_isolate__;
7949 const char* kScriptChars =
7950 "import 'dart:isolate';\n"
7951 "void callPort(SendPort port) {\n"
7952 " var receivePort = new RawReceivePort();\n"
7953 " var replyPort = receivePort.sendPort;\n"
7954 " port.send(<dynamic>[replyPort]);\n"
7955 " receivePort.handler = (message) {\n"
7956 " receivePort.close();\n"
7957 " throw new Exception(message);\n"
7958 " };\n"
7959 "}\n";
7960 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7962
7963 // Create a port w/ a current isolate, to make sure that works too.
7964 Dart_Port port_id2 =
7965 Dart_NewNativePort("Port321", NewNativePort_send321, true);
7966
7967 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
7968 EXPECT_VALID(send_port1);
7969 Dart_Handle send_port2 = Dart_NewSendPort(port_id2);
7970 EXPECT_VALID(send_port2);
7971
7972 // Test first port.
7973 Dart_Handle dart_args[1];
7974 dart_args[0] = send_port1;
7975 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
7977 result = Dart_RunLoop();
7980 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
7981
7982 // result second port.
7983 dart_args[0] = send_port2;
7984 result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
7986 result = Dart_RunLoop();
7989 EXPECT_SUBSTRING("Exception: 321\n", Dart_GetError(result));
7990
7992
7993 // Delete the native ports.
7994 EXPECT(Dart_CloseNativePort(port_id1));
7995 EXPECT(Dart_CloseNativePort(port_id2));
7997
7998static void NewNativePort_sendInteger123(Dart_Port dest_port_id,
8000 // Gets a send port message.
8001 EXPECT_NOTNULL(message);
8002 EXPECT_EQ(Dart_CObject_kArray, message->type);
8003 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
8004
8005 // Post integer value.
8006 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
8007 123);
8009
8010static void NewNativePort_sendInteger321(Dart_Port dest_port_id,
8012 // Gets a null message.
8013 EXPECT_NOTNULL(message);
8014 EXPECT_EQ(Dart_CObject_kArray, message->type);
8015 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
8016
8017 // Post integer value.
8018 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
8019 321);
8020}
8021
8022TEST_CASE(DartAPI_NativePortPostInteger) {
8023 const char* kScriptChars =
8024 "import 'dart:isolate';\n"
8025 "void callPort(SendPort port) {\n"
8026 " var receivePort = new RawReceivePort();\n"
8027 " var replyPort = receivePort.sendPort;\n"
8028 " port.send(<dynamic>[replyPort]);\n"
8029 " receivePort.handler = (message) {\n"
8030 " receivePort.close();\n"
8031 " throw new Exception(message);\n"
8032 " };\n"
8033 "}\n";
8034 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8036
8037 Dart_Port port_id1 =
8039 Dart_Port port_id2 =
8041
8042 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
8043 EXPECT_VALID(send_port1);
8044 Dart_Handle send_port2 = Dart_NewSendPort(port_id2);
8045 EXPECT_VALID(send_port2);
8046
8047 // Test first port.
8048 Dart_Handle dart_args[1];
8049 dart_args[0] = send_port1;
8050 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8052 result = Dart_RunLoop();
8055 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
8056
8057 // result second port.
8058 dart_args[0] = send_port2;
8059 result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8061 result = Dart_RunLoop();
8064 EXPECT_SUBSTRING("Exception: 321\n", Dart_GetError(result));
8065
8067
8068 // Delete the native ports.
8069 EXPECT(Dart_CloseNativePort(port_id1));
8071}
8072
8073static void NewNativePort_Transferrable1(Dart_Port dest_port_id,
8075 // Gets a send port message.
8076 EXPECT_NOTNULL(message);
8077 EXPECT_EQ(Dart_CObject_kTypedData, message->type);
8078 EXPECT_EQ(Dart_TypedData_kUint8, message->value.as_typed_data.type);
8079 EXPECT_EQ(10, message->value.as_typed_data.length);
8080 EXPECT_EQ(42, message->value.as_typed_data.values[0]);
8081 free(const_cast<uint8_t*>(message->value.as_typed_data.values));
8082}
8083
8086 // Gets a send port message.
8087 EXPECT_NOTNULL(message);
8088 EXPECT_EQ(Dart_CObject_kArray, message->type);
8089 EXPECT_EQ(1, message->value.as_array.length);
8090 Dart_CObject* cobj = message->value.as_array.values[0];
8091 EXPECT_EQ(Dart_CObject_kTypedData, cobj->type);
8093 EXPECT_EQ(10, cobj->value.as_typed_data.length);
8094 EXPECT_EQ(42, cobj->value.as_typed_data.values[0]);
8095 free(const_cast<uint8_t*>(cobj->value.as_typed_data.values));
8096}
8097
8098TEST_CASE(DartAPI_NativePortPostTransferrableTypedData) {
8099 const char* kScriptChars =
8100 "import 'dart:typed_data';\n"
8101 "import 'dart:isolate';\n"
8102 "void callPort(SendPort port1, SendPort port2) {\n"
8103 " final td1 ="
8104 " TransferableTypedData.fromList([Uint8List(10)..[0] = 42]);\n"
8105 " final td2 ="
8106 " TransferableTypedData.fromList([Uint8List(10)..[0] = 42]);\n"
8107 " port1.send(td1);\n"
8108 " port2.send([td2]);\n"
8109 "}\n";
8110 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8112
8113 Dart_Port port_id1 =
8115 Dart_Port port_id2 =
8117
8118 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
8119 EXPECT_VALID(send_port1);
8120 Dart_Handle send_port2 = Dart_NewSendPort(port_id2);
8121 EXPECT_VALID(send_port2);
8122
8123 // Test first port.
8124 Dart_Handle dart_args[2];
8125 dart_args[0] = send_port1;
8126 dart_args[1] = send_port2;
8127 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 2, dart_args);
8129 result = Dart_RunLoop();
8131
8133
8134 // Delete the native ports.
8135 EXPECT(Dart_CloseNativePort(port_id1));
8136 EXPECT(Dart_CloseNativePort(port_id2));
8137}
8138
8139static constexpr intptr_t kSendLength = 16;
8140
8141static void NewNativePort_ExternalTypedData(Dart_Port dest_port_id,
8143 // Gets a send port message.
8144 EXPECT_NOTNULL(message);
8145 EXPECT_EQ(Dart_CObject_kTypedData, message->type);
8146 EXPECT_EQ(Dart_TypedData_kUint8, message->value.as_typed_data.type);
8147 EXPECT_EQ(kSendLength, message->value.as_typed_data.length);
8148 for (intptr_t i = 0; i < kSendLength; i++) {
8149 EXPECT_EQ((0x41 + i), message->value.as_typed_data.values[i]);
8150 }
8151}
8152
8153static void FinalizeTypedData(void* isolate_callback_data, void* peer) {
8154 delete[] reinterpret_cast<int8_t*>(peer);
8155}
8156
8157TEST_CASE(DartAPI_NativePortPostExternalTypedData) {
8158 int8_t* extTypedData = new int8_t[kSendLength];
8159 for (int i = 0; i < kSendLength; i++) {
8160 extTypedData[i] = 0x41 + i;
8161 }
8162 const char* kScriptChars =
8163 "import 'dart:typed_data';\n"
8164 "import 'dart:isolate';\n"
8165 "void callPort(SendPort port, Uint8List data) {\n"
8166 " port.send(data);\n"
8167 "}\n";
8168 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8170
8171 Dart_Port port_id =
8173
8174 Dart_Handle send_port = Dart_NewSendPort(port_id);
8175 EXPECT_VALID(send_port);
8176
8178 Dart_TypedData_kUint8, extTypedData, kSendLength, extTypedData,
8180 EXPECT_VALID(extdata);
8181
8182 // Test first port.
8183 Dart_Handle dart_args[2];
8184 dart_args[0] = send_port;
8185 dart_args[1] = extdata;
8186 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 2, dart_args);
8190
8192
8193 // Delete the native ports.
8194 EXPECT(Dart_CloseNativePort(port_id));
8195}
8196
8197static void UnreachableMessageHandler(Dart_Port dest_port_id,
8199 UNREACHABLE();
8200}
8201
8202TEST_CASE(DartAPI_NativePortPostUserClass) {
8203 const char* kScriptChars =
8204 "import 'dart:isolate';\n"
8205 "class ABC {}\n"
8206 "void callPort(SendPort port) {\n"
8207 " port.send(new ABC());\n"
8208 "}\n";
8209 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8211
8212 Dart_Port port_id =
8214
8215 // Test send with port open.
8216 {
8217 Dart_Handle send_port = Dart_NewSendPort(port_id);
8218 EXPECT_VALID(send_port);
8219 Dart_Handle dart_args[1];
8220 dart_args[0] = send_port;
8221 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8222 EXPECT_ERROR(result, "Invalid argument");
8223 }
8224
8225 // Test send with port closed.
8226 {
8227 Dart_CloseNativePort(port_id);
8228 Dart_Handle send_port = Dart_NewSendPort(port_id);
8229 EXPECT_VALID(send_port);
8230 Dart_Handle dart_args[1];
8231 dart_args[0] = send_port;
8232 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8233 EXPECT_ERROR(result, "Invalid argument");
8234 }
8235
8237}
8238
8241 EXPECT_NOTNULL(message);
8242
8243 if ((message->type == Dart_CObject_kArray) &&
8244 (message->value.as_array.values[0]->type == Dart_CObject_kSendPort)) {
8245 // Post integer value.
8246 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
8247 123);
8248 } else {
8249 EXPECT_EQ(message->type, Dart_CObject_kNull);
8250 }
8251}
8252
8253TEST_CASE(DartAPI_NativePortReceiveNull) {
8254 const char* kScriptChars =
8255 "import 'dart:isolate';\n"
8256 "void callPort(SendPort port) {\n"
8257 " var receivePort = new RawReceivePort();\n"
8258 " var replyPort = receivePort.sendPort;\n"
8259 " port.send(null);\n"
8260 " port.send(<dynamic>[replyPort]);\n"
8261 " receivePort.handler = (message) {\n"
8262 " receivePort.close();\n"
8263 " throw new Exception(message);\n"
8264 " };\n"
8265 "}\n";
8266 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8268
8269 Dart_Port port_id1 =
8271 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
8272 EXPECT_VALID(send_port1);
8273
8274 // Test first port.
8275 Dart_Handle dart_args[1];
8276 dart_args[0] = send_port1;
8277 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8279 result = Dart_RunLoop();
8282 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
8283
8285
8286 // Delete the native ports.
8287 EXPECT(Dart_CloseNativePort(port_id1));
8288}
8289
8290static void NewNativePort_nativeReceiveInteger(Dart_Port dest_port_id,
8292 EXPECT_NOTNULL(message);
8293
8294 if ((message->type == Dart_CObject_kArray) &&
8295 (message->value.as_array.values[0]->type == Dart_CObject_kSendPort)) {
8296 // Post integer value.
8297 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
8298 123);
8299 } else {
8300 EXPECT_EQ(message->type, Dart_CObject_kInt32);
8301 EXPECT_EQ(message->value.as_int32, 321);
8302 }
8303}
8304
8305TEST_CASE(DartAPI_NativePortReceiveInteger) {
8306 const char* kScriptChars =
8307 "import 'dart:isolate';\n"
8308 "void callPort(SendPort port) {\n"
8309 " var receivePort = new RawReceivePort();\n"
8310 " var replyPort = receivePort.sendPort;\n"
8311 " port.send(321);\n"
8312 " port.send(<dynamic>[replyPort]);\n"
8313 " receivePort.handler = (message) {\n"
8314 " receivePort.close();\n"
8315 " throw new Exception(message);\n"
8316 " };\n"
8317 "}\n";
8318 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8320
8321 Dart_Port port_id1 =
8323 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
8324 EXPECT_VALID(send_port1);
8325
8326 // Test first port.
8327 Dart_Handle dart_args[1];
8328 dart_args[0] = send_port1;
8329 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8331 result = Dart_RunLoop();
8334 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
8335
8337
8338 // Delete the native ports.
8339 EXPECT(Dart_CloseNativePort(port_id1));
8340}
8341
8342static Dart_Isolate RunLoopTestCallback(const char* script_name,
8343 const char* main,
8344 const char* package_root,
8345 const char* package_config,
8347 void* data,
8348 char** error) {
8349 const char* kScriptChars =
8350 "import 'dart:isolate';\n"
8351 "void main(shouldThrowException) {\n"
8352 " var rp = new RawReceivePort();\n"
8353 " rp.handler = (msg) {\n"
8354 " rp.close();\n"
8355 " if (shouldThrowException) {\n"
8356 " throw new Exception('ExceptionFromTimer');\n"
8357 " }\n"
8358 " };\n"
8359 " rp.sendPort.send(1);\n"
8360 "}\n";
8361
8362 if (Dart_CurrentIsolate() != nullptr) {
8364 }
8365 Dart_Isolate isolate = TestCase::CreateTestIsolate(script_name);
8366 ASSERT(isolate != nullptr);
8367 if (Dart_IsServiceIsolate(isolate)) {
8368 return isolate;
8371 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8372 EXPECT_VALID(lib);
8377 char* err_msg = Dart_IsolateMakeRunnable(isolate);
8378 EXPECT(err_msg == nullptr);
8379 return isolate;
8380}
8381
8382// Common code for RunLoop_Success/RunLoop_Failure.
8383static void RunLoopTest(bool throw_exception) {
8386 Dart_Isolate isolate = RunLoopTestCallback(nullptr, nullptr, nullptr, nullptr,
8387 nullptr, nullptr, nullptr);
8388
8389 Dart_EnterIsolate(isolate);
8392 EXPECT_VALID(lib);
8393
8395 Dart_Handle args[1];
8396 args[0] = (throw_exception ? Dart_True() : Dart_False());
8397 result = Dart_Invoke(lib, NewString("main"), 1, args);
8399 result = Dart_RunLoop();
8400 if (throw_exception) {
8401 EXPECT_ERROR(result, "Exception: ExceptionFromTimer");
8402 } else {
8404 }
8405
8410}
8411
8412VM_UNIT_TEST_CASE(DartAPI_RunLoop_Success) {
8413 RunLoopTest(false);
8414}
8415
8416VM_UNIT_TEST_CASE(DartAPI_RunLoop_Exception) {
8417 RunLoopTest(true);
8418}
8419
8420static void* shutdown_isolate_group_data;
8421static void* shutdown_isolate_data;
8422static void* cleanup_isolate_group_data;
8423static void* cleanup_isolate_data;
8424
8425// Called on isolate shutdown time (which is still allowed to run Dart code)
8426static void IsolateShutdownTestCallback(void* group_data, void* isolate_data) {
8427 // Shutdown runs before cleanup.
8430
8431 // Shutdown must have a current isolate (since it is allowed to execute Dart
8432 // code)
8433 EXPECT(Dart_CurrentIsolate() != nullptr);
8434 EXPECT(Dart_CurrentIsolateGroupData() == group_data);
8435 EXPECT(Dart_CurrentIsolateData() == isolate_data);
8436
8437 shutdown_isolate_group_data = group_data;
8438 shutdown_isolate_data = isolate_data;
8439}
8440
8441// Called on isolate cleanup time (which is after the isolate has been
8442// destroyed)
8443static void IsolateCleanupTestCallback(void* group_data, void* isolate_data) {
8444 // Cleanup runs after shutdown.
8446 EXPECT(shutdown_isolate_data != nullptr);
8448 // The isolate was destroyed and there should not be a current isolate.
8449 EXPECT(Dart_CurrentIsolate() == nullptr);
8450
8451 cleanup_isolate_group_data = group_data;
8452 cleanup_isolate_data = isolate_data;
8453}
8454
8455// Called on isolate group cleanup time (once all isolates have been destroyed)
8456static void* cleanup_group_callback_data;
8457static void IsolateGroupCleanupTestCallback(void* callback_data) {
8458 cleanup_group_callback_data = callback_data;
8459}
8460
8461VM_UNIT_TEST_CASE(DartAPI_IsolateShutdownAndCleanup) {
8463 Dart_IsolateGroupCleanupCallback saved_cleanup =
8468
8470 shutdown_isolate_data = nullptr;
8472 void* my_group_data = reinterpret_cast<void*>(123);
8473 void* my_data = reinterpret_cast<void*>(456);
8474
8475 // Create an isolate.
8476 Dart_Isolate isolate =
8477 TestCase::CreateTestIsolate(nullptr, my_group_data, my_data);
8478 EXPECT(isolate != nullptr);
8479
8480 // The shutdown callback has not been called.
8481 EXPECT(nullptr == shutdown_isolate_data);
8484
8485 // The isolate is the active isolate which allows us to access the isolate
8486 // specific and isolate-group specific data.
8487 EXPECT(Dart_CurrentIsolateData() == my_data);
8488 EXPECT(Dart_CurrentIsolateGroupData() == my_group_data);
8489
8490 // Shutdown the isolate.
8492
8493 // The shutdown & cleanup callbacks have been called.
8494 EXPECT(my_data == shutdown_isolate_data);
8495 EXPECT(my_group_data == shutdown_isolate_group_data);
8496 EXPECT(my_data == cleanup_isolate_data);
8497 EXPECT(my_group_data == cleanup_isolate_group_data);
8498 EXPECT(my_group_data == cleanup_group_callback_data);
8499
8500 Isolate::SetShutdownCallback(saved_shutdown);
8501 Isolate::SetGroupCleanupCallback(saved_cleanup);
8502}
8503
8504static int64_t add_result = 0;
8505static void IsolateShutdownRunDartCodeTestCallback(void* isolate_group_data,
8506 void* isolate_data) {
8508 if (Dart_IsKernelIsolate(isolate) || Dart_IsServiceIsolate(isolate)) {
8509 return;
8510 } else {
8511 ASSERT(add_result == 0);
8512 }
8515 EXPECT_VALID(lib);
8516 Dart_Handle arg1 = Dart_NewInteger(90);
8517 EXPECT_VALID(arg1);
8518 Dart_Handle arg2 = Dart_NewInteger(9);
8519 EXPECT_VALID(arg2);
8520 Dart_Handle dart_args[2] = {arg1, arg2};
8521 Dart_Handle result = Dart_Invoke(lib, NewString("add"), 2, dart_args);
8526}
8527
8528VM_UNIT_TEST_CASE(DartAPI_IsolateShutdownRunDartCode) {
8529 const char* kScriptChars =
8530 "int add(int a, int b) {\n"
8531 " return a + b;\n"
8532 "}\n"
8533 "\n"
8534 "void main() {\n"
8535 " add(4, 5);\n"
8536 "}\n";
8537
8538 // Create an isolate.
8539 auto isolate = reinterpret_cast<Isolate*>(TestCase::CreateTestIsolate());
8540 EXPECT(isolate != nullptr);
8541
8542 isolate->set_on_shutdown_callback(IsolateShutdownRunDartCodeTestCallback);
8543
8544 {
8546 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8547 EXPECT_VALID(lib);
8552 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
8555 }
8556
8557 // The shutdown callback has not been called.
8558 EXPECT_EQ(0, add_result);
8559
8560 // Shutdown the isolate.
8562
8563 // The shutdown callback has been called and ran Dart code.
8564 EXPECT_EQ(99, add_result);
8565}
8566
8567static int64_t GetValue(Dart_Handle arg) {
8568 EXPECT_VALID(arg);
8569 EXPECT(Dart_IsInteger(arg));
8570 int64_t value;
8572 return value;
8573}
8574
8578 EXPECT_EQ(1, i);
8580 EXPECT_VALID(arg);
8583}
8584
8588 EXPECT_EQ(2, i);
8590 EXPECT_VALID(arg1);
8591 int64_t value = 0;
8593 int64_t integer_value = 0;
8596 EXPECT_EQ(value, integer_value);
8597 double double_value;
8598 result = Dart_GetNativeDoubleArgument(args, 1, &double_value);
8600 bool bool_value;
8601 result = Dart_GetNativeBooleanArgument(args, 1, &bool_value);
8605}
8606
8610 EXPECT_EQ(3, i);
8616
8620 EXPECT_EQ(4, i);
8625 args, Dart_NewInteger(GetValue(arg1) + GetValue(arg2) + GetValue(arg3)));
8627}
8628
8630 int arg_count,
8631 bool* auto_setup_scope) {
8632 ASSERT(auto_setup_scope != nullptr);
8633 *auto_setup_scope = false;
8634 TransitionNativeToVM transition(Thread::Current());
8635 const Object& obj = Object::Handle(Api::UnwrapHandle(name));
8636 if (!obj.IsString()) {
8637 return nullptr;
8638 }
8639 const char* function_name = obj.ToCString();
8640 const char* kNativeFoo1 = "NativeFoo1";
8641 const char* kNativeFoo2 = "NativeFoo2";
8642 const char* kNativeFoo3 = "NativeFoo3";
8643 const char* kNativeFoo4 = "NativeFoo4";
8644 if (strncmp(function_name, kNativeFoo1, strlen(kNativeFoo1)) == 0) {
8645 return &NativeFoo1;
8646 } else if (strncmp(function_name, kNativeFoo2, strlen(kNativeFoo2)) == 0) {
8647 return &NativeFoo2;
8648 } else if (strncmp(function_name, kNativeFoo3, strlen(kNativeFoo3)) == 0) {
8649 return &NativeFoo3;
8650 } else if (strncmp(function_name, kNativeFoo4, strlen(kNativeFoo4)) == 0) {
8651 return &NativeFoo4;
8652 } else {
8653 UNREACHABLE();
8654 return nullptr;
8655 }
8656}
8657
8658TEST_CASE(DartAPI_NativeFunctionClosure) {
8659 const char* kScriptChars =
8660 R"(
8661 class Test {
8662 @pragma('vm:external-name', 'NativeFoo1')
8663 external int foo1();
8664
8665 @pragma('vm:external-name', 'NativeFoo2')
8666 external int foo2(int i);
8668 @pragma('vm:external-name', 'NativeFoo3')
8669 external int foo3([int k = 10000, int l = 1]);
8670
8671 @pragma('vm:external-name', 'NativeFoo4')
8672 external int foo4(int i, [int j = 10, int k = 1]);
8673
8674 int bar1() { var func = foo1; return func(); }
8675 int bar2(int i) { var func = foo2; return func(i); }
8676 int bar30() { var func = foo3; return func(); }
8677 int bar31(int i) { var func = foo3; return func(i); }
8678 int bar32(int i, int j) { var func = foo3; return func(i, j); }
8679 int bar41(int i) {
8680 var func = foo4; return func(i); }
8681 int bar42(int i, int j) {
8682 var func = foo4; return func(i, j); }
8683 int bar43(int i, int j, int k) {
8684 var func = foo4; return func(i, j, k); }
8685 }
8686 class Expect {
8687 static equals(a, b) {
8688 if (a != b) {
8689 throw 'not equal. expected: $a, got: $b';
8690 }
8691 }
8692 }
8693 int testMain() {
8694 Test obj = new Test();
8695 Expect.equals(1, obj.foo1());
8696 Expect.equals(1, obj.bar1());
8697
8698 Expect.equals(10, obj.foo2(10));
8699 Expect.equals(10, obj.bar2(10));
8700
8701 Expect.equals(10001, obj.foo3());
8702 Expect.equals(10001, obj.bar30());
8703 Expect.equals(2, obj.foo3(1));
8704 Expect.equals(2, obj.bar31(1));
8705 Expect.equals(4, obj.foo3(2, 2));
8706 Expect.equals(4, obj.bar32(2, 2));
8707
8708 Expect.equals(12, obj.foo4(1));
8709 Expect.equals(12, obj.bar41(1));
8710 Expect.equals(3, obj.foo4(1, 1));
8711 Expect.equals(3, obj.bar42(1, 1));
8712 Expect.equals(6, obj.foo4(2, 2, 2));
8713 Expect.equals(6, obj.bar43(2, 2, 2));
8714
8715 return 0;
8716 }
8717 )";
8718
8720
8721 // Load a test script.
8722 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8723 EXPECT_VALID(lib);
8724 EXPECT(Dart_IsLibrary(lib));
8729
8730 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
8733 int64_t value = 0;
8735 EXPECT_EQ(0, value);
8737
8741 EXPECT_EQ(0, i);
8744}
8745
8749 EXPECT_EQ(1, i);
8753}
8754
8758 EXPECT_EQ(2, i);
8763}
8764
8768 EXPECT_EQ(3, i);
8773 args, Dart_NewInteger(GetValue(arg1) + GetValue(arg2) + GetValue(arg3)));
8775}
8776
8779 int arg_count,
8780 bool* auto_setup_scope) {
8781 ASSERT(auto_setup_scope != nullptr);
8782 *auto_setup_scope = false;
8783 TransitionNativeToVM transition(Thread::Current());
8785 if (!obj.IsString()) {
8786 return nullptr;
8787 }
8788 const char* function_name = obj.ToCString();
8789 const char* kNativeFoo1 = "StaticNativeFoo1";
8790 const char* kNativeFoo2 = "StaticNativeFoo2";
8791 const char* kNativeFoo3 = "StaticNativeFoo3";
8792 const char* kNativeFoo4 = "StaticNativeFoo4";
8793 if (strncmp(function_name, kNativeFoo1, strlen(kNativeFoo1)) == 0) {
8794 return &StaticNativeFoo1;
8795 } else if (strncmp(function_name, kNativeFoo2, strlen(kNativeFoo2)) == 0) {
8796 return &StaticNativeFoo2;
8797 } else if (strncmp(function_name, kNativeFoo3, strlen(kNativeFoo3)) == 0) {
8798 return &StaticNativeFoo3;
8799 } else if (strncmp(function_name, kNativeFoo4, strlen(kNativeFoo4)) == 0) {
8800 return &StaticNativeFoo4;
8801 } else {
8802 UNREACHABLE();
8803 return nullptr;
8804 }
8805}
8806
8807TEST_CASE(DartAPI_NativeStaticFunctionClosure) {
8808 const char* kScriptChars =
8809 R"(
8810 class Test {
8811 @pragma('vm:external-name', 'StaticNativeFoo1')
8812 external static int foo1();
8813
8814 @pragma('vm:external-name', 'StaticNativeFoo2')
8815 external static int foo2(int i);
8816
8817 @pragma('vm:external-name', 'StaticNativeFoo3')
8818 external static int foo3([int k = 10000, int l = 1]);
8819
8820 @pragma('vm:external-name', 'StaticNativeFoo4')
8821 external static int foo4(int i, [int j = 10, int k = 1]);
8822
8823 int bar1() { var func = foo1; return func(); }
8824 int bar2(int i) { var func = foo2; return func(i); }
8825 int bar30() { var func = foo3; return func(); }
8826 int bar31(int i) { var func = foo3; return func(i); }
8827 int bar32(int i, int j) { var func = foo3; return func(i, j); }
8828 int bar41(int i) {
8829 var func = foo4; return func(i); }
8830 int bar42(int i, int j) {
8831 var func = foo4; return func(i, j); }
8832 int bar43(int i, int j, int k) {
8833 var func = foo4; return func(i, j, k); }
8834 }
8835 class Expect {
8836 static equals(a, b) {
8837 if (a != b) {
8838 throw 'not equal. expected: $a, got: $b';
8839 }
8841 }
8842 int testMain() {
8843 Test obj = new Test();
8844 Expect.equals(0, Test.foo1());
8845 Expect.equals(0, obj.bar1());
8846
8847 Expect.equals(10, Test.foo2(10));
8848 Expect.equals(10, obj.bar2(10));
8849
8850 Expect.equals(10001, Test.foo3());
8851 Expect.equals(10001, obj.bar30());
8852 Expect.equals(2, Test.foo3(1));
8853 Expect.equals(2, obj.bar31(1));
8854 Expect.equals(4, Test.foo3(2, 2));
8855 Expect.equals(4, obj.bar32(2, 2));
8856
8857 Expect.equals(12, Test.foo4(1));
8858 Expect.equals(12, obj.bar41(1));
8859 Expect.equals(3, Test.foo4(1, 1));
8860 Expect.equals(3, obj.bar42(1, 1));
8861 Expect.equals(6, Test.foo4(2, 2, 2));
8862 Expect.equals(6, obj.bar43(2, 2, 2));
8863
8864 return 0;
8866 )";
8867
8869
8870 // Load a test script.
8871 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8872 EXPECT_VALID(lib);
8873 EXPECT(Dart_IsLibrary(lib));
8878
8879 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
8882 int64_t value = 0;
8884 EXPECT_EQ(0, value);
8885}
8886
8887TEST_CASE(DartAPI_RangeLimits) {
8888 uint8_t chars8[1] = {'a'};
8889 uint16_t chars16[1] = {'a'};
8890 int32_t chars32[1] = {'a'};
8891
8893 "expects argument 'length' to be in the range");
8895 "expects argument 'length' to be in the range");
8897 "expects argument 'length' to be in the range");
8899 "expects argument 'length' to be in the range");
8901 "expects argument 'length' to be in the range");
8904 "expects argument 'length' to be in the range");
8906 "expects argument 'length' to be in the range");
8909 "expects argument 'length' to be in the range");
8910}
8911
8912TEST_CASE(DartAPI_NewString_Null) {
8913 Dart_Handle str = Dart_NewStringFromUTF8(nullptr, 0);
8914 EXPECT_VALID(str);
8915 EXPECT(Dart_IsString(str));
8916 intptr_t len = -1;
8918 EXPECT_EQ(0, len);
8919
8920 str = Dart_NewStringFromUTF16(nullptr, 0);
8921 EXPECT_VALID(str);
8922 EXPECT(Dart_IsString(str));
8923 len = -1;
8925 EXPECT_EQ(0, len);
8926
8927 str = Dart_NewStringFromUTF32(nullptr, 0);
8928 EXPECT_VALID(str);
8929 EXPECT(Dart_IsString(str));
8930 len = -1;
8932 EXPECT_EQ(0, len);
8933}
8934
8935// Try to allocate a peer with a handles to objects of prohibited
8936// subtypes.
8937TEST_CASE(DartAPI_InvalidGetSetPeer) {
8938 void* out = &out;
8940 EXPECT(out == &out);
8944 EXPECT(out == &out);
8946 out = &out;
8948 EXPECT(out == &out);
8950 out = &out;
8953 EXPECT(out == &out);
8955 out = &out;
8956 Dart_Handle big = Dart_NewIntegerFromHexCString("0x10000000000000000");
8957 EXPECT(Dart_IsApiError(big));
8958 out = &out;
8959 Dart_Handle dbl = Dart_NewDouble(0.0);
8961 EXPECT(out == &out);
8963}
8964
8965// Allocates an object in new space and assigns it a peer. Removes
8966// the peer and checks that the count of peer objects is decremented
8967// by one.
8968TEST_CASE(DartAPI_OneNewSpacePeer) {
8969 Heap* heap = IsolateGroup::Current()->heap();
8970 Dart_Handle str = NewString("a string");
8971 EXPECT_VALID(str);
8972 EXPECT(Dart_IsString(str));
8973 EXPECT_EQ(0, heap->PeerCount());
8974 void* out = &out;
8976 EXPECT(out == nullptr);
8977 int peer = 1234;
8978 EXPECT_VALID(Dart_SetPeer(str, &peer));
8979 EXPECT_EQ(1, heap->PeerCount());
8980 out = &out;
8982 EXPECT(out == reinterpret_cast<void*>(&peer));
8983 EXPECT_VALID(Dart_SetPeer(str, nullptr));
8984 out = &out;
8986 EXPECT(out == nullptr);
8987 EXPECT_EQ(0, heap->PeerCount());
8988}
8989
8990// Allocates an object in new space and assigns it a peer. Allows the
8991// peer referent to be garbage collected and checks that the count of
8992// peer objects is decremented by one.
8993TEST_CASE(DartAPI_CollectOneNewSpacePeer) {
8994 Heap* heap = IsolateGroup::Current()->heap();
8996 {
8997 CHECK_API_SCOPE(thread);
8998 Dart_Handle str = NewString("a string");
8999 EXPECT_VALID(str);
9000 EXPECT(Dart_IsString(str));
9001 EXPECT_EQ(0, heap->PeerCount());
9002 void* out = &out;
9004 EXPECT(out == nullptr);
9005 int peer = 1234;
9006 EXPECT_VALID(Dart_SetPeer(str, &peer));
9007 EXPECT_EQ(1, heap->PeerCount());
9008 out = &out;
9010 EXPECT(out == reinterpret_cast<void*>(&peer));
9011 {
9012 TransitionNativeToVM transition(thread);
9013 GCTestHelper::CollectNewSpace();
9014 EXPECT_EQ(1, heap->PeerCount());
9015 }
9018 EXPECT(out == reinterpret_cast<void*>(&peer));
9019 }
9021 {
9022 TransitionNativeToVM transition(thread);
9023 GCTestHelper::CollectNewSpace();
9024 EXPECT_EQ(0, heap->PeerCount());
9025 }
9026}
9027
9028// Allocates two objects in new space and assigns them peers. Removes
9029// the peers and checks that the count of peer objects is decremented
9030// by two.
9031TEST_CASE(DartAPI_TwoNewSpacePeers) {
9032 Heap* heap = IsolateGroup::Current()->heap();
9033 Dart_Handle s1 = NewString("s1");
9034 EXPECT_VALID(s1);
9035 EXPECT(Dart_IsString(s1));
9036 void* o1 = &o1;
9037 EXPECT_VALID(Dart_GetPeer(s1, &o1));
9038 EXPECT(o1 == nullptr);
9039 EXPECT_EQ(0, heap->PeerCount());
9040 int p1 = 1234;
9041 EXPECT_VALID(Dart_SetPeer(s1, &p1));
9042 EXPECT_EQ(1, heap->PeerCount());
9043 EXPECT_VALID(Dart_GetPeer(s1, &o1));
9044 EXPECT(o1 == reinterpret_cast<void*>(&p1));
9045 Dart_Handle s2 = NewString("a string");
9046 EXPECT_VALID(s2);
9047 EXPECT(Dart_IsString(s2));
9048 EXPECT_EQ(1, heap->PeerCount());
9049 void* o2 = &o2;
9050 EXPECT(Dart_GetPeer(s2, &o2));
9051 EXPECT(o2 == nullptr);
9052 int p2 = 5678;
9053 EXPECT_VALID(Dart_SetPeer(s2, &p2));
9054 EXPECT_EQ(2, heap->PeerCount());
9055 EXPECT_VALID(Dart_GetPeer(s2, &o2));
9056 EXPECT(o2 == reinterpret_cast<void*>(&p2));
9058 EXPECT_EQ(1, heap->PeerCount());
9059 EXPECT(Dart_GetPeer(s1, &o1));
9060 EXPECT(o1 == nullptr);
9061 EXPECT_VALID(Dart_SetPeer(s2, nullptr));
9062 EXPECT_EQ(0, heap->PeerCount());
9063 EXPECT(Dart_GetPeer(s2, &o2));
9064 EXPECT(o2 == nullptr);
9065}
9066
9067// Allocates two objects in new space and assigns them a peer. Allow
9068// the peer referents to be garbage collected and check that the count
9069// of peer objects is decremented by two.
9070TEST_CASE(DartAPI_CollectTwoNewSpacePeers) {
9071 Heap* heap = IsolateGroup::Current()->heap();
9073 {
9074 CHECK_API_SCOPE(thread);
9075 Dart_Handle s1 = NewString("s1");
9076 EXPECT_VALID(s1);
9077 EXPECT(Dart_IsString(s1));
9078 EXPECT_EQ(0, heap->PeerCount());
9079 void* o1 = &o1;
9080 EXPECT(Dart_GetPeer(s1, &o1));
9081 EXPECT(o1 == nullptr);
9082 int p1 = 1234;
9083 EXPECT_VALID(Dart_SetPeer(s1, &p1));
9084 EXPECT_EQ(1, heap->PeerCount());
9085 EXPECT_VALID(Dart_GetPeer(s1, &o1));
9086 EXPECT(o1 == reinterpret_cast<void*>(&p1));
9087 Dart_Handle s2 = NewString("s2");
9088 EXPECT_VALID(s2);
9090 EXPECT_EQ(1, heap->PeerCount());
9091 void* o2 = &o2;
9092 EXPECT(Dart_GetPeer(s2, &o2));
9093 EXPECT(o2 == nullptr);
9094 int p2 = 5678;
9095 EXPECT_VALID(Dart_SetPeer(s2, &p2));
9096 EXPECT_EQ(2, heap->PeerCount());
9097 EXPECT_VALID(Dart_GetPeer(s2, &o2));
9098 EXPECT(o2 == reinterpret_cast<void*>(&p2));
9099 }
9101 {
9102 TransitionNativeToVM transition(thread);
9103 GCTestHelper::CollectNewSpace();
9104 EXPECT_EQ(0, heap->PeerCount());
9105 }
9106}
9107
9108// Allocates several objects in new space. Performs successive
9109// garbage collections and checks that the peer count is stable.
9110TEST_CASE(DartAPI_CopyNewSpacePeers) {
9111 const int kPeerCount = 10;
9112 Heap* heap = IsolateGroup::Current()->heap();
9113 Dart_Handle s[kPeerCount];
9114 for (int i = 0; i < kPeerCount; ++i) {
9115 s[i] = NewString("a string");
9116 EXPECT_VALID(s[i]);
9118 void* o = &o;
9120 EXPECT(o == nullptr);
9121 }
9122 EXPECT_EQ(0, heap->PeerCount());
9123 int p[kPeerCount];
9124 for (int i = 0; i < kPeerCount; ++i) {
9126 EXPECT_EQ(i + 1, heap->PeerCount());
9127 void* o = &o;
9129 EXPECT(o == reinterpret_cast<void*>(&p[i]));
9130 }
9131 EXPECT_EQ(kPeerCount, heap->PeerCount());
9132 {
9133 TransitionNativeToVM transition(thread);
9134 GCTestHelper::CollectNewSpace();
9135 EXPECT_EQ(kPeerCount, heap->PeerCount());
9136 GCTestHelper::CollectNewSpace();
9137 EXPECT_EQ(kPeerCount, heap->PeerCount());
9138 }
9139}
9140
9141// Allocates an object in new space and assigns it a peer. Promotes
9142// the peer to old space. Removes the peer and check that the count
9143// of peer objects is decremented by one.
9144TEST_CASE(DartAPI_OnePromotedPeer) {
9145 Heap* heap = IsolateGroup::Current()->heap();
9146 Dart_Handle str = NewString("a string");
9147 EXPECT_VALID(str);
9148 EXPECT(Dart_IsString(str));
9149 EXPECT_EQ(0, heap->PeerCount());
9150 void* out = &out;
9151 EXPECT(Dart_GetPeer(str, &out));
9152 EXPECT(out == nullptr);
9153 int peer = 1234;
9154 EXPECT_VALID(Dart_SetPeer(str, &peer));
9155 out = &out;
9156 EXPECT(Dart_GetPeer(str, &out));
9157 EXPECT(out == reinterpret_cast<void*>(&peer));
9158 EXPECT_EQ(1, heap->PeerCount());
9159 {
9160 TransitionNativeToVM transition(thread);
9161 GCTestHelper::CollectNewSpace();
9162 GCTestHelper::CollectNewSpace();
9163 }
9164 {
9165 CHECK_API_SCOPE(thread);
9166 TransitionNativeToVM transition(thread);
9167 HANDLESCOPE(thread);
9168 String& handle = String::Handle();
9169 handle ^= Api::UnwrapHandle(str);
9170 EXPECT(handle.IsOld());
9171 }
9173 EXPECT(out == reinterpret_cast<void*>(&peer));
9174 EXPECT_EQ(1, heap->PeerCount());
9175 EXPECT_VALID(Dart_SetPeer(str, nullptr));
9176 out = &out;
9178 EXPECT(out == nullptr);
9179 EXPECT_EQ(0, heap->PeerCount());
9180}
9181
9182// Allocates an object in old space and assigns it a peer. Removes
9183// the peer and checks that the count of peer objects is decremented
9184// by one.
9185TEST_CASE(DartAPI_OneOldSpacePeer) {
9186 Heap* heap = IsolateGroup::Current()->heap();
9187 Dart_Handle str = AllocateOldString("str");
9188 EXPECT_VALID(str);
9189 EXPECT(Dart_IsString(str));
9190 EXPECT_EQ(0, heap->PeerCount());
9191 void* out = &out;
9192 EXPECT(Dart_GetPeer(str, &out));
9193 EXPECT(out == nullptr);
9194 int peer = 1234;
9195 EXPECT_VALID(Dart_SetPeer(str, &peer));
9196 EXPECT_EQ(1, heap->PeerCount());
9197 out = &out;
9199 EXPECT(out == reinterpret_cast<void*>(&peer));
9200 {
9201 TransitionNativeToVM transition(thread);
9202 GCTestHelper::CollectOldSpace();
9203 EXPECT_EQ(1, heap->PeerCount());
9204 }
9206 EXPECT(out == reinterpret_cast<void*>(&peer));
9207 EXPECT_VALID(Dart_SetPeer(str, nullptr));
9208 out = &out;
9210 EXPECT(out == nullptr);
9211 EXPECT_EQ(0, heap->PeerCount());
9212}
9213
9214// Allocates an object in old space and assigns it a peer. Allow the
9215// peer referent to be garbage collected and check that the count of
9216// peer objects is decremented by one.
9217TEST_CASE(DartAPI_CollectOneOldSpacePeer) {
9218 Heap* heap = IsolateGroup::Current()->heap();
9220 {
9221 Thread* T = Thread::Current();
9223 Dart_Handle str = AllocateOldString("str");
9224 EXPECT_VALID(str);
9225 EXPECT(Dart_IsString(str));
9226 EXPECT_EQ(0, heap->PeerCount());
9227 void* out = &out;
9228 EXPECT(Dart_GetPeer(str, &out));
9229 EXPECT(out == nullptr);
9230 int peer = 1234;
9231 EXPECT_VALID(Dart_SetPeer(str, &peer));
9232 EXPECT_EQ(1, heap->PeerCount());
9233 out = &out;
9235 EXPECT(out == reinterpret_cast<void*>(&peer));
9236 {
9237 TransitionNativeToVM transition(thread);
9238 GCTestHelper::CollectOldSpace();
9239 EXPECT_EQ(1, heap->PeerCount());
9240 }
9242 EXPECT(out == reinterpret_cast<void*>(&peer));
9243 }
9245 {
9246 TransitionNativeToVM transition(thread);
9247 GCTestHelper::CollectOldSpace();
9248 EXPECT_EQ(0, heap->PeerCount());
9249 }
9250}
9251
9252// Allocates two objects in old space and assigns them peers. Removes
9253// the peers and checks that the count of peer objects is decremented
9254// by two.
9255TEST_CASE(DartAPI_TwoOldSpacePeers) {
9256 Heap* heap = IsolateGroup::Current()->heap();
9257 Dart_Handle s1 = AllocateOldString("s1");
9258 EXPECT_VALID(s1);
9259 EXPECT(Dart_IsString(s1));
9260 EXPECT_EQ(0, heap->PeerCount());
9261 void* o1 = &o1;
9262 EXPECT(Dart_GetPeer(s1, &o1));
9263 EXPECT(o1 == nullptr);
9264 int p1 = 1234;
9265 EXPECT_VALID(Dart_SetPeer(s1, &p1));
9266 EXPECT_EQ(1, heap->PeerCount());
9267 o1 = &o1;
9268 EXPECT_VALID(Dart_GetPeer(s1, &o1));
9269 EXPECT(o1 == reinterpret_cast<void*>(&p1));
9270 Dart_Handle s2 = AllocateOldString("s2");
9271 EXPECT_VALID(s2);
9272 EXPECT(Dart_IsString(s2));
9273 EXPECT_EQ(1, heap->PeerCount());
9274 void* o2 = &o2;
9275 EXPECT(Dart_GetPeer(s2, &o2));
9276 EXPECT(o2 == nullptr);
9277 int p2 = 5678;
9278 EXPECT_VALID(Dart_SetPeer(s2, &p2));
9279 EXPECT_EQ(2, heap->PeerCount());
9280 o2 = &o2;
9281 EXPECT_VALID(Dart_GetPeer(s2, &o2));
9282 EXPECT(o2 == reinterpret_cast<void*>(&p2));
9283 EXPECT_VALID(Dart_SetPeer(s1, nullptr));
9284 EXPECT_EQ(1, heap->PeerCount());
9285 o1 = &o1;
9286 EXPECT(Dart_GetPeer(s1, &o1));
9287 EXPECT(o1 == nullptr);
9288 EXPECT_VALID(Dart_SetPeer(s2, nullptr));
9289 EXPECT_EQ(0, heap->PeerCount());
9290 o2 = &o2;
9291 EXPECT_VALID(Dart_GetPeer(s2, &o2));
9292 EXPECT(o2 == nullptr);
9293}
9294
9295// Allocates two objects in old space and assigns them a peer. Allows
9296// the peer referents to be garbage collected and checks that the
9297// count of peer objects is decremented by two.
9298TEST_CASE(DartAPI_CollectTwoOldSpacePeers) {
9299 Heap* heap = IsolateGroup::Current()->heap();
9301 {
9302 Thread* T = Thread::Current();
9304 Dart_Handle s1 = AllocateOldString("s1");
9305 EXPECT_VALID(s1);
9306 EXPECT(Dart_IsString(s1));
9307 EXPECT_EQ(0, heap->PeerCount());
9308 void* o1 = &o1;
9309 EXPECT(Dart_GetPeer(s1, &o1));
9310 EXPECT(o1 == nullptr);
9311 int p1 = 1234;
9312 EXPECT_VALID(Dart_SetPeer(s1, &p1));
9313 EXPECT_EQ(1, heap->PeerCount());
9314 o1 = &o1;
9315 EXPECT_VALID(Dart_GetPeer(s1, &o1));
9316 EXPECT(o1 == reinterpret_cast<void*>(&p1));
9317 Dart_Handle s2 = AllocateOldString("s2");
9318 EXPECT_VALID(s2);
9319 EXPECT(Dart_IsString(s2));
9320 EXPECT_EQ(1, heap->PeerCount());
9321 void* o2 = &o2;
9322 EXPECT(Dart_GetPeer(s2, &o2));
9323 EXPECT(o2 == nullptr);
9324 int p2 = 5678;
9325 EXPECT_VALID(Dart_SetPeer(s2, &p2));
9326 EXPECT_EQ(2, heap->PeerCount());
9327 o2 = &o2;
9328 EXPECT_VALID(Dart_GetPeer(s2, &o2));
9329 EXPECT(o2 == reinterpret_cast<void*>(&p2));
9330 }
9332 {
9333 TransitionNativeToVM transition(thread);
9334 GCTestHelper::CollectOldSpace();
9335 EXPECT_EQ(0, heap->PeerCount());
9336 }
9337}
9338
9339TEST_CASE(DartAPI_StringFromExternalTypedData) {
9340 const char* kScriptChars =
9341 "test(external) {\n"
9342 " var str1 = new String.fromCharCodes(external);\n"
9343 " var str2 = new String.fromCharCodes(new List.from(external));\n"
9344 " if (str2 != str1) throw 'FAIL';\n"
9345 " return str1;\n"
9346 "}\n"
9347 "testView8(external) {\n"
9348 " return test(external.buffer.asUint8List());\n"
9349 "}\n"
9350 "testView16(external) {\n"
9351 " return test(external.buffer.asUint16List());\n"
9352 "}\n";
9353 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
9354
9355 {
9356 uint8_t data[64];
9357 for (int i = 0; i < 64; i++) {
9358 data[i] = i * 4;
9359 }
9360 // LATIN-1 in external Uint8List.
9361 Dart_Handle external =
9363 EXPECT_VALID(external);
9364 Dart_Handle dart_args[1];
9365 dart_args[0] = external;
9366 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 1, dart_args);
9369
9370 result = Dart_Invoke(lib, NewString("testView8"), 1, dart_args);
9373 }
9374
9375 {
9376 uint16_t data[64];
9377 for (int i = 0; i < 64; i++) {
9378 data[i] = i * 4;
9379 }
9380 // LATIN-1 in external Uint16List.
9381 Dart_Handle external =
9383 EXPECT_VALID(external);
9384 Dart_Handle dart_args[1];
9385 dart_args[0] = external;
9386 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 1, dart_args);
9389
9390 result = Dart_Invoke(lib, NewString("testView16"), 1, dart_args);
9393 }
9394
9395 {
9396 uint16_t data[64];
9397 for (int i = 0; i < 64; i++) {
9398 data[i] = 0x2000 + i * 4;
9399 }
9400 // Non-LATIN-1 in external Uint16List.
9401 Dart_Handle external =
9403 EXPECT_VALID(external);
9404 Dart_Handle dart_args[1];
9405 dart_args[0] = external;
9406 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 1, dart_args);
9409
9410 result = Dart_Invoke(lib, NewString("testView16"), 1, dart_args);
9413 }
9414}
9415
9416#ifndef PRODUCT
9417
9418TEST_CASE(DartAPI_TimelineDuration) {
9419 Isolate* isolate = Isolate::Current();
9420 // Grab embedder stream.
9421 TimelineStream* stream = Timeline::GetEmbedderStream();
9422 // Make sure it is enabled.
9423 stream->set_enabled(true);
9424 // Add a duration event.
9425 Dart_RecordTimelineEvent("testDurationEvent", 500, 1500, 0, nullptr,
9426 Dart_Timeline_Event_Duration, 0, nullptr, nullptr);
9427 // Check that it is in the output.
9428 TimelineEventRecorder* recorder = Timeline::recorder();
9429 JSONStream js;
9430 IsolateTimelineEventFilter filter(isolate->main_port());
9431 recorder->PrintJSON(&js, &filter);
9432 const char* json = js.ToCString();
9433 EXPECT_SUBSTRING("\"name\":\"testDurationEvent\"", json);
9434 EXPECT_SUBSTRING("\"ph\":\"X\"", json);
9435 EXPECT_SUBSTRING("\"ts\":500", json);
9436 EXPECT_SUBSTRING("\"dur\":1000", json);
9437}
9438
9439TEST_CASE(DartAPI_TimelineBegin) {
9440 Isolate* isolate = Isolate::Current();
9441 // Grab embedder stream.
9442 TimelineStream* stream = Timeline::GetEmbedderStream();
9443 // Make sure it is enabled.
9444 stream->set_enabled(true);
9445 // Add a begin event.
9446 Dart_RecordTimelineEvent("testBeginEvent", 1000, 1, 0, nullptr,
9447 Dart_Timeline_Event_Begin, 0, nullptr, nullptr);
9448 // Check that it is in the output.
9449 TimelineEventRecorder* recorder = Timeline::recorder();
9450 JSONStream js;
9451 IsolateTimelineEventFilter filter(isolate->main_port());
9452 recorder->PrintJSON(&js, &filter);
9453 const char* json = js.ToCString();
9454 EXPECT_SUBSTRING("\"name\":\"testBeginEvent\"", json);
9455 EXPECT_SUBSTRING("\"ph\":\"B\"", json);
9456 EXPECT_SUBSTRING("\"ts\":1000", json);
9457}
9458
9459TEST_CASE(DartAPI_TimelineEnd) {
9460 Isolate* isolate = Isolate::Current();
9461 // Grab embedder stream.
9462 TimelineStream* stream = Timeline::GetEmbedderStream();
9463 // Make sure it is enabled.
9464 stream->set_enabled(true);
9465 // Add a begin event.
9466 Dart_RecordTimelineEvent("testEndEvent", 1000, 1, 0, nullptr,
9467 Dart_Timeline_Event_End, 0, nullptr, nullptr);
9468 // Check that it is in the output.
9469 TimelineEventRecorder* recorder = Timeline::recorder();
9470 JSONStream js;
9471 IsolateTimelineEventFilter filter(isolate->main_port());
9472 recorder->PrintJSON(&js, &filter);
9473 const char* json = js.ToCString();
9474 EXPECT_SUBSTRING("\"name\":\"testEndEvent\"", json);
9475 EXPECT_SUBSTRING("\"ph\":\"E\"", json);
9476 EXPECT_SUBSTRING("\"ts\":1000", json);
9477}
9478
9479TEST_CASE(DartAPI_TimelineInstant) {
9480 Isolate* isolate = Isolate::Current();
9481 // Grab embedder stream.
9482 TimelineStream* stream = Timeline::GetEmbedderStream();
9483 // Make sure it is enabled.
9484 stream->set_enabled(true);
9485 Dart_RecordTimelineEvent("testInstantEvent", 1000, 1, 0, nullptr,
9486 Dart_Timeline_Event_Instant, 0, nullptr, nullptr);
9487 // Check that it is in the output.
9488 TimelineEventRecorder* recorder = Timeline::recorder();
9490 IsolateTimelineEventFilter filter(isolate->main_port());
9491 recorder->PrintJSON(&js, &filter);
9492 const char* json = js.ToCString();
9493 EXPECT_SUBSTRING("\"name\":\"testInstantEvent\"", json);
9494 EXPECT_SUBSTRING("\"ph\":\"i\"", json);
9495 EXPECT_SUBSTRING("\"ts\":1000", json);
9496}
9497
9498TEST_CASE(DartAPI_TimelineAsyncDisabled) {
9499 // Grab embedder stream.
9500 TimelineStream* stream = Timeline::GetEmbedderStream();
9501 // Make sure it is disabled.
9502 stream->set_enabled(false);
9503 int64_t async_id = 99;
9504 Dart_RecordTimelineEvent("testAsyncEvent", 0, async_id, 0, nullptr,
9506 nullptr);
9507 // Check that testAsync is not in the output.
9508 TimelineEventRecorder* recorder = Timeline::recorder();
9509 JSONStream js;
9510 TimelineEventFilter filter;
9511 recorder->PrintJSON(&js, &filter);
9512 EXPECT_NOTSUBSTRING("testAsyncEvent", js.ToCString());
9513}
9514
9515TEST_CASE(DartAPI_TimelineAsync) {
9516 Isolate* isolate = Isolate::Current();
9517 // Grab embedder stream.
9518 TimelineStream* stream = Timeline::GetEmbedderStream();
9519 // Make sure it is enabled.
9520 stream->set_enabled(true);
9521 int64_t async_id = 99;
9522 Dart_RecordTimelineEvent("testAsyncEvent", 1000, async_id, 0, nullptr,
9524 nullptr);
9525
9526 // Check that it is in the output.
9527 TimelineEventRecorder* recorder = Timeline::recorder();
9528 JSONStream js;
9529 IsolateTimelineEventFilter filter(isolate->main_port());
9530 recorder->PrintJSON(&js, &filter);
9531 const char* json = js.ToCString();
9532 EXPECT_SUBSTRING("\"name\":\"testAsyncEvent\"", json);
9533 EXPECT_SUBSTRING("\"ph\":\"b\"", json);
9534 EXPECT_SUBSTRING("\"ts\":1000", json);
9535 EXPECT_SUBSTRING("\"id\":\"63\"", json); // Hex for some reason.
9536}
9537
9538#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
9539TEST_CASE(DartAPI_TimelineAsyncInstantRace) {
9540 struct ReportAsyncEventArguments {
9541 Monitor& synchronization_monitor;
9543 };
9544
9545 Monitor synchronization_monitor;
9546 ReportAsyncEventArguments report_async_event_1_arguments{
9547 synchronization_monitor};
9548 ReportAsyncEventArguments report_async_event_2_arguments{
9549 synchronization_monitor};
9550 TimelineEventRecorder& recorder = *Timeline::recorder();
9551 JSONStream js;
9552 TimelineEventFilter filter;
9553
9554 // Grab embedder stream.
9555 TimelineStream* stream = Timeline::GetEmbedderStream();
9556 // Make sure it is enabled.
9557 stream->set_enabled(true);
9558 // Try concurrently writing async events and reading from the async track
9559 // metadata map. It is not possible to assert anything about the outcome,
9560 // because of scheduling uncertainty. This test is just used to ensure that
9561 // TSAN checks the async track metadata map code.
9563 "ReportAsyncEvent1",
9564 [](uword arguments_ptr) {
9565 ReportAsyncEventArguments& arguments =
9566 *reinterpret_cast<ReportAsyncEventArguments*>(arguments_ptr);
9567 Dart_RecordTimelineEvent("async1", /*timestamp0=*/0, /*async_id=*/1, 0,
9569 /*argument_count=*/0, nullptr, nullptr);
9570 MonitorLocker ml(&arguments.synchronization_monitor);
9571 arguments.join_id =
9573 ml.Notify();
9574 },
9575 reinterpret_cast<uword>(&report_async_event_1_arguments));
9577 "ReportAsyncEvent2",
9578 [](uword arguments_ptr) {
9579 ReportAsyncEventArguments& arguments =
9580 *reinterpret_cast<ReportAsyncEventArguments*>(arguments_ptr);
9581 Dart_RecordTimelineEvent("async2", /*timestamp0=*/0, /*async_id=*/2, 0,
9583 /*argument_count=*/0, nullptr, nullptr);
9584 MonitorLocker ml(&arguments.synchronization_monitor);
9585 arguments.join_id =
9587 ml.Notify();
9588 },
9589 reinterpret_cast<uword>(&report_async_event_2_arguments));
9590 recorder.PrintPerfettoTimeline(&js, filter);
9591
9592 MonitorLocker ml(&synchronization_monitor);
9593 while (report_async_event_1_arguments.join_id ==
9595 report_async_event_2_arguments.join_id ==
9597 ml.Wait();
9599 OSThread::Join(report_async_event_1_arguments.join_id);
9600 OSThread::Join(report_async_event_2_arguments.join_id);
9601}
9602#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
9603
9604TEST_CASE(DartAPI_TimelineClock) {
9605 int64_t micros1 = Dart_TimelineGetMicros();
9606 int64_t ticks1 = Dart_TimelineGetTicks();
9607 int64_t frequency1 = Dart_TimelineGetTicksFrequency();
9608 OS::Sleep(1);
9609 int64_t micros2 = Dart_TimelineGetMicros();
9610 int64_t ticks2 = Dart_TimelineGetTicks();
9611 int64_t frequency2 = Dart_TimelineGetTicksFrequency();
9612 EXPECT_NE(micros1, micros2);
9613 EXPECT_NE(ticks1, ticks2);
9614 EXPECT_EQ(frequency1, frequency2);
9615}
9616
9617TEST_CASE(DartAPI_TimelineCategories) {
9618 bool result;
9619 {
9621 EXPECT_EQ(true, result);
9622 JSONStream js;
9623 JSONObject obj(&js);
9624 JSONArray jstream(&obj, "available");
9625 Timeline::PrintFlagsToJSONArray(&jstream);
9626 const char* js_str = js.ToCString();
9627#define TIMELINE_STREAM_CHECK(name, ...) EXPECT_SUBSTRING(#name, js_str);
9628 TIMELINE_STREAM_LIST(TIMELINE_STREAM_CHECK)
9629#undef TIMELINE_STREAM_CHECK
9630 }
9632 {
9634 EXPECT_EQ(false, result);
9636 EXPECT_EQ(false, result);
9637 }
9638
9639 {
9640 result = Dart_SetEnabledTimelineCategory("GC,API,Compiler");
9641 EXPECT_EQ(true, result);
9643 JSONObject obj(&js);
9644 JSONArray jstream(&obj, "available");
9645 Timeline::PrintFlagsToJSONArray(&jstream);
9646 const char* js_str = js.ToCString();
9647 EXPECT_SUBSTRING("GC", js_str);
9648 EXPECT_SUBSTRING("API", js_str);
9649 EXPECT_SUBSTRING("Compiler", js_str);
9650 EXPECT_NOTSUBSTRING("CompilerVerbose", js_str);
9651 EXPECT_NOTSUBSTRING("Debugger", js_str);
9652 EXPECT_NOTSUBSTRING("Embedder", js_str);
9653 EXPECT_NOTSUBSTRING("Isolate", js_str);
9654 EXPECT_NOTSUBSTRING("VM", js_str);
9655 }
9656
9657 {
9659 EXPECT_EQ(true, result);
9660 JSONStream js;
9661 JSONObject obj(&js);
9662 JSONArray jstream(&obj, "available");
9663 Timeline::PrintFlagsToJSONArray(&jstream);
9664 const char* js_str = js.ToCString();
9665 EXPECT_NOTSUBSTRING("GC", js_str);
9666 EXPECT_NOTSUBSTRING("API", js_str);
9667 EXPECT_NOTSUBSTRING("Compiler", js_str);
9668 EXPECT_NOTSUBSTRING("CompilerVerbose", js_str);
9669 EXPECT_NOTSUBSTRING("Debugger", js_str);
9670 EXPECT_NOTSUBSTRING("Embedder", js_str);
9671 EXPECT_SUBSTRING("Isolate", js_str);
9672 EXPECT_NOTSUBSTRING("VM", js_str);
9673 }
9674
9675 {
9677 EXPECT_EQ(true, result);
9678 JSONStream js;
9679 JSONObject obj(&js);
9680 JSONArray jstream(&obj, "available");
9681 Timeline::PrintFlagsToJSONArray(&jstream);
9682 const char* js_str = js.ToCString();
9683 EXPECT_NOTSUBSTRING("GC", js_str);
9684 EXPECT_NOTSUBSTRING("API", js_str);
9685 EXPECT_NOTSUBSTRING("Compiler", js_str);
9686 EXPECT_NOTSUBSTRING("CompilerVerbose", js_str);
9687 EXPECT_NOTSUBSTRING("Debugger", js_str);
9688 EXPECT_NOTSUBSTRING("Embedder", js_str);
9689 EXPECT_NOTSUBSTRING("Isolate", js_str);
9690 EXPECT_NOTSUBSTRING("VM", js_str);
9691 }
9692}
9693
9696}
9697
9700 int argument_count,
9701 bool* auto_setup_scope) {
9702 return NotifyIdleShortNative;
9703}
9704
9705TEST_CASE(DartAPI_NotifyIdleShort) {
9706 const char* kScriptChars = R"(
9707@pragma("vm:external-name", "Test_nativeFunc")
9708external void notifyIdle();
9709void main() {
9710 var v;
9711 for (var i = 0; i < 100; i++) {
9712 var t = [];
9713 for (var j = 0; j < 10000; j++) {
9714 t.add(List.filled(100, null));
9715 }
9716 v = t;
9717 notifyIdle();
9718 }
9719})";
9720 Dart_Handle lib =
9722 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
9724}
9725
9728}
9729
9732 int argument_count,
9733 bool* auto_setup_scope) {
9734 return NotifyIdleLongNative;
9735}
9736
9737TEST_CASE(DartAPI_NotifyIdleLong) {
9738 const char* kScriptChars = R"(
9739@pragma("vm:external-name", "Test_nativeFunc")
9740external void notifyIdle();
9741void main() {
9742 var v;
9743 for (var i = 0; i < 100; i++) {
9744 var t = [];
9745 for (var j = 0; j < 10000; j++) {
9746 t.add(List.filled(100, null));
9747 }
9748 v = t;
9749 notifyIdle();
9750 }
9751}
9752)";
9753 Dart_Handle lib =
9755 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
9757}
9758
9761}
9762
9765 int argument_count,
9766 bool* auto_setup_scope) {
9767 return NotifyDestroyedNative;
9769
9770TEST_CASE(DartAPI_NotifyDestroyed) {
9771 const char* kScriptChars = R"(
9772import 'dart:isolate';
9773@pragma("vm:external-name", "Test_nativeFunc")
9774external void notifyDetach();
9775void main() {
9776 var v;
9777 for (var i = 0; i < 100; i++) {
9778 var t = [];
9779 for (var j = 0; j < 10000; j++) {
9780 t.add(List.filled(100, null));
9781 }
9782 v = t;
9783 notifyDetach();
9784 }
9785})";
9786 Dart_Handle lib =
9788 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
9790}
9791
9794}
9797}
9801 bool* auto_setup_scope) {
9802 const char* cstr = nullptr;
9804 if (strcmp(cstr, "SetPerformanceModeDefault") == 0) {
9806 } else if (strcmp(cstr, "SetPerformanceModeLatency") == 0) {
9808 }
9809 return nullptr;
9810}
9811
9812TEST_CASE(DartAPI_SetPerformanceMode) {
9813 const char* kScriptChars = R"(
9814import "dart:typed_data";
9815@pragma("vm:external-name", "SetPerformanceModeDefault")
9816external void setPerformanceModeDefault();
9817@pragma("vm:external-name", "SetPerformanceModeLatency")
9818external void setPerformanceModeLatency();
9819void main() {
9820 for (var i = 0; i < 10; i++) {
9821 setPerformanceModeLatency();
9822 var t = [];
9823 for (var j = 0; j < 32; j++) {
9824 t.add(Uint8List(1000000));
9825 }
9826 setPerformanceModeDefault();
9827 }
9828}
9829)";
9830 Dart_Handle lib =
9832 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
9834}
9835
9838}
9839
9842 int argument_count,
9843 bool* auto_setup_scope) {
9845}
9846
9847TEST_CASE(DartAPI_NotifyLowMemory) {
9848 const char* kScriptChars = R"(
9849import 'dart:isolate';
9850@pragma("vm:external-name", "Test_nativeFunc")
9851external void notifyLowMemory();
9852void main() {
9853 var v;
9854 for (var i = 0; i < 100; i++) {
9855 var t = [];
9856 for (var j = 0; j < 10000; j++) {
9857 t.add(List.filled(100, null));
9858 }
9859 v = t;
9860 notifyLowMemory();
9861 }
9862})";
9863 Dart_Handle lib =
9865 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
9867}
9868
9869// There exists another test by name DartAPI_Invoke_CrossLibrary.
9870// However, that currently fails for the dartk configuration as it
9871// uses Dart_LoadLibrary. This test here effectively tests the same
9872// functionality but invokes a function from an imported standard
9873// library.
9874TEST_CASE(DartAPI_InvokeImportedFunction) {
9875 const char* kScriptChars =
9876 "import 'dart:math';\n"
9877 "import 'dart:developer';\n"
9878 "main() {}";
9879 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
9880 EXPECT_VALID(lib);
9881
9883
9887 "NoSuchMethodError: No top-level method 'max' declared.");
9888
9889 Dart_Handle getCurrentTag = Dart_NewStringFromCString("getCurrentTag");
9890 result = Dart_Invoke(lib, getCurrentTag, 0, nullptr);
9892 result,
9893 "NoSuchMethodError: No top-level method 'getCurrentTag' declared.");
9894}
9895
9896TEST_CASE(DartAPI_InvokeVMServiceMethod) {
9897 char buffer[1024];
9898 Utils::SNPrint(buffer, sizeof(buffer),
9899 R"({
9900 "jsonrpc": 2.0,
9901 "id": "foo",
9902 "method": "getVM",
9903 "params": { }
9904 })");
9905 uint8_t* response_json = nullptr;
9906 intptr_t response_json_length = 0;
9907 char* error = nullptr;
9908 const bool success = Dart_InvokeVMServiceMethod(
9909 reinterpret_cast<uint8_t*>(buffer), strlen(buffer), &response_json,
9910 &response_json_length, &error);
9911 EXPECT(success);
9912 EXPECT(error == nullptr);
9913
9915 Dart_TypedData_kUint8, response_json, response_json_length, response_json,
9916 response_json_length, [](void* ignored, void* peer) { free(peer); });
9917 EXPECT_VALID(bytes);
9918
9919 // We don't have a C++ JSON decoder so we'll invoke dart to validate the
9920 // result.
9921 const char* kScript =
9922 R"(
9923 import 'dart:convert';
9924 import 'dart:typed_data';
9925 bool validate(bool condition) {
9926 if (!condition) {
9927 throw 'Failed to validate InvokeVMServiceMethod() response.';
9928 }
9929 return false;
9930 }
9931 bool validateResult(Uint8List bytes) {
9932 final map = json.decode(utf8.decode(bytes));
9933 validate(map['jsonrpc'] == '2.0');
9934 validate(map['id'] == 'foo');
9935 validate(map['result']['name'] == 'vm');
9936 validate(map['result']['type'] == 'VM');
9937 validate(map['result'].containsKey('architectureBits'));
9938 validate(map['result'].containsKey('pid'));
9939 validate(map['result'].containsKey('startTime'));
9940 validate(map['result'].containsKey('hostCPU'));
9941 validate(map['result'].containsKey('targetCPU'));
9942 validate(map['result'].containsKey('version'));
9943 return true;
9944 }
9945 )";
9946
9947 Dart_Handle lib = TestCase::LoadTestScript(kScript, nullptr);
9948 EXPECT_VALID(lib);
9949 Dart_Handle result = Dart_Invoke(lib, NewString("validateResult"), 1, &bytes);
9951 EXPECT(result == Dart_True());
9952}
9953
9954static Monitor* loop_test_lock = new Monitor();
9955static bool loop_test_exit = false;
9956static bool loop_reset_count = false;
9957
9958#if !defined(PRODUCT)
9959static void InvokeServiceMessages(uword param) {
9960 char buffer[1024];
9962 R"({
9963 "jsonrpc": 2.0,
9964 "id": "foo",
9965 "method": "getVM",
9966 "params": { }
9967 })");
9968 uint8_t* response_json = nullptr;
9969 intptr_t response_json_length = 0;
9970 char* error = nullptr;
9971 uint32_t count = 0;
9972 do {
9973 error = nullptr;
9974 response_json = nullptr;
9975 response_json_length = 0;
9976 const bool success = Dart_InvokeVMServiceMethod(
9977 reinterpret_cast<uint8_t*>(buffer), strlen(buffer), &response_json,
9978 &response_json_length, &error);
9979 if (success) {
9981 EXPECT(error == nullptr);
9982 free(response_json);
9983 if (count == 10) {
9984 loop_test_exit = true;
9985 ml.Notify();
9986 }
9987 count++;
9988 } else {
9989 free(error);
9990 }
9991 } while (count < 100);
9992}
9993
9994TEST_CASE(DartAPI_InvokeVMServiceMethod_Loop) {
9995 MonitorLocker ml(loop_test_lock);
9996 loop_test_exit = false;
9997 loop_reset_count = false;
9998 OSThread::Start("InvokeServiceMessages", InvokeServiceMessages, 0);
9999 while (!loop_test_exit) {
10000 ml.Wait();
10001 }
10002}
10003#endif // !defined(PRODUCT)
10004
10005static void HandleResponse(Dart_Port dest_port_id, Dart_CObject* message) {
10006 printf("Response received\n");
10007}
10008
10009static void CreateNativePorts(uword param) {
10010 uint32_t count = 0;
10011 do {
10012 const Dart_Port port_id = Dart_NewNativePort("tst", &HandleResponse, false);
10013 if (port_id != ILLEGAL_PORT) {
10014 Dart_CloseNativePort(port_id);
10016 if (count == 10) {
10017 loop_test_exit = true;
10018 ml.Notify();
10019 }
10021 }
10022 } while (count < 100);
10023}
10024
10025TEST_CASE(DartAPI_NativePort_Loop) {
10027 loop_test_exit = false;
10028 loop_reset_count = false;
10029 OSThread::Start("NativePort", CreateNativePorts, 0);
10030 while (!loop_test_exit) {
10031 ml.Wait();
10032 }
10033}
10034
10035#if !defined(PRODUCT)
10036static void ReportTimelineEvents() {
10037 intptr_t flow_id_count = 1;
10038 const int64_t flow_ids[1] = {123};
10039
10040 Dart_RecordTimelineEvent("T1", 0, 1, /*flow_id_count=*/0, nullptr,
10041 Dart_Timeline_Event_Begin, 0, nullptr, nullptr);
10042 Dart_RecordTimelineEvent("T1", 10, 1, /*flow_id_count=*/0, nullptr,
10043 Dart_Timeline_Event_End, /*argument_count=*/0,
10044 nullptr, nullptr);
10045
10046 Dart_RecordTimelineEvent("T2", 20, 2, /*flow_id_count=*/0, nullptr,
10047 Dart_Timeline_Event_Instant, /*argument_count=*/0,
10048 nullptr, nullptr);
10049
10050 Dart_RecordTimelineEvent("T3", 30, /*timestamp1=*/40, /*flow_id_count=*/0,
10052 /*argument_count=*/0, nullptr, nullptr);
10053
10054 Dart_RecordTimelineEvent("T4", 50, 4, /*flow_id_count=*/0, nullptr,
10056 /*argument_count=*/0, nullptr, nullptr);
10057 Dart_RecordTimelineEvent("T4", 60, 4, /*flow_id_count=*/0, nullptr,
10058 Dart_Timeline_Event_Async_End, /*argument_count=*/0,
10059 nullptr, nullptr);
10060
10061 Dart_RecordTimelineEvent("T5", 70, 5, /*flow_id_count=*/0, nullptr,
10063 /*argument_count=*/0, nullptr, nullptr);
10064
10065 Dart_RecordTimelineEvent("T6", 80, -1, /*flow_id_count=*/0, nullptr,
10066 Dart_Timeline_Event_Counter, /*argument_count=*/0,
10067 nullptr, nullptr);
10068
10069 Dart_RecordTimelineEvent("T7", 90, 7, flow_id_count, flow_ids,
10070 Dart_Timeline_Event_Begin, /*argument_count=*/0,
10071 nullptr, nullptr);
10072 Dart_RecordTimelineEvent("F", 90, 10, /*flow_id_count=*/0, nullptr,
10074 /*argument_count=*/0, nullptr, nullptr);
10075 Dart_RecordTimelineEvent("T7", 100, 7, /*flow_id_count=*/0, nullptr,
10076 Dart_Timeline_Event_End, /*argument_count=*/0,
10077 nullptr, nullptr);
10078
10079 Dart_RecordTimelineEvent("T8", 110, 8, flow_id_count, flow_ids,
10080 Dart_Timeline_Event_Begin, 0, nullptr, nullptr);
10081 Dart_RecordTimelineEvent("F", 110, 10, /*flow_id_count=*/0, nullptr,
10083 /*argument_count=*/0, nullptr, nullptr);
10084 Dart_RecordTimelineEvent("T8", 120, 8, /*flow_id_count=*/0, nullptr,
10085 Dart_Timeline_Event_End, /*argument_count=*/0,
10086 nullptr, nullptr);
10087
10088 Dart_RecordTimelineEvent("T9", 130, 9, flow_id_count, flow_ids,
10089 Dart_Timeline_Event_Begin, /*argument_count=*/0,
10090 nullptr, nullptr);
10091 Dart_RecordTimelineEvent("F", 130, 10, /*flow_id_count=*/0, nullptr,
10093 /*argument_count=*/0, nullptr, nullptr);
10094 Dart_RecordTimelineEvent("T9", 140, 9, /*flow_id_count=*/0, nullptr,
10095 Dart_Timeline_Event_End, /*argument_count=*/0,
10096 nullptr, nullptr);
10097}
10098
10099TEST_CASE(DartAPI_TimelineEvents_Serialization) {
10100 // We do not check the contents of the JSON output here because we have
10101 // pkg/vm_service/test/get_perfetto_vm_timeline_rpc_test.dart and
10102 // runtime/observatory/tests/get_vm_timeline_rpc_test.dart for that. This test
10103 // is used to ensure that assertions in timeline code are checked by debug
10104 // tryjobs, and that the sanitizers run on the timeline code.
10105
10106 // Grab embedder stream.
10107 TimelineStream* stream = Timeline::GetEmbedderStream();
10108 // Make sure it is enabled.
10109 stream->set_enabled(true);
10110
10112 TimelineEventRecorder* recorder = Timeline::recorder();
10113 JSONStream js_chrome_timeline;
10114 JSONStream js_perfetto_timeline;
10115 TimelineEventFilter filter;
10116 recorder->PrintJSON(&js_chrome_timeline, &filter);
10117#if defined(SUPPORT_PERFETTO)
10118 recorder->PrintPerfettoTimeline(&js_perfetto_timeline, filter);
10119#endif // defined(SUPPORT_PERFETTO)
10120}
10121
10122static void CreateTimelineEvents(uword param) {
10123 {
10124 MonitorLocker ml(loop_test_lock);
10125 loop_test_exit = true;
10126 ml.Notify();
10127 }
10128 do {
10130 } while (true);
10133UNIT_TEST_CASE(DartAPI_TimelineEvents_Loop) {
10135 FLAG_complete_timeline = true;
10137 memset(&params, 0, sizeof(Dart_InitializeParams));
10139 params.vm_snapshot_data = TesterState::vm_snapshot_data;
10140 params.create_group = TesterState::create_callback;
10141 params.shutdown_isolate = TesterState::shutdown_callback;
10143 params.start_kernel_isolate = true;
10144 char* result = nullptr;
10147 EXPECT(result == nullptr);
10148 {
10150 loop_test_exit = false;
10151 loop_reset_count = false;
10152 OSThread::Start("TimelineEvents", CreateTimelineEvents, 0);
10153 while (!loop_test_exit) {
10154 printf("VM waiting for notification\n");
10155 ml.Wait();
10156 }
10158 }
10159 result = Dart_Cleanup();
10160 EXPECT(result == nullptr);
10161 for (intptr_t i = 0; i < 50; i++) {
10164 EXPECT(result == nullptr);
10165 result = Dart_Cleanup();
10166 EXPECT(result == nullptr);
10167 }
10168}
10169
10170UNIT_TEST_CASE(DartAPI_TimelineEvents_NullFlowIdsHandledGracefully) {
10171 Dart_RecordTimelineEvent("T1", 0, 10, /*flow_id_count=*/1, nullptr,
10172 Dart_Timeline_Event_Duration, /*argument_count=*/0,
10173 nullptr, nullptr);
10174}
10175#endif // !defined(PRODUCT)
10176
10177static intptr_t EchoInt(double x) {
10178 return x;
10179}
10180
10181static void* FfiNativeResolver(const char* name, uintptr_t args_n) {
10182 ASSERT(strcmp(name, "EchoInt") == 0);
10183 ASSERT(args_n == 1);
10184 return reinterpret_cast<void*>(EchoInt);
10185}
10188 const char* kScriptChars = R"(
10189 import 'dart:ffi';
10190 @Native<IntPtr Function(Double)>(symbol: 'EchoInt', isLeaf:true)
10191 external int echoInt(double x);
10192 main() => echoInt(7.0);
10193 )";
10194 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
10195 EXPECT_VALID(lib);
10196
10199
10200 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
10202
10203 int64_t value = 0;
10206 EXPECT_EQ(7, value);
10207}
10208
10209TEST_CASE(Dart_SetFfiNativeResolver_MissingResolver) {
10210 const char* kScriptChars = R"(
10211 import 'dart:ffi';
10212 @Native<IntPtr Function(Double)>(symbol: 'EchoInt', isLeaf:true)
10213 external int echoInt(double x);
10214 main() => echoInt(7.0);
10215 )";
10216 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
10217 EXPECT_VALID(lib);
10218
10219 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
10220
10221 // With no resolver, we resolve in process. Expect to not find the symbol
10222 // in processes. Error message depends on architecture.
10223 EXPECT_ERROR(result, "Invalid argument(s):");
10224}
10225
10226static void* NopResolver(const char* name, uintptr_t args_n) {
10227 return nullptr;
10228}
10229
10230TEST_CASE(Dart_SetFfiNativeResolver_DoesNotResolve) {
10231 const char* kScriptChars = R"(
10232 import 'dart:ffi';
10233 @Native<Void Function()>(symbol: 'DoesNotResolve')
10234 external void doesNotResolve();
10235 main() => doesNotResolve();
10236 )";
10237 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
10238 EXPECT_VALID(lib);
10239
10242
10243 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
10244 EXPECT_ERROR(result, "Couldn't resolve function: 'DoesNotResolve'");
10245}
10246
10247TEST_CASE(DartAPI_UserTags) {
10248 Dart_Handle default_tag = Dart_GetDefaultUserTag();
10249 EXPECT_VALID(default_tag);
10250
10251 CStringUniquePtr default_label(Dart_GetUserTagLabel(default_tag));
10252 EXPECT_STREQ(default_label.get(), "Default");
10253
10254 Dart_Handle current_tag = Dart_GetCurrentUserTag();
10255 EXPECT(Dart_IdentityEquals(default_tag, current_tag));
10256
10257 CStringUniquePtr current_label(Dart_GetUserTagLabel(current_tag));
10258 EXPECT_STREQ(default_label.get(), current_label.get());
10259
10260 Dart_Handle new_tag = Dart_NewUserTag("Foo");
10261 EXPECT_VALID(new_tag);
10262
10263 CStringUniquePtr new_tag_label(Dart_GetUserTagLabel(new_tag));
10264 EXPECT_STREQ(new_tag_label.get(), "Foo");
10265
10266 Dart_Handle old_tag = Dart_SetCurrentUserTag(new_tag);
10267 EXPECT_VALID(old_tag);
10268
10269 CStringUniquePtr old_label(Dart_GetUserTagLabel(old_tag));
10270 EXPECT_STREQ(old_label.get(), default_label.get());
10271
10272 current_tag = Dart_GetCurrentUserTag();
10273 EXPECT(Dart_IdentityEquals(new_tag, current_tag));
10274
10275 current_label.reset(Dart_GetUserTagLabel(current_tag));
10276 EXPECT_STREQ(current_label.get(), new_tag_label.get());
10277
10278 EXPECT(Dart_GetUserTagLabel(Dart_Null()) == nullptr);
10279
10281 "Dart_NewUserTag expects argument 'label' to be non-null");
10282
10285 "Dart_SetCurrentUserTag expects argument 'user_tag' to be non-null");
10286}
10287
10288#endif // !PRODUCT
10289
10290#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
10291
10292static void* last_allocation_context = nullptr;
10293static const char* last_allocation_cls = nullptr;
10294static intptr_t heap_samples = 0;
10295static const char* expected_allocation_cls = nullptr;
10296static bool found_allocation = false;
10297
10298static void* HeapSamplingCreate(Dart_Isolate isolate,
10299 Dart_IsolateGroup isolate_group,
10300 const char* cls_name,
10301 intptr_t heap_size) {
10302 last_allocation_cls = cls_name;
10303 return strdup(cls_name);
10304}
10305
10306static void HeapSamplingDelete(void* data) {
10307 free(data);
10308}
10309
10310void HeapSamplingReport(void* context, void* data) {
10311 last_allocation_context = context;
10312 if (strcmp(reinterpret_cast<char*>(data), expected_allocation_cls) == 0) {
10313 found_allocation = true;
10314 }
10315 heap_samples++;
10316}
10317
10318void ResetHeapSamplingState(const char* expected_cls = nullptr) {
10319 heap_samples = 0;
10320 expected_allocation_cls = expected_cls;
10321 found_allocation = false;
10322 last_allocation_context = nullptr;
10323 last_allocation_cls = nullptr;
10324}
10325
10326// Threads won't pick up heap sampling profiler state changes until they
10327// process outstanding VM interrupts. Invoke this method after calling
10328// any of the following APIs in a test to ensure changes are applied:
10329//
10330// - Dart_EnableHeapSampling()
10331// - Dart_DisableHeapSampling()
10332// - Dart_SetHeapSamplingPeriod(...)
10333void HandleInterrupts(Thread* thread) {
10334 TransitionNativeToVM transition(thread);
10335 thread->HandleInterrupts();
10336}
10337
10338void InitHeapSampling(Thread* thread, const char* expected_cls) {
10339 ResetHeapSamplingState(expected_cls);
10342 // Start with sampling on every byte allocated.
10344 HandleInterrupts(thread);
10345}
10346
10347TEST_CASE(DartAPI_HeapSampling_UserDefinedClass) {
10348 DisableBackgroundCompilationScope scope;
10349 const char* kScriptChars = R"(
10350 class Bar {}
10351 final list = [];
10352 foo() {
10353 for (int i = 0; i < 100000; ++i) {
10354 list.add(Bar());
10355 }
10356 }
10357 )";
10358
10359 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
10360 EXPECT_VALID(lib);
10361
10362 InitHeapSampling(thread, "Bar");
10363 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, nullptr);
10365
10366 // Exit the isolate before getting the profile.
10369
10370 void* context = reinterpret_cast<void*>(42); // Fake data, not used.
10372 /*force_gc=*/true);
10373 EXPECT(heap_samples > 0);
10374 EXPECT(heap_samples < 100000);
10375 EXPECT(last_allocation_context == context);
10377 Dart_EnterIsolate(isolate);
10378}
10379
10380TEST_CASE(DartAPI_HeapSampling_APIAllocations) {
10381 InitHeapSampling(thread, "List");
10382
10383 // Some simple allocations
10385
10386 // Exit the isolate before getting the profile.
10388 EXPECT(isolate != nullptr);
10390
10392 /*force_gc=*/true);
10393 EXPECT(heap_samples > 0);
10394#if !defined(PRODUCT)
10395 EXPECT_STREQ("List", last_allocation_cls);
10396 ResetHeapSamplingState("String");
10397#else
10398 EXPECT_STREQ("_List", last_allocation_cls);
10399 ResetHeapSamplingState("_OneByteString");
10400#endif
10401
10402 // Re-enter the isolate.
10403 Dart_EnterIsolate(isolate);
10404
10405 const intptr_t kNumAllocations = 1000;
10406 for (intptr_t i = 0; i < kNumAllocations; ++i) {
10408 }
10409
10410 // Exit the isolate after performing allocations.
10412
10414 /*force_gc=*/true);
10415 EXPECT(heap_samples > 0);
10417
10418#if !defined(PRODUCT)
10419 ResetHeapSamplingState("String");
10420#else
10421 ResetHeapSamplingState("_OneByteString");
10422#endif
10423
10424 // Re-enter the isolate.
10425 Dart_EnterIsolate(isolate);
10426
10428
10429 // Exit the isolate after performing allocations.
10431
10433 /*force_gc=*/true);
10434 EXPECT(heap_samples > 0);
10436
10437 ResetHeapSamplingState("Uint8List");
10438
10439 // Re-enter the isolate.
10440 Dart_EnterIsolate(isolate);
10441
10443
10444 // Exit the isolate after performing allocations.
10446
10448 /*force_gc=*/true);
10449 EXPECT(heap_samples > 0);
10451
10452 Dart_EnterIsolate(isolate);
10453}
10454
10455TEST_CASE(DartAPI_HeapSampling_NonTrivialSamplingPeriod) {
10456 DisableBackgroundCompilationScope scope;
10457 InitHeapSampling(thread, "List");
10458
10459 // Increase the sampling period and check that we don't sample each
10460 // allocation. This should cause samples to be collected for approximately
10461 // every 1KiB allocated.
10463 HandleInterrupts(thread);
10464
10465 // Allocate via the embedding API.
10466 const intptr_t kNumAllocations = 1000;
10467 for (intptr_t i = 0; i < kNumAllocations; ++i) {
10469 }
10470
10471 // Exit the isolate before getting the profile.
10473 EXPECT(isolate != nullptr);
10475
10477 /*force_gc=*/true);
10478 EXPECT(heap_samples > 0);
10479 EXPECT(heap_samples < kNumAllocations);
10480
10481 // Re-enter the isolate.
10482 Dart_EnterIsolate(isolate);
10483
10484 const char* kScriptChars = R"(
10485 final list = [];
10486 foo() {
10487 for (int i = 0; i < 1000; ++i) {
10488 list.add(List.filled(100, 0));
10489 }
10490 }
10491 )";
10493 HandleInterrupts(thread);
10494
10495 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
10496 EXPECT_VALID(lib);
10497
10498 ResetHeapSamplingState("List");
10499
10501 HandleInterrupts(thread);
10502
10503 // Allocate via Dart code.
10504 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, nullptr);
10506
10507 // Exit the isolate after performing allocations.
10509
10511 /*force_gc=*/true);
10512 EXPECT(heap_samples > 0);
10513 EXPECT(heap_samples < kNumAllocations);
10514
10515 Dart_EnterIsolate(isolate);
10517}
10518
10519// Check that we set correct sampling interval for old space allocations
10520// during initial isolate startup (before the first TLAB is created).
10521// This is a regression test for a bug that was causing each old space
10522// allocation to be sampled.
10524 DartAPI_HeapSampling_CorrectSamplingIntervalForOldSpaceAllocations) {
10526 [](Dart_Isolate isolate, Dart_IsolateGroup isolate_group,
10527 const char* cls_name, intptr_t allocation_size) -> void* {
10528 // Should not be called because sampling interval is very large.
10529 UNREACHABLE();
10530 return nullptr;
10531 },
10532 [](void* data) {
10533 // Nothing to do.
10534 });
10540}
10541#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
10542
10543#if defined(DART_ENABLE_HEAP_SNAPSHOT_WRITER)
10544TEST_CASE(DartAPI_WriteHeapSnapshot) {
10545 struct WriterContext {
10546 intptr_t bytes_written;
10547 bool saw_last_chunk;
10548 };
10549
10550 WriterContext context = {0, false};
10552 [](void* context, uint8_t* buffer, intptr_t size, bool is_last) {
10553 auto ctx = static_cast<WriterContext*>(context);
10554 ctx->bytes_written += size;
10555 EXPECT(!ctx->saw_last_chunk);
10556 ctx->saw_last_chunk = is_last;
10557
10558 free(buffer);
10559 },
10560 &context);
10561 EXPECT(error == nullptr);
10562 EXPECT_GT(context.bytes_written, 0);
10563 EXPECT(context.saw_last_chunk);
10564}
10565#endif // defined(DART_ENABLE_HEAP_SNAPSHOT_WRITER)
10566
10567} // namespace dart
static bool invalid(const SkISize &size)
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition: DM.cpp:263
int count
Definition: FontMgrTest.cpp:50
static bool equal(const SkBitmap &a, const SkBitmap &b)
Definition: ImageTest.cpp:1395
float e1
static bool is_equal(SkSurface *a, SkSurface *b)
bool equals(SkDrawable *a, SkDrawable *b)
static const size_t kBufferSize
Definition: SkString.cpp:27
#define EXPECT(type, expectedAlignment, expectedSize)
#define UNREACHABLE()
Definition: assert.h:248
GLenum type
#define FUNCTION_NAME(name)
Definition: builtin.h:19
static Dart_Handle NewHandle(Thread *thread, ObjectPtr raw)
static Dart_Isolate CastIsolate(Isolate *isolate)
static ObjectPtr UnwrapHandle(Dart_Handle object)
static Dart_Handle NewError(const char *format,...) PRINTF_ATTRIBUTE(1
static constexpr intptr_t kMaxElements
Definition: object.h:10924
BackgroundGCTask(IsolateGroup *isolate_group, Monitor *monitor, bool *done)
uint16_t num_native_fields() const
Definition: object.h:1788
intptr_t host_instance_size() const
Definition: object.h:1143
static ThreadPool * thread_pool()
Definition: dart.h:73
@ kNew
Definition: heap.h:38
@ kOld
Definition: heap.h:39
intptr_t Collections(Space space) const
Definition: heap.cc:835
intptr_t ExternalInWords(Space space) const
Definition: heap.cc:811
InfiniteLoopTask(Dart_Isolate *isolate, Monitor *monitor, bool *interrupted)
Heap * heap() const
Definition: isolate.h:296
static IsolateGroup * Current()
Definition: isolate.h:539
ApiState * api_state() const
Definition: isolate.h:700
static Isolate * Current()
Definition: isolate.h:986
static Dart_IsolateShutdownCallback ShutdownCallback()
Definition: isolate.h:1217
static void SetShutdownCallback(Dart_IsolateShutdownCallback cb)
Definition: isolate.h:1214
IsolateGroup * group() const
Definition: isolate.h:1037
static void SetCleanupCallback(Dart_IsolateCleanupCallback cb)
Definition: isolate.h:1221
static Dart_IsolateGroupCreateCallback CreateGroupCallback()
Definition: isolate.h:1203
Dart_MessageNotifyCallback message_notify_callback() const
Definition: isolate.h:1011
static Dart_IsolateGroupCleanupCallback GroupCleanupCallback()
Definition: isolate.h:1231
static void SetGroupCleanupCallback(Dart_IsolateGroupCleanupCallback cb)
Definition: isolate.h:1228
static void SetCreateGroupCallback(Dart_IsolateGroupCreateCallback cb)
Definition: isolate.h:1200
StringPtr PrivateName(const String &name) const
Definition: object.cc:14704
Monitor::WaitResult Wait(int64_t millis=Monitor::kNoTimeout)
Definition: lockers.h:172
static int Start(const char *name, ThreadStartFunction function, uword parameter)
static void Join(ThreadJoinId id)
static OSThread * Current()
Definition: os_thread.h:179
static ThreadJoinId GetCurrentThreadJoinId(OSThread *thread)
static const ThreadJoinId kInvalidThreadJoinId
Definition: os_thread.h:249
static void Sleep(int64_t millis)
ObjectPtr ptr() const
Definition: object.h:332
bool IsNew() const
Definition: object.h:390
bool IsOld() const
Definition: object.h:391
virtual const char * ToCString() const
Definition: object.h:366
static Object & Handle()
Definition: object.h:407
ClassPtr clazz() const
Definition: object.h:13218
static constexpr intptr_t kMaxElements
Definition: object.h:10543
static PersistentHandle * Cast(Dart_PersistentHandle handle)
ObjectPtr ptr() const
static SmiPtr New(intptr_t value)
Definition: object.h:10006
intptr_t Value() const
Definition: object.h:9990
static constexpr int kPreallocatedStackdepth
Definition: object.h:12558
bool Equals(const String &str) const
Definition: object.h:13337
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition: object.cc:23698
static const char * ToCString(Thread *thread, StringPtr ptr)
Definition: object.cc:24126
static void AddToKernelBuffers(const uint8_t *kernel_buffer)
Definition: unit_test.cc:101
static Dart_Handle LoadTestScriptWithDFE(int sourcefiles_count, Dart_SourceFile sourcefiles[], Dart_NativeEntryResolver resolver=nullptr, bool finalize=true, bool incrementally=true, bool allow_compile_errors=false, const char *entry_script_uri=nullptr, const char *multiroot_filepaths=nullptr, const char *multiroot_scheme=nullptr)
Definition: unit_test.cc:490
static void AddTestLib(const char *url, const char *source)
Definition: unit_test.cc:189
static Dart_Handle LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true, bool allow_compile_errors=false)
Definition: unit_test.cc:436
static char * CompileTestScriptWithDFE(const char *url, const char *source, const uint8_t **kernel_buffer, intptr_t *kernel_buffer_size, bool incrementally=true, bool allow_compile_errors=false, const char *multiroot_filepaths=nullptr, const char *multiroot_scheme=nullptr)
Definition: unit_test.cc:297
static const char * url()
Definition: unit_test.cc:185
static Dart_Handle LoadTestLibrary(const char *lib_uri, const char *script, Dart_NativeEntryResolver resolver=nullptr)
Definition: unit_test.cc:455
static Dart_Handle library_handler(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url)
Definition: unit_test.cc:651
static Dart_Isolate CreateTestIsolate(const char *name=nullptr, void *isolate_group_data=nullptr, void *isolate_data=nullptr)
Definition: unit_test.cc:140
static Dart_IsolateShutdownCallback shutdown_callback
Definition: unit_test.h:257
static Dart_IsolateGroupCreateCallback create_callback
Definition: unit_test.h:256
static const char ** argv
Definition: unit_test.h:259
static Dart_IsolateGroupCleanupCallback group_cleanup_callback
Definition: unit_test.h:258
static int argc
Definition: unit_test.h:260
static const uint8_t * vm_snapshot_data
Definition: unit_test.h:255
bool Run(Args &&... args)
Definition: thread_pool.h:45
Zone * zone() const
Definition: thread_state.h:37
ApiLocalScope * api_top_scope() const
Definition: thread.h:513
@ kUnknownTask
Definition: thread.h:346
static Thread * Current()
Definition: thread.h:362
Heap * heap() const
Definition: thread.cc:943
int ZoneSizeInBytes() const
Definition: thread.cc:1291
intptr_t CountLocalHandles() const
Definition: thread.cc:1281
static void ExitIsolateGroupAsHelper(bool bypass_safepoint)
Definition: thread.cc:499
Isolate * isolate() const
Definition: thread.h:534
static bool EnterIsolateGroupAsHelper(IsolateGroup *isolate_group, TaskKind kind, bool bypass_safepoint)
Definition: thread.cc:481
static constexpr intptr_t kMaxElements
Definition: object.h:10684
static TypePtr NullType()
static TypePtr BoolType()
static UnwindErrorPtr New(const String &message, Heap::Space space=Heap::kNew)
Definition: object.cc:20005
static int SNPrint(char *str, size_t size, const char *format,...) PRINTF_ATTRIBUTE(3
static char * StrDup(const char *s)
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition: utils.h:120
#define DART_INITIALIZE_PARAMS_CURRENT_VERSION
Definition: dart_api.h:840
Dart_Isolate(* Dart_IsolateGroupCreateCallback)(const char *script_uri, const char *main, const char *package_root, const char *package_config, Dart_IsolateFlags *flags, void *isolate_data, char **error)
Definition: dart_api.h:654
#define ILLEGAL_PORT
Definition: dart_api.h:1535
@ Dart_PerformanceMode_Default
Definition: dart_api.h:1373
@ Dart_PerformanceMode_Latency
Definition: dart_api.h:1380
int64_t Dart_Port
Definition: dart_api.h:1525
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
struct _Dart_Isolate * Dart_Isolate
Definition: dart_api.h:88
struct _Dart_IsolateGroup * Dart_IsolateGroup
Definition: dart_api.h:89
struct _Dart_NativeArguments * Dart_NativeArguments
Definition: dart_api.h:3019
Dart_TypedData_Type
Definition: dart_api.h:2612
@ Dart_TypedData_kFloat32x4
Definition: dart_api.h:2626
@ Dart_TypedData_kUint8
Definition: dart_api.h:2615
@ Dart_TypedData_kUint32
Definition: dart_api.h:2620
@ Dart_TypedData_kInt32
Definition: dart_api.h:2619
@ Dart_TypedData_kUint16
Definition: dart_api.h:2618
@ Dart_TypedData_kUint64
Definition: dart_api.h:2622
@ Dart_TypedData_kFloat32
Definition: dart_api.h:2623
@ Dart_TypedData_kInt16
Definition: dart_api.h:2617
@ Dart_TypedData_kFloat64
Definition: dart_api.h:2624
@ Dart_TypedData_kUint8Clamped
Definition: dart_api.h:2616
@ Dart_TypedData_kByteData
Definition: dart_api.h:2613
@ Dart_TypedData_kInt8
Definition: dart_api.h:2614
@ Dart_TypedData_kInt64
Definition: dart_api.h:2621
@ Dart_TypedData_kInvalid
Definition: dart_api.h:2628
Dart_Handle Dart_PersistentHandle
Definition: dart_api.h:259
void(* Dart_IsolateGroupCleanupCallback)(void *isolate_group_data)
Definition: dart_api.h:745
struct _Dart_FinalizableHandle * Dart_FinalizableHandle
Definition: dart_api.h:261
void(* Dart_IsolateShutdownCallback)(void *isolate_group_data, void *isolate_data)
Definition: dart_api.h:711
void(* Dart_NativeFunction)(Dart_NativeArguments arguments)
Definition: dart_api.h:3207
@ Dart_NativeArgument_kString
Definition: dart_api.h:3033
@ Dart_NativeArgument_kNativeFields
Definition: dart_api.h:3035
@ Dart_NativeArgument_kInstance
Definition: dart_api.h:3034
@ Dart_NativeArgument_kInt32
Definition: dart_api.h:3028
@ Dart_NativeArgument_kUint64
Definition: dart_api.h:3031
@ Dart_NativeArgument_kDouble
Definition: dart_api.h:3032
@ Dart_NativeArgument_kBool
Definition: dart_api.h:3027
struct _Dart_WeakPersistentHandle * Dart_WeakPersistentHandle
Definition: dart_api.h:260
#define CHECK_API_SCOPE(thread)
Definition: dart_api_impl.h:64
#define TIMELINE_STREAM_CHECK(name,...)
@ Dart_CObject_kTypedData
@ Dart_CObject_kSendPort
@ Dart_CObject_kArray
@ Dart_CObject_kNull
@ Dart_CObject_kExternalTypedData
@ Dart_CObject_kInt32
@ Dart_Timeline_Event_Async_Begin
@ Dart_Timeline_Event_Async_End
@ Dart_Timeline_Event_Begin
@ Dart_Timeline_Event_Counter
@ Dart_Timeline_Event_Flow_End
@ Dart_Timeline_Event_Duration
@ Dart_Timeline_Event_Flow_Begin
@ Dart_Timeline_Event_End
@ Dart_Timeline_Event_Instant
@ Dart_Timeline_Event_Async_Instant
@ Dart_Timeline_Event_Flow_Step
const EmbeddedViewParams * params
#define ASSERT(E)
VkInstance instance
Definition: main.cc:48
SkBitmap source
Definition: examples.cpp:28
double frame
Definition: examples.cpp:31
static bool b
struct MyStruct s
struct MyStruct a[10]
EMSCRIPTEN_KEEPALIVE void empty()
AtkStateType state
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
GAsyncResult * result
Dart_NativeFunction function
Definition: fuchsia.cc:51
int argument_count
Definition: fuchsia.cc:52
#define HANDLESCOPE(thread)
Definition: handles.h:321
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
size_t length
Win32Message message
double x
std::string printf(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: SkSLString.cpp:83
Definition: dart_vm.cc:33
DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str, uint8_t **utf8_array, intptr_t *length)
void CurrentStackTraceNative(Dart_NativeArguments args)
constexpr int64_t kMaxInt64
Definition: globals.h:486
static void NewNativePort_sendInteger123(Dart_Port dest_port_id, Dart_CObject *message)
DART_EXPORT bool Dart_IsLibrary(Dart_Handle object)
static void NewNativePort_nativeReceiveInteger(Dart_Port dest_port_id, Dart_CObject *message)
constexpr intptr_t MB
Definition: globals.h:530
static void NativeFoo4(Dart_NativeArguments args)
static void NotifyIdleShortNative(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_SetFfiNativeResolver(Dart_Handle library, Dart_FfiNativeResolver resolver)
constexpr int64_t kMinInt64
Definition: globals.h:485
static Dart_NativeFunction native_field_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
static void * shutdown_isolate_group_data
static Dart_NativeFunction native_args_lookup(Dart_Handle name, int argument_count, bool *auto_scope_setup)
DART_EXPORT void Dart_ReportSurvivingAllocations(Dart_HeapSamplingReportCallback callback, void *context, bool force_gc)
static Dart_Handle AllocateNewString(const char *c_str)
DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index)
DART_EXPORT Dart_WeakPersistentHandle Dart_NewWeakPersistentHandle(Dart_Handle object, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback)
static int64_t GetValue(Dart_Handle arg)
DART_EXPORT Dart_Handle Dart_ClassLibrary(Dart_Handle cls_type)
static void * HeapSamplingCreate(Dart_Isolate isolate, Dart_IsolateGroup isolate_group, const char *cls_name, intptr_t heap_size)
DART_EXPORT Dart_Handle Dart_SetPeer(Dart_Handle object, void *peer)
static Dart_NativeFunction PropagateError_native_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
DART_EXPORT bool Dart_IsDouble(Dart_Handle object)
DART_EXPORT bool Dart_IsInstance(Dart_Handle object)
DART_EXPORT void Dart_DisableHeapSampling()
DART_EXPORT Dart_Handle Dart_IsNonNullableType(Dart_Handle type, bool *result)
static void FinalizableHandlePeerFinalizer(void *isolate_callback_data, void *peer)
static const char * last_allocation_cls
DART_EXPORT Dart_Handle Dart_SetCurrentUserTag(Dart_Handle user_tag)
constexpr intptr_t kMicrosecondsPerMillisecond
Definition: globals.h:561
DART_EXPORT bool Dart_IsCompilationError(Dart_Handle object)
void ResetHeapSamplingState(const char *expected_cls=nullptr)
static void IsolateShutdownTestCallback(void *group_data, void *isolate_data)
static void NativeArgumentAccess(Dart_NativeArguments args)
static void DeleteWeakHandleOnFinalization(void *isolate_callback_data, void *peer)
static void FinalizableHandlePeerCleanupFinalizer(void *isolate_callback_data, void *peer)
static void NotifyLowMemoryNative(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_Allocate(Dart_Handle type)
static void MyNativeFunction1(Dart_NativeArguments args)
DART_EXPORT bool Dart_IsBoolean(Dart_Handle object)
Dart_Handle Dart_StackTraceLength(Dart_StackTrace trace, intptr_t *length)
static void SetPerformanceModeLatency(Dart_NativeArguments args)
DART_EXPORT void Dart_EnterScope()
DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object)
static void * last_allocation_context
DART_EXPORT void Dart_SetPersistentHandle(Dart_PersistentHandle obj1, Dart_Handle obj2)
static void NewNativePort_Transferrable1(Dart_Port dest_port_id, Dart_CObject *message)
Dart_Handle Dart_ActivationFrameInfo(Dart_ActivationFrame activation_frame, Dart_Handle *function_name, Dart_Handle *script_url, intptr_t *line_number, intptr_t *column_number)
const char *const name
DART_EXPORT Dart_Port Dart_GetMainPortId()
DART_EXPORT Dart_Handle Dart_FinalizeLoading(bool complete_futures)
DART_EXPORT Dart_Handle Dart_NewUserTag(const char *label)
DART_EXPORT Dart_Handle Dart_GetStickyError()
static void ExternalTypedDataAccessTests(Dart_Handle obj, Dart_TypedData_Type expected_type, uint8_t data[], intptr_t data_length)
DART_EXPORT char * Dart_GetUserTagLabel(Dart_Handle user_tag)
void NativeFieldLookup(Dart_NativeArguments args)
DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle handle)
static void ExternalByteDataNativeFunction(Dart_NativeArguments args)
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
void PropagateErrorNative(Dart_NativeArguments args)
UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__INCREASING)
static Dart_NativeFunction SetMode_native_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
DART_EXPORT Dart_Handle Dart_TypeNever()
static bool byte_data_finalizer_run
DART_EXPORT Dart_Handle Dart_DebugName()
DART_EXPORT Dart_Handle Dart_False()
DART_EXPORT bool Dart_ErrorHasException(Dart_Handle handle)
CAllocUniquePtr< char > CStringUniquePtr
Definition: utils.h:31
static void * SecretKeeperFfiNativeResolver(const char *name, uintptr_t argn)
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, int index, intptr_t *value)
DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t *utf32_array, intptr_t length)
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
static Dart_NativeFunction MyNativeResolver1(Dart_Handle name, int arg_count, bool *auto_setup_scope)
static void SlowWeakPersistentHandle(void *isolate_callback_data, void *peer)
pthread_t ThreadJoinId
DART_EXPORT Dart_Handle Dart_NewDouble(double value)
Dart_Handle Dart_GetStackTrace(Dart_StackTrace *trace)
DART_EXPORT const char * Dart_IsolateServiceId(Dart_Isolate isolate)
static void UnreachedCallback(void *isolate_callback_data, void *peer)
static void * cleanup_isolate_data
Dart_WeakPersistentHandle delete_on_finalization
DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle cls_type)
DART_EXPORT Dart_Handle Dart_GetPeer(Dart_Handle object, void **peer)
static Dart_WeakPersistentHandle weak3
static void TestFieldOk(Dart_Handle container, Dart_Handle name, bool final, const char *initial_value)
static void StaticNativeFoo4(Dart_NativeArguments args)
DART_EXPORT bool Dart_HasStickyError()
DART_EXPORT Dart_Handle Dart_StringToLatin1(Dart_Handle str, uint8_t *latin1_array, intptr_t *length)
DART_EXPORT void Dart_NotifyLowMemory()
static Dart_WeakPersistentHandle weak1
DART_EXPORT Dart_Handle Dart_True()
DART_EXPORT Dart_Handle Dart_RootLibrary()
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library, Dart_Handle class_name)
DART_EXPORT bool Dart_IsNumber(Dart_Handle object)
static void CreateTimelineEvents(uword param)
static bool use_set_return
DART_EXPORT Dart_Handle Dart_NewStringFromUTF16(const uint16_t *utf16_array, intptr_t length)
static void IsolateGroupCleanupTestCallback(void *callback_data)
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer, bool *fits)
DART_EXPORT Dart_Handle Dart_GetNativeInstanceFieldCount(Dart_Handle obj, int *count)
void * malloc(size_t size)
Definition: allocation.cc:19
static void WeakPersistentHandlePeerCleanupFinalizer(void *isolate_callback_data, void *peer)
void TestNativeFieldsAccess_access(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_GetDefaultUserTag()
DART_EXPORT Dart_Handle Dart_TypeDynamic()
static void MyMessageNotifyCallback(Dart_Isolate dest_isolate)
DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception)
static intptr_t kNativeArgumentNativeField1Value
static void NativeFoo1(Dart_NativeArguments args)
static void StaticNativeFoo1(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value)
DART_EXPORT bool Dart_IsUnhandledExceptionError(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_BooleanValue(Dart_Handle boolean_obj, bool *value)
static Dart_NativeFunction NotifyIdleLong_native_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
static intptr_t EchoInt(double x)
DART_EXPORT Dart_Handle Dart_NewExternalTypedDataWithFinalizer(Dart_TypedData_Type type, void *data, intptr_t length, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback)
static Dart_NativeFunction ExternalByteDataNativeResolver(Dart_Handle name, int arg_count, bool *auto_setup_scope)
static void NotifyDestroyedNative(Dart_NativeArguments args)
static void NotifyIdleLongNative(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t *utf8_array, intptr_t length)
DART_EXPORT void Dart_PropagateError(Dart_Handle handle)
static void NewNativePort_send123(Dart_Port dest_port_id, Dart_CObject *message)
static Dart_WeakPersistentHandle weak_persistent_handle2
constexpr uint64_t kMaxUint64
Definition: globals.h:487
static Dart_NativeFunction MyNativeClosureResolver(Dart_Handle name, int arg_count, bool *auto_setup_scope)
static void ReportTimelineEvents()
static void HandleResponse(Dart_Port dest_port_id, Dart_CObject *message)
DART_EXPORT void * Dart_IsolateGroupData(Dart_Isolate isolate)
DART_EXPORT Dart_Handle Dart_GetNonNullableType(Dart_Handle library, Dart_Handle class_name, intptr_t number_of_type_arguments, Dart_Handle *type_arguments)
DART_EXPORT Dart_FinalizableHandle Dart_NewFinalizableHandle(Dart_Handle object, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback)
DART_EXPORT const char * Dart_GetError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type, intptr_t length)
DART_EXPORT Dart_Handle Dart_HandleFromWeakPersistent(Dart_WeakPersistentHandle object)
DART_EXPORT Dart_IsolateGroup Dart_CurrentIsolateGroup()
void TestNativeFieldsAccess_init(Dart_NativeArguments args)
DART_EXPORT uint8_t * Dart_ScopeAllocate(intptr_t size)
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, Dart_Handle retval)
static void NewNativePort_Transferrable2(Dart_Port dest_port_id, Dart_CObject *message)
DART_EXPORT Dart_Handle Dart_GetStaticMethodClosure(Dart_Handle library, Dart_Handle cls_type, Dart_Handle function_name)
DART_EXPORT void Dart_RecordTimelineEvent(const char *label, int64_t timestamp0, int64_t timestamp1_or_id, intptr_t flow_id_count, const int64_t *flow_ids, Dart_Timeline_Event_Type type, intptr_t argument_count, const char **argument_names, const char **argument_values)
const intptr_t kDefaultNewGenSemiMaxSize
Definition: globals.h:63
DART_EXPORT void Dart_NotifyDestroyed()
static intptr_t heap_samples
static void RunLoopTest(bool throw_exception)
static void IsolateShutdownRunDartCodeTestCallback(void *isolate_group_data, void *isolate_data)
DART_EXPORT char * Dart_Initialize(Dart_InitializeParams *params)
static int64_t add_result
DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name)
void JustPropagateErrorNative(Dart_NativeArguments args)
static constexpr intptr_t kSendLength
DART_EXPORT Dart_Handle Dart_IsNullableType(Dart_Handle type, bool *result)
DART_EXPORT Dart_Handle Dart_GetCurrentUserTag()
static void * FfiNativeResolver(const char *name, uintptr_t args_n)
DART_EXPORT Dart_Handle Dart_MapGetAt(Dart_Handle map, Dart_Handle key)
DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function, bool *is_static)
constexpr intptr_t KB
Definition: globals.h:528
uintptr_t uword
Definition: globals.h:501
DART_EXPORT Dart_Handle Dart_NewIntegerFromHexCString(const char *str)
DART_EXPORT void Dart_SetHeapSamplingPeriod(intptr_t bytes)
DART_EXPORT int64_t Dart_TimelineGetTicks()
static void StaticNativeFoo2(Dart_NativeArguments args)
DART_EXPORT bool Dart_IsFuture(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_ToString(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure)
static Dart_NativeFunction native_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
static void UnreachableMessageHandler(Dart_Port dest_port_id, Dart_CObject *message)
void TestNativeFieldsAccess_invalidAccess(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object, Dart_TypedData_Type *type, void **data, intptr_t *len)
DART_EXPORT Dart_Handle Dart_GetNullableType(Dart_Handle library, Dart_Handle class_name, intptr_t number_of_type_arguments, Dart_Handle *type_arguments)
static void StaticNativeFoo3(Dart_NativeArguments args)
DART_EXPORT Dart_Isolate Dart_CurrentIsolate()
static void OptExternalByteDataNativeFunction(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_NewListOfTypeFilled(Dart_Handle element_type, Dart_Handle fill_object, intptr_t length)
static Dart_FinalizableHandle finalizable_handle3
DART_EXPORT Dart_Handle Dart_InvokeConstructor(Dart_Handle object, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list, intptr_t index, Dart_Handle value)
DART_EXPORT char * Dart_WriteHeapSnapshot(Dart_HeapSnapshotWriteChunkCallback write, void *context)
static Dart_Handle AsHandle(Dart_PersistentHandle weak)
DART_EXPORT Dart_Handle Dart_IntegerToHexCString(Dart_Handle integer, const char **value)
static constexpr intptr_t kExtLength
DART_EXPORT bool Dart_SetEnabledTimelineCategory(const char *categories)
DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function)
DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate)
struct _Dart_ActivationFrame * Dart_ActivationFrame
void FUNCTION_NAME() SecretKeeper_KeepSecret(Dart_NativeArguments native_args)
static void MyNativeFunction2(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_NewBoolean(bool value)
DART_EXPORT char * Dart_Cleanup()
static Dart_NativeFunction NotifyIdleShort_native_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
static Monitor * loop_test_lock
static constexpr int kTestNumNativeFields
DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj, int index, intptr_t value)
DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args, int64_t retval)
DART_EXPORT void Dart_DeleteWeakPersistentHandle(Dart_WeakPersistentHandle object)
static Dart_NativeFunction MyNativeResolver2(Dart_Handle name, int arg_count, bool *auto_setup_scope)
DART_EXPORT Dart_Handle Dart_EmptyString()
static void NativeArgumentCreate(Dart_NativeArguments args)
static void NopCallback(void *isolate_callback_data, void *peer)
static Dart_NativeFunction MyStaticNativeClosureResolver(Dart_Handle name, int arg_count, bool *auto_setup_scope)
DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id)
DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object, Dart_Handle type, bool *value)
DART_EXPORT Dart_Handle Dart_CopyUTF8EncodingOfString(Dart_Handle str, uint8_t *utf8_array, intptr_t length)
DART_EXPORT Dart_Handle Dart_ErrorGetStackTrace(Dart_Handle handle)
static void FinalizeTypedData(void *isolate_callback_data, void *peer)
DART_EXPORT Dart_Handle Dart_TypeToNullableType(Dart_Handle type)
DART_EXPORT Dart_Handle Dart_GetNativeFieldsOfArgument(Dart_NativeArguments args, int arg_index, int num_fields, intptr_t *field_values)
Dart_Handle Dart_GetActivationFrame(Dart_StackTrace trace, int frame_index, Dart_ActivationFrame *frame)
static bool found_allocation
DART_EXPORT Dart_PerformanceMode Dart_SetPerformanceMode(Dart_PerformanceMode mode)
DART_EXPORT Dart_Handle Dart_ListSetAsBytes(Dart_Handle list, intptr_t offset, const uint8_t *native_array, intptr_t length)
static void TestTypedDataDirectAccess()
static Dart_Handle AllocateOldString(const char *c_str)
static Dart_NativeFunction ByteDataNativeResolver(Dart_Handle name, int arg_count, bool *auto_setup_scope)
static void TestDirectAccess(Dart_Handle lib, Dart_Handle array, Dart_TypedData_Type expected_type, bool is_external)
static Dart_NativeFunction CurrentStackTraceNativeLookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
static Dart_NativeFunction TestNativeFieldsAccess_lookup(Dart_Handle name, int argument_count, bool *auto_scope)
DART_EXPORT Dart_Handle Dart_NewExternalTypedData(Dart_TypedData_Type type, void *data, intptr_t length)
static void HeapSamplingDelete(void *data)
DART_EXPORT Dart_Handle Dart_TypeToNonNullableType(Dart_Handle type)
DART_EXPORT Dart_Handle Dart_AllocateWithNativeFields(Dart_Handle type, intptr_t num_native_fields, const intptr_t *native_fields)
DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer, uint64_t *value)
DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfTypedData(Dart_Handle object)
DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t *request_json, intptr_t request_json_length, uint8_t **response_json, intptr_t *response_json_length, char **error)
DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function)
DART_EXPORT Dart_Handle Dart_StringGetProperties(Dart_Handle object, intptr_t *char_size, intptr_t *str_len, void **peer)
DART_EXPORT Dart_Handle Dart_NewIntegerFromUint64(uint64_t value)
DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate)
static void WeakPersistentHandlePeerCleanupEnsuresIGFinalizer(void *isolate_callback_data, void *peer)
static void NewNativePort_ExternalTypedData(Dart_Port dest_port_id, Dart_CObject *message)
DART_EXPORT bool Dart_IsMap(Dart_Handle object)
static void USE(T &&)
Definition: globals.h:618
static void NewNativePort_sendInteger321(Dart_Port dest_port_id, Dart_CObject *message)
DART_EXPORT Dart_Handle Dart_SetNativeResolver(Dart_Handle library, Dart_NativeEntryResolver resolver, Dart_NativeEntrySymbol symbol)
static constexpr intptr_t kNativeField1Value
DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj, double *value)
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
static Dart_PersistentHandle persistent_handle1
static void * finalizable_old_ref_peer
DART_EXPORT void Dart_ExitIsolate()
constexpr intptr_t GB
Definition: globals.h:532
static bool loop_test_exit
DART_EXPORT bool Dart_IsFunction(Dart_Handle handle)
DART_EXPORT char * Dart_IsolateMakeRunnable(Dart_Isolate isolate)
static void CreateNativePorts(uword param)
static void NewNativePort_nativeReceiveNull(Dart_Port dest_port_id, Dart_CObject *message)
static Dart_FinalizableHandle finalizable_old_ref
static Dart_NativeFunction NotifyDestroyed_native_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance)
DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id)
static void NativeFoo2(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data)
DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container, Dart_Handle name, Dart_Handle value)
TEST_CASE(DirectoryCurrent)
DART_EXPORT Dart_Handle Dart_StringLength(Dart_Handle str, intptr_t *len)
static void TestByteDataDirectAccess()
Dart_Handle NewString(const char *str)
static void * finalizable_new_ref_peer
DART_EXPORT bool Dart_IsTearOff(Dart_Handle object)
static Dart_Isolate RunLoopTestCallback(const char *script_name, const char *main, const char *package_root, const char *package_config, Dart_IsolateFlags *flags, void *data, char **error)
static void NativeArgumentCounter(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list, intptr_t offset, uint8_t *native_array, intptr_t length)
void HandleInterrupts(Thread *thread)
static void SlowFinalizer(void *isolate_callback_data, void *peer)
DART_EXPORT Dart_Handle Dart_RunLoop()
DART_EXPORT void * Dart_CurrentIsolateGroupData()
DART_EXPORT Dart_Handle Dart_NewListOfType(Dart_Handle element_type, intptr_t length)
static void CheckFloat32x4Data(Dart_Handle obj)
DART_EXPORT bool Dart_IsType(Dart_Handle handle)
static Dart_WeakPersistentHandle weak_persistent_handle3
DART_EXPORT Dart_Handle Dart_MapKeys(Dart_Handle map)
static void TestTypedDataDirectAccess1()
DART_EXPORT Dart_Handle Dart_InvokeClosure(Dart_Handle closure, int number_of_arguments, Dart_Handle *arguments)
Dart_Handle Dart_GetStackTraceFromError(Dart_Handle handle, Dart_StackTrace *trace)
DART_EXPORT char * Dart_SetVMFlags(int argc, const char **argv)
DART_EXPORT void Dart_NotifyIdle(int64_t deadline)
void InitHeapSampling(Thread *thread, const char *expected_cls)
static int8_t opt_data[kOptExtLength]
static void * NopResolver(const char *name, uintptr_t args_n)
DART_EXPORT void Dart_DeleteFinalizableHandle(Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object)
DART_EXPORT Dart_Handle Dart_SetLibraryTagHandler(Dart_LibraryTagHandler handler)
static const char * expected_allocation_cls
static Dart_Handle LoadScript(const char *url_str, const char *source)
DART_EXPORT Dart_Handle Dart_TypeVoid()
DART_EXPORT Dart_Handle Dart_MapContainsKey(Dart_Handle map, Dart_Handle key)
DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object)
DART_EXPORT void Dart_ExitScope()
DART_EXPORT int64_t Dart_TimelineGetTicksFrequency()
static void UnreachableFinalizer(void *isolate_callback_data, void *peer)
static intptr_t kNativeArgumentNativeField2Value
DART_EXPORT void Dart_RegisterHeapSamplingCallback(Dart_HeapSamplingCreateCallback create_callback, Dart_HeapSamplingDeleteCallback delete_callback)
DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfExternalTypedData(Dart_Handle object)
static void FinalizableHandleCallback(void *isolate_callback_data, void *peer)
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer, bool *fits)
static void WeakPersistentHandlePeerFinalizer(void *isolate_callback_data, void *peer)
DART_EXPORT Dart_Handle Dart_NewApiError(const char *error)
DART_EXPORT Dart_Handle Dart_ListGetRange(Dart_Handle list, intptr_t offset, intptr_t length, Dart_Handle *result)
DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t *len)
DART_EXPORT void Dart_SetMessageNotifyCallback(Dart_MessageNotifyCallback message_notify_callback)
DART_EXPORT Dart_Handle Dart_NewList(intptr_t length)
void ExceptionNative(Dart_NativeArguments args)
static Dart_Handle PrivateLibName(Dart_Handle lib, const char *str)
static Dart_NativeFunction NotifyLowMemory_native_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
constexpr intptr_t kWordSize
Definition: globals.h:509
static void * cleanup_isolate_group_data
DART_EXPORT void Dart_KillIsolate(Dart_Isolate handle)
DART_EXPORT Dart_Handle Dart_NewCompilationError(const char *error)
DART_EXPORT Dart_Handle Dart_GetNativeDoubleArgument(Dart_NativeArguments args, int index, double *value)
DART_EXPORT Dart_Handle Dart_ErrorGetException(Dart_Handle handle)
static void TestUnmodifiableTypedDataViewDirectAccess()
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url)
static constexpr intptr_t kObjectAlignment
DART_EXPORT bool Dart_IsList(Dart_Handle object)
static Dart_NativeFunction SecretKeeperNativeResolver(Dart_Handle name, int argument_count, bool *auto_setup_scope)
DART_EXPORT bool Dart_IsApiError(Dart_Handle object)
static void NativeFoo3(Dart_NativeArguments args)
DART_EXPORT void * Dart_CurrentIsolateData()
static void TestNativeFields(Dart_Handle retobj)
DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception)
static void ByteDataNativeFunction(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_GetNativeIntegerArgument(Dart_NativeArguments args, int index, int64_t *value)
static void CollectAllGarbage(Thread *thread, JSONStream *js)
Definition: service.cc:4559
DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args)
struct _Dart_StackTrace * Dart_StackTrace
DART_EXPORT Dart_Handle Dart_LoadScriptFromKernel(const uint8_t *buffer, intptr_t buffer_size)
DART_EXPORT bool Dart_IsInteger(Dart_Handle object)
static intptr_t ReturnPtrAsInt(void *ptr)
static constexpr intptr_t kOptExtLength
DART_EXPORT int64_t Dart_TimelineGetMicros()
DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1, Dart_Handle obj2, bool *value)
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
static void NewNativePort_send321(Dart_Port dest_port_id, Dart_CObject *message)
DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library)
DART_EXPORT Dart_Port Dart_NewNativePort(const char *name, Dart_NativeMessageHandler handler, bool handle_concurrently)
DART_EXPORT bool Dart_IsTypedData(Dart_Handle handle)
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject *message)
DART_EXPORT Dart_Handle Dart_Null()
void HeapSamplingReport(void *context, void *data)
static void SetPerformanceModeDefault(Dart_NativeArguments args)
static bool use_throw_exception
static Dart_NativeFunction OptExternalByteDataNativeResolver(Dart_Handle name, int arg_count, bool *auto_setup_scope)
DART_EXPORT void Dart_SetStickyError(Dart_Handle error)
DART_EXPORT bool Dart_IsString(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_New(Dart_Handle type, Dart_Handle constructor_name, int number_of_arguments, Dart_Handle *arguments)
const char *const function_name
static int8_t data[kExtLength]
static void TestTypedDataViewDirectAccess()
static Dart_NativeFunction gnac_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
DART_EXPORT Dart_Handle Dart_SetRootLibrary(Dart_Handle library)
DART_EXPORT Dart_Handle Dart_GetNativeBooleanArgument(Dart_NativeArguments args, int index, bool *value)
static void TestFieldNotFound(Dart_Handle container, Dart_Handle name)
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object, const char **cstr)
static int kLength
DART_EXPORT Dart_Handle Dart_HandleFromPersistent(Dart_PersistentHandle object)
DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library, Dart_Handle class_name, intptr_t number_of_type_arguments, Dart_Handle *type_arguments)
DART_EXPORT void Dart_ShutdownIsolate()
DART_EXPORT bool Dart_IsClosure(Dart_Handle object)
static void DontDeleteWeakHandleOnFinalization(void *isolate_callback_data, void *peer)
static void * cleanup_group_callback_data
DART_EXPORT Dart_Handle Dart_NewUnmodifiableExternalTypedDataWithFinalizer(Dart_TypedData_Type type, const void *data, intptr_t length, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback)
DART_EXPORT Dart_Handle Dart_GetDataFromByteBuffer(Dart_Handle object)
void ByteDataFinalizer(void *isolate_data, void *peer)
DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message)
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)
static void ExternalTypedDataFinalizer(void *isolate_callback_data, void *peer)
Definition: isolate.cc:1111
DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_GetNativeArguments(Dart_NativeArguments args, int num_arguments, const Dart_NativeArgument_Descriptor *argument_descriptors, Dart_NativeArgument_Value *arg_values)
static Dart_NativeFunction JustPropagateError_lookup(Dart_Handle name, int argument_count, bool *auto_setup_scope)
DART_EXPORT bool Dart_IsByteBuffer(Dart_Handle handle)
static void InvokeServiceMessages(uword param)
void VerifyStackOverflowStackTraceInfo(const char *script, const char *top_frame_func_name, const char *entry_func_name, int expected_line_number, int expected_column_number)
const intptr_t kMaxAddrSpaceMB
Definition: globals.h:49
DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2)
static void * shutdown_isolate_data
DART_EXPORT bool Dart_IsFatalError(Dart_Handle object)
static Dart_WeakPersistentHandle weak2
DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer, int64_t *value)
static void IsolateCleanupTestCallback(void *group_data, void *isolate_data)
DART_EXPORT Dart_Handle Dart_StringUTF8Length(Dart_Handle str, intptr_t *len)
static bool loop_reset_count
static void ImplicitReferencesCallback(void *isolate_callback_data, void *peer)
static Dart_FinalizableHandle finalizable_new_ref
DART_EXPORT void Dart_EnableHeapSampling()
DECLARE_FLAG(bool, show_invisible_frames)
static constexpr intptr_t kNativeField2Value
VM_UNIT_TEST_CASE(DirectoryCurrentNoScope)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
char * strdup(const char *str1)
std::function< void()> closure
Definition: closure.h:14
Definition: main.py:1
constexpr bool contains(std::string_view str, std::string_view needle)
Definition: SkStringView.h:41
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
Definition: SkVx.h:680
#define Pd64
Definition: globals.h:416
#define DART_INT64_C(x)
Definition: globals.h:433
#define T
Definition: precompiler.cc:65
Dart_OnNewCodeCallback on_new_code
Definition: dart_api.h:863
union _Dart_CObject::@86 value
Dart_CObject_Type type
struct _Dart_CObject::@86::@90 as_typed_data
struct _Dart_CObject ** values
struct _Dart_NativeArgument_Value::@84 as_native_fields
#define ZONE_STR(FMT,...)
Definition: unit_test.h:226
#define EXPECT_ERROR(handle, substring)
Definition: unit_test.h:663
#define RESOLVED_USER_TEST_URI
Definition: unit_test.h:317
#define EXPECT_VALID(handle)
Definition: unit_test.h:643
#define USER_TEST_URI
Definition: unit_test.h:316
#define ARRAY_SIZE(array)
Definition: globals.h:72