Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
396void VerifyStackOverflowStackTraceInfo(const char* script,
397 const char* top_frame_func_name,
398 const char* entry_func_name,
399 int expected_line_number,
400 int expected_column_number) {
401 Dart_Handle lib = TestCase::LoadTestScript(script, nullptr);
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
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
794 EXPECT(Dart_IsClosure(closure));
795 Dart_Handle result = Dart_InvokeClosure(closure, 0, nullptr);
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"));
1096 EXPECT_VALID(closure);
1097 if (Dart_IsClosure(closure)) {
1098 closure = Dart_ClosureFunction(closure);
1099 EXPECT_VALID(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"));
1116 EXPECT_VALID(closure);
1117 if (Dart_IsClosure(closure)) {
1118 closure = Dart_ClosureFunction(closure);
1119 EXPECT_VALID(closure);
1120 }
1121
1122 const char* url = "";
1123 Dart_Handle owner = Dart_FunctionOwner(closure);
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.
1168 Dart_Handle closure =
1169 Dart_GetStaticMethodClosure(lib, baz_cls, NewString("foo"));
1170 EXPECT_VALID(closure);
1171 EXPECT(Dart_IsTearOff(closure));
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);
1187 EXPECT_VALID(closure);
1188 EXPECT(Dart_IsTearOff(closure));
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"));
1200 EXPECT_VALID(closure);
1201 if (Dart_IsClosure(closure)) {
1202 closure = Dart_ClosureFunction(closure);
1203 EXPECT_VALID(closure);
1204 }
1205
1206 bool is_static = false;
1207 Dart_Handle result = Dart_FunctionIsStatic(closure, &is_static);
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"));
1218 EXPECT_VALID(closure);
1219 if (Dart_IsClosure(closure)) {
1220 closure = Dart_ClosureFunction(closure);
1221 EXPECT_VALID(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"));
1236 EXPECT_VALID(closure);
1237 EXPECT(Dart_IsClosure(closure));
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
1267 Dart_Handle closure =
1268 Dart_GetStaticMethodClosure(lib, foo_cls, NewString("getInt"));
1269 EXPECT_VALID(closure);
1270 EXPECT(Dart_IsClosure(closure));
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;
1535 Dart_Handle result = Dart_ListLength(val, &len);
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
1865 result = Dart_IntegerToInt64(values[0], &value);
1867 EXPECT_EQ(20, value);
1868
1869 result = Dart_IntegerToInt64(values[1], &value);
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.
1907 Dart_Handle map = result;
1908 Dart_Handle a = NewString("a");
1909 Dart_Handle b = NewString("b");
1910 Dart_Handle c = NewString("c");
1911
1912 EXPECT(Dart_IsMap(map));
1913 EXPECT(!Dart_IsMap(a));
1914
1915 // Access values in the map.
1916 int64_t value;
1917 result = Dart_MapGetAt(map, a);
1921 EXPECT_EQ(value, 1);
1922
1923 result = Dart_MapGetAt(map, b);
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.)
1956 Dart_Handle keys = Dart_MapKeys(map);
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];
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 = new UnmodifiableInt8ListView(a);\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
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 {
2376 GCTestHelper::CollectAllGarbage();
2377 }
2378
2380
2381 Dart_Handle result = Dart_Invoke(lib, NewString("releaseArray"), 0, nullptr);
2383
2384 {
2386 GCTestHelper::CollectAllGarbage();
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.");
2489 result = Dart_TypedDataAcquireData(str, &type, &data, &len);
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;
2531 result = Dart_TypedDataAcquireData(array, &type, &data, &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++) {
2571 GCTestHelper::CollectAllGarbage();
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 new UnmodifiableInt8ListView(list);"
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);
3192 GCTestHelper::CollectAllGarbage();
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);
3221 GCTestHelper::CollectAllGarbage();
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++) {
3337 Dart_DeletePersistentHandle(handles[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
3463
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.
3582 GCTestHelper::CollectAllGarbage();
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);
3704 GCTestHelper::CollectAllGarbage();
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);
3879 GCTestHelper::CollectAllGarbage();
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);
3919 GCTestHelper::CollectAllGarbage();
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");
4537 strong = Dart_NewPersistentHandle(local);
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");
4605 strong = Dart_NewPersistentHandle(local);
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 =
5034 ? Dart_GetNonNullableType(lib, NewString("MyClass0"), 2, &type_args)
5035 : Dart_GetType(lib, NewString("MyClass0"), 2, &type_args);
5036 EXPECT_VALID(myclass0_type);
5037
5038 type_args = Dart_NewList(2);
5039 Dart_Handle list_int_type =
5040 Dart_Invoke(lib, NewString("getListIntType"), 0, nullptr);
5041 EXPECT_VALID(list_int_type);
5042 EXPECT_VALID(Dart_ListSetAt(type_args, 0, list_int_type));
5043 Dart_Handle list_type =
5044 Dart_Invoke(lib, NewString("getListType"), 0, nullptr);
5045 EXPECT_VALID(list_type);
5046 EXPECT_VALID(Dart_ListSetAt(type_args, 1, list_type));
5047 Dart_Handle myclass1_type =
5049 ? Dart_GetNonNullableType(lib, NewString("MyClass1"), 2, &type_args)
5050 : Dart_GetType(lib, NewString("MyClass1"), 2, &type_args);
5051 EXPECT_VALID(myclass1_type);
5052
5053 // Now create objects of the type and validate the object type matches
5054 // the one returned above. Also get the runtime type of the object and
5055 // verify that it matches the type returned above. Note: we use
5056 // Dart_ObjectEquals instead of Dart_IdentityEquals since we are comparing
5057 // type literals with non-literals which would fail in unsound null safety
5058 // mode.
5059 // MyClass0<int, double> type.
5060 Dart_Handle type0_obj =
5061 Dart_Invoke(lib, NewString("getMyClass0"), 0, nullptr);
5062 EXPECT_VALID(type0_obj);
5063 bool instanceOf = false;
5064 EXPECT_VALID(Dart_ObjectIsType(type0_obj, myclass0_type, &instanceOf));
5065 EXPECT(instanceOf);
5066 type0_obj = Dart_Invoke(lib, NewString("getMyClass0Type"), 0, nullptr);
5067 EXPECT_VALID(type0_obj);
5068
5069 bool equal = false;
5070 EXPECT_VALID(Dart_ObjectEquals(type0_obj, myclass0_type, &equal));
5071 EXPECT(equal);
5072
5073 // MyClass1<List<int>, List> type.
5074 Dart_Handle type1_obj =
5075 Dart_Invoke(lib, NewString("getMyClass1"), 0, nullptr);
5076 EXPECT_VALID(type1_obj);
5077 EXPECT_VALID(Dart_ObjectIsType(type1_obj, myclass1_type, &instanceOf));
5078 EXPECT(instanceOf);
5079 type1_obj = Dart_Invoke(lib, NewString("getMyClass1Type"), 0, nullptr);
5080 EXPECT_VALID(type1_obj);
5081
5082 EXPECT_VALID(Dart_ObjectEquals(type1_obj, myclass1_type, &equal));
5083 EXPECT(equal);
5084
5085 // MyClass0<double, int> type.
5086 type0_obj = Dart_Invoke(lib, NewString("getMyClass0_1"), 0, nullptr);
5087 EXPECT_VALID(type0_obj);
5088 EXPECT_VALID(Dart_ObjectIsType(type0_obj, myclass0_type, &instanceOf));
5089 EXPECT(!instanceOf);
5090 type0_obj = Dart_Invoke(lib, NewString("getMyClass0_1Type"), 0, nullptr);
5091 EXPECT_VALID(type0_obj);
5092 EXPECT_VALID(Dart_ObjectEquals(type0_obj, myclass0_type, &equal));
5093 EXPECT(!equal);
5094
5095 // MyClass1<List<int>, List<double>> type.
5096 type1_obj = Dart_Invoke(lib, NewString("getMyClass1_1"), 0, nullptr);
5097 EXPECT_VALID(type1_obj);
5098 EXPECT_VALID(Dart_ObjectIsType(type1_obj, myclass1_type, &instanceOf));
5099 EXPECT(instanceOf);
5100 type1_obj = Dart_Invoke(lib, NewString("getMyClass1_1Type"), 0, nullptr);
5101 EXPECT_VALID(type1_obj);
5102 EXPECT_VALID(Dart_ObjectEquals(type1_obj, myclass1_type, &equal));
5103 EXPECT(!equal);
5104}
5105
5106static void TestFieldOk(Dart_Handle container,
5108 bool final,
5109 const char* initial_value) {
5111
5112 // Make sure we have the right initial value.
5113 result = Dart_GetField(container, name);
5115 const char* value = "";
5117 EXPECT_STREQ(initial_value, value);
5118
5119 // Use a unique expected value.
5120 static int counter = 0;
5121 char buffer[256];
5122 Utils::SNPrint(buffer, 256, "Expected%d", ++counter);
5123
5124 // Try to change the field value.
5125 result = Dart_SetField(container, name, NewString(buffer));
5126 if (final) {
5128 } else {
5130 }
5131
5132 // Make sure we have the right final value.
5133 result = Dart_GetField(container, name);
5136 if (final) {
5137 EXPECT_STREQ(initial_value, value);
5138 } else {
5139 EXPECT_STREQ(buffer, value);
5140 }
5141}
5142
5144 EXPECT_ERROR(Dart_GetField(container, name), "NoSuchMethodError");
5146 "NoSuchMethodError");
5147}
5148
5149TEST_CASE(DartAPI_FieldAccess) {
5150 const char* kScriptChars =
5151 "class BaseFields {\n"
5152 " BaseFields()\n"
5153 " : this.inherited_fld = 'inherited' {\n"
5154 " }\n"
5155 " var inherited_fld;\n"
5156 " static var non_inherited_fld;\n"
5157 "}\n"
5158 "\n"
5159 "class Fields extends BaseFields {\n"
5160 " Fields()\n"
5161 " : this.instance_fld = 'instance',\n"
5162 " this._instance_fld = 'hidden instance',\n"
5163 " this.final_instance_fld = 'final instance',\n"
5164 " this._final_instance_fld = 'hidden final instance' {\n"
5165 " instance_getset_fld = 'instance getset';\n"
5166 " _instance_getset_fld = 'hidden instance getset';\n"
5167 " }\n"
5168 "\n"
5169 " static Init() {\n"
5170 " static_fld = 'static';\n"
5171 " _static_fld = 'hidden static';\n"
5172 " static_getset_fld = 'static getset';\n"
5173 " _static_getset_fld = 'hidden static getset';\n"
5174 " }\n"
5175 "\n"
5176 " var instance_fld;\n"
5177 " var _instance_fld;\n"
5178 " final final_instance_fld;\n"
5179 " final _final_instance_fld;\n"
5180 " static var static_fld;\n"
5181 " static var _static_fld;\n"
5182 " static const const_static_fld = 'const static';\n"
5183 " static const _const_static_fld = 'hidden const static';\n"
5184 "\n"
5185 " get instance_getset_fld { return _gs_fld1; }\n"
5186 " void set instance_getset_fld(var value) { _gs_fld1 = value; }\n"
5187 " get _instance_getset_fld { return _gs_fld2; }\n"
5188 " void set _instance_getset_fld(var value) { _gs_fld2 = value; }\n"
5189 " var _gs_fld1;\n"
5190 " var _gs_fld2;\n"
5191 "\n"
5192 " static get static_getset_fld { return _gs_fld3; }\n"
5193 " static void set static_getset_fld(var value) { _gs_fld3 = value; }\n"
5194 " static get _static_getset_fld { return _gs_fld4; }\n"
5195 " static void set _static_getset_fld(var value) { _gs_fld4 = value; }\n"
5196 " static var _gs_fld3;\n"
5197 " static var _gs_fld4;\n"
5198 "}\n"
5199 "var top_fld;\n"
5200 "var _top_fld;\n"
5201 "const const_top_fld = 'const top';\n"
5202 "const _const_top_fld = 'hidden const top';\n"
5203 "\n"
5204 "get top_getset_fld { return _gs_fld5; }\n"
5205 "void set top_getset_fld(var value) { _gs_fld5 = value; }\n"
5206 "get _top_getset_fld { return _gs_fld6; }\n"
5207 "void set _top_getset_fld(var value) { _gs_fld6 = value; }\n"
5208 "var _gs_fld5;\n"
5209 "var _gs_fld6;\n"
5210 "\n"
5211 "Fields test() {\n"
5212 " Fields.Init();\n"
5213 " top_fld = 'top';\n"
5214 " _top_fld = 'hidden top';\n"
5215 " top_getset_fld = 'top getset';\n"
5216 " _top_getset_fld = 'hidden top getset';\n"
5217 " return new Fields();\n"
5218 "}\n";
5219 const char* kImportedScriptChars =
5220 "library library_name;\n"
5221 "var imported_fld = 'imported';\n"
5222 "var _imported_fld = 'hidden imported';\n"
5223 "get imported_getset_fld { return _gs_fld1; }\n"
5224 "void set imported_getset_fld(var value) { _gs_fld1 = value; }\n"
5225 "get _imported_getset_fld { return _gs_fld2; }\n"
5226 "void set _imported_getset_fld(var value) { _gs_fld2 = value; }\n"
5227 "var _gs_fld1;\n"
5228 "var _gs_fld2;\n"
5229 "void test2() {\n"
5230 " imported_getset_fld = 'imported getset';\n"
5231 " _imported_getset_fld = 'hidden imported getset';\n"
5232 "}\n";
5233
5234 // Shared setup.
5235 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5237 Dart_GetNonNullableType(lib, NewString("Fields"), 0, nullptr);
5239 Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, nullptr);
5242
5243 // Load imported lib.
5244 Dart_Handle imported_lib =
5245 TestCase::LoadTestLibrary("library_url", kImportedScriptChars);
5246 EXPECT_VALID(imported_lib);
5249 result = Dart_Invoke(imported_lib, NewString("test2"), 0, nullptr);
5251
5252 // Instance field.
5253 name = NewString("instance_fld");
5254 TestFieldNotFound(lib, name);
5256 TestFieldOk(instance, name, false, "instance");
5257
5258 // Hidden instance field.
5259 name = NewString("_instance_fld");
5260 TestFieldNotFound(lib, name);
5262 TestFieldOk(instance, name, false, "hidden instance");
5263
5264 // Final instance field.
5265 name = NewString("final_instance_fld");
5266 TestFieldNotFound(lib, name);
5268 TestFieldOk(instance, name, true, "final instance");
5269
5270 // Hidden final instance field.
5271 name = NewString("_final_instance_fld");
5272 TestFieldNotFound(lib, name);
5274 TestFieldOk(instance, name, true, "hidden final instance");
5275
5276 // Inherited field.
5277 name = NewString("inherited_fld");
5278 TestFieldNotFound(lib, name);
5280 TestFieldOk(instance, name, false, "inherited");
5281
5282 // Instance get/set field.
5283 name = NewString("instance_getset_fld");
5284 TestFieldNotFound(lib, name);
5286 TestFieldOk(instance, name, false, "instance getset");
5287
5288 // Hidden instance get/set field.
5289 name = NewString("_instance_getset_fld");
5290 TestFieldNotFound(lib, name);
5292 TestFieldOk(instance, name, false, "hidden instance getset");
5293
5294 // Static field.
5295 name = NewString("static_fld");
5296 TestFieldNotFound(lib, name);
5298 TestFieldOk(type, name, false, "static");
5299
5300 // Hidden static field.
5301 name = NewString("_static_fld");
5302 TestFieldNotFound(lib, name);
5304 TestFieldOk(type, name, false, "hidden static");
5305
5306 // Static final field.
5307 name = NewString("const_static_fld");
5308 TestFieldNotFound(lib, name);
5310 TestFieldOk(type, name, true, "const static");
5311
5312 // Hidden static const field.
5313 name = NewString("_const_static_fld");
5314 TestFieldNotFound(lib, name);
5316 TestFieldOk(type, name, true, "hidden const static");
5317
5318 // Static non-inherited field. Not found at any level.
5319 name = NewString("non_inherited_fld");
5320 TestFieldNotFound(lib, name);
5323
5324 // Static get/set field.
5325 name = NewString("static_getset_fld");
5326 TestFieldNotFound(lib, name);
5328 TestFieldOk(type, name, false, "static getset");
5329
5330 // Hidden static get/set field.
5331 name = NewString("_static_getset_fld");
5332 TestFieldNotFound(lib, name);
5334 TestFieldOk(type, name, false, "hidden static getset");
5335
5336 // Top-Level field.
5337 name = NewString("top_fld");
5340 TestFieldOk(lib, name, false, "top");
5341
5342 // Hidden top-level field.
5343 name = NewString("_top_fld");
5346 TestFieldOk(lib, name, false, "hidden top");
5347
5348 // Top-Level final field.
5349 name = NewString("const_top_fld");
5352 TestFieldOk(lib, name, true, "const top");
5353
5354 // Hidden top-level final field.
5355 name = NewString("_const_top_fld");
5358 TestFieldOk(lib, name, true, "hidden const top");
5359
5360 // Top-Level get/set field.
5361 name = NewString("top_getset_fld");
5364 TestFieldOk(lib, name, false, "top getset");
5365
5366 // Hidden top-level get/set field.
5367 name = NewString("_top_getset_fld");
5370 TestFieldOk(lib, name, false, "hidden top getset");
5371
5372 // Imported top-Level field.
5373 name = NewString("imported_fld");
5376 TestFieldNotFound(lib, name);
5377
5378 // Hidden imported top-level field. Not found at any level.
5379 name = NewString("_imported_fld");
5382 TestFieldNotFound(lib, name);
5383
5384 // Imported top-Level get/set field.
5385 name = NewString("imported_getset_fld");
5388 TestFieldNotFound(lib, name);
5389
5390 // Hidden imported top-level get/set field. Not found at any level.
5391 name = NewString("_imported_getset_fld");
5394 TestFieldNotFound(lib, name);
5395}
5396
5397TEST_CASE(DartAPI_SetField_FunnyValue) {
5398 const char* kScriptChars = "var top;\n";
5399
5400 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5401 Dart_Handle name = NewString("top");
5402 bool value;
5403
5404 // Test that you can set the field to a good value.
5410 EXPECT(value);
5411
5412 // Test that you can set the field to null
5414 result = Dart_GetField(lib, name);
5417
5418 // Pass a non-instance handle.
5419 result = Dart_SetField(lib, name, lib);
5421 result, "Dart_SetField expects argument 'value' to be of type Instance.");
5422
5423 // Pass an error handle. The error is contagious.
5424 result = Dart_SetField(lib, name, Api::NewError("myerror"));
5426 EXPECT_STREQ("myerror", Dart_GetError(result));
5427}
5428
5429TEST_CASE(DartAPI_SetField_BadType) {
5430 const char* kScriptChars =
5431 TestCase::IsNNBD() ? "late int foo;\n" : "int foo;\n";
5432 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5433 Dart_Handle name = NewString("foo");
5436 EXPECT_SUBSTRING("type 'bool' is not a subtype of type 'int' of 'foo'",
5438}
5439
5443
5445 int argument_count,
5446 bool* auto_setup_scope) {
5447 ASSERT(auto_setup_scope != nullptr);
5448 *auto_setup_scope = false;
5449 return NativeFieldLookup;
5450}
5451
5452TEST_CASE(DartAPI_InjectNativeFields2) {
5453 // clang-format off
5454 auto kScriptChars = Utils::CStringUniquePtr(
5455 OS::SCreate(nullptr,
5456 "class NativeFields extends NativeFieldsWrapper {\n"
5457 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5458 " int fld1;\n"
5459 " final int fld;\n"
5460 " static int%s fld3;\n"
5461 " static const int fld4 = 10;\n"
5462 "}\n"
5463 "NativeFields testMain() {\n"
5464 " NativeFields obj = new NativeFields(10, 20);\n"
5465 " return obj;\n"
5466 "}\n",
5467 TestCase::NullableTag()), std::free);
5468 // clang-format on
5469
5471 // Create a test library and Load up a test script in it.
5472 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(), nullptr,
5473 USER_TEST_URI, false);
5474
5475 // Invoke a function which returns an object of type NativeFields.
5476 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5477
5478 // We expect this to fail as class "NativeFields" extends
5479 // "NativeFieldsWrapper" and there is no definition of it either
5480 // in the dart code or through the native field injection mechanism.
5482}
5483
5484TEST_CASE(DartAPI_InjectNativeFields3) {
5485 // clang-format off
5486 auto kScriptChars = Utils::CStringUniquePtr(
5487 OS::SCreate(nullptr,
5488 "import 'dart:nativewrappers';"
5489 "final class NativeFields "
5490 "extends NativeFieldWrapperClass2 {\n"
5491 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5492 " int fld1;\n"
5493 " final int fld2;\n"
5494 " static int%s fld3;\n"
5495 " static const int fld4 = 10;\n"
5496 "}\n"
5497 "NativeFields testMain() {\n"
5498 " NativeFields obj = new NativeFields(10, 20);\n"
5499 " return obj;\n"
5500 "}\n",
5501 TestCase::NullableTag()), std::free);
5502 // clang-format on
5504 const int kNumNativeFields = 2;
5505
5506 // Load up a test script in the test library.
5507 Dart_Handle lib =
5508 TestCase::LoadTestScript(kScriptChars.get(), native_field_lookup);
5509
5510 // Invoke a function which returns an object of type NativeFields.
5511 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5513 CHECK_API_SCOPE(thread);
5514 TransitionNativeToVM transition(thread);
5515 HANDLESCOPE(thread);
5516 Instance& obj = Instance::Handle();
5517 obj ^= Api::UnwrapHandle(result);
5518 const Class& cls = Class::Handle(obj.clazz());
5519 // We expect the newly created "NativeFields" object to have
5520 // 2 dart instance fields (fld1, fld2) and a reference to the native fields.
5521 // Hence the size of an instance of "NativeFields" should be
5522 // (1 + 2) * kWordSize + size of object header.
5523 // We check to make sure the instance size computed by the VM matches
5524 // our expectations.
5525 intptr_t header_size = sizeof(UntaggedObject);
5526 EXPECT_EQ(
5527 Utils::RoundUp(((1 + 2) * kWordSize) + header_size, kObjectAlignment),
5528 cls.host_instance_size());
5529 EXPECT_EQ(kNumNativeFields, cls.num_native_fields());
5530}
5531
5532TEST_CASE(DartAPI_InjectNativeFields4) {
5533 // clang-format off
5534 auto kScriptChars = Utils::CStringUniquePtr(
5535 OS::SCreate(nullptr,
5536 "class NativeFields extends NativeFieldsWrapperClass2 {\n"
5537 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5538 " int fld1;\n"
5539 " final int fld;\n"
5540 " static int%s fld3;\n"
5541 " static const int fld4 = 10;\n"
5542 "}\n"
5543 "NativeFields testMain() {\n"
5544 " NativeFields obj = new NativeFields(10, 20);\n"
5545 " return obj;\n"
5546 "}\n",
5547 TestCase::NullableTag()), std::free);
5548 // clang-format on
5550 // Load up a test script in the test library.
5551 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(), nullptr);
5552
5553 // Invoke a function which returns an object of type NativeFields.
5554 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5555
5556 USE(result);
5557#if 0
5558 // TODO(12455) Need better validation.
5559 // We expect the test script to fail finalization with the error below:
5561 Dart_Handle expected_error = DartUtils::NewError(
5562 "'dart:test-lib': Error: line 1 pos 36: "
5563 "class 'NativeFields' is trying to extend a native fields class, "
5564 "but library '%s' has no native resolvers",
5565 TestCase::url());
5566 EXPECT_SUBSTRING(Dart_GetError(expected_error), Dart_GetError(result));
5567#endif
5568}
5569
5570static constexpr int kTestNumNativeFields = 2;
5571static constexpr intptr_t kNativeField1Value = 30;
5572static constexpr intptr_t kNativeField2Value = 40;
5573
5579
5581 intptr_t field_values[kTestNumNativeFields];
5583 args, 0, kTestNumNativeFields, field_values);
5585 EXPECT_EQ(kNativeField1Value, field_values[0]);
5586 EXPECT_EQ(kNativeField2Value, field_values[1]);
5588 field_values);
5590 EXPECT_EQ(0, field_values[0]);
5591 EXPECT_EQ(0, field_values[1]);
5592}
5593
5595 intptr_t field_values[kTestNumNativeFields];
5597 args, 0, kTestNumNativeFields, field_values);
5599 "Dart_GetNativeFieldsOfArgument: "
5600 "expected 0 'num_fields' but was passed in 2");
5601}
5602
5604 int argument_count,
5605 bool* auto_scope) {
5606 ASSERT(auto_scope != nullptr);
5607 *auto_scope = true;
5610 if (!obj.IsString()) {
5611 return nullptr;
5612 }
5613 const char* function_name = obj.ToCString();
5614 ASSERT(function_name != nullptr);
5615 if (strcmp(function_name, "TestNativeFieldsAccess_init") == 0) {
5617 } else if (strcmp(function_name, "TestNativeFieldsAccess_access") == 0) {
5619 } else if (strcmp(function_name, "TestNativeFieldsAccess_invalidAccess") ==
5620 0) {
5622 } else {
5623 return nullptr;
5624 }
5625}
5626
5627TEST_CASE(DartAPI_TestNativeFieldsAccess) {
5628 const char* nullable_tag = TestCase::NullableTag();
5629 // clang-format off
5630 auto kScriptChars = Utils::CStringUniquePtr(
5632 nullptr, R"(
5633 import 'dart:nativewrappers';
5634 base class NativeFields extends NativeFieldWrapperClass2 {
5635 NativeFields(int i, int j) : fld1 = i, fld2 = j {}
5636 int fld1;
5637 final int fld2;
5638 static int%s fld3;
5639 static const int fld4 = 10;
5640 @pragma('vm:external-name', 'TestNativeFieldsAccess_init')
5641 external int%s initNativeFlds();
5642 @pragma('vm:external-name', 'TestNativeFieldsAccess_access')
5643 external int%s accessNativeFlds(int%s i);
5644 }
5645 class NoNativeFields {
5646 int neitherATypedDataNorNull = 0;
5647 @pragma('vm:external-name', 'TestNativeFieldsAccess_invalidAccess')
5648 external invalidAccess();
5649 }
5650 NativeFields testMain() {
5651 NativeFields obj = new NativeFields(10, 20);
5652 obj.initNativeFlds();
5653 obj.accessNativeFlds(null);
5654 new NoNativeFields().invalidAccess();
5655 return obj;
5656 }
5657 )",
5658 nullable_tag, nullable_tag, nullable_tag, nullable_tag),
5659 std::free);
5660 // clang-format on
5661
5662 // Load up a test script in the test library.
5663 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(),
5665
5666 // Invoke a function which returns an object of type NativeFields.
5667 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5669}
5670
5671TEST_CASE(DartAPI_InjectNativeFieldsSuperClass) {
5672 const char* kScriptChars =
5673 "import 'dart:nativewrappers';"
5674 "base class NativeFieldsSuper extends NativeFieldWrapperClass1 {\n"
5675 " NativeFieldsSuper() : fld1 = 42 {}\n"
5676 " int fld1;\n"
5677 "}\n"
5678 "base class NativeFields extends NativeFieldsSuper {\n"
5679 " fld() => fld1;\n"
5680 "}\n"
5681 "int testMain() {\n"
5682 " NativeFields obj = new NativeFields();\n"
5683 " return obj.fld();\n"
5684 "}\n";
5686 // Load up a test script in the test library.
5688
5689 // Invoke a function which returns an object of type NativeFields.
5690 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5691
5694 int64_t value = 0;
5697 EXPECT_EQ(42, value);
5698}
5699
5700static void TestNativeFields(Dart_Handle retobj) {
5701 // Access and set various instance fields of the object.
5702 Dart_Handle result = Dart_GetField(retobj, NewString("fld3"));
5704 result = Dart_GetField(retobj, NewString("fld0"));
5707 result = Dart_GetField(retobj, NewString("fld1"));
5709 int64_t value = 0;
5711 EXPECT_EQ(10, value);
5712 result = Dart_GetField(retobj, NewString("fld2"));
5715 EXPECT_EQ(20, value);
5716 result = Dart_SetField(retobj, NewString("fld2"), Dart_NewInteger(40));
5718 result = Dart_SetField(retobj, NewString("fld1"), Dart_NewInteger(40));
5720 result = Dart_GetField(retobj, NewString("fld1"));
5723 EXPECT_EQ(40, value);
5724
5725 // Now access and set various native instance fields of the returned object.
5726 const int kNativeFld0 = 0;
5727 const int kNativeFld1 = 1;
5728 const int kNativeFld2 = 2;
5729 const int kNativeFld3 = 3;
5730 const int kNativeFld4 = 4;
5731 int field_count = 0;
5732 intptr_t field_value = 0;
5733 EXPECT_VALID(Dart_GetNativeInstanceFieldCount(retobj, &field_count));
5734 EXPECT_EQ(4, field_count);
5735 result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &field_value);
5737 result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &field_value);
5739 EXPECT_EQ(0, field_value);
5740 result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &field_value);
5742 EXPECT_EQ(0, field_value);
5743 result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &field_value);
5745 EXPECT_EQ(0, field_value);
5746 result = Dart_GetNativeInstanceField(retobj, kNativeFld3, &field_value);
5748 EXPECT_EQ(0, field_value);
5749 result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
5751 result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 4);
5753 result = Dart_SetNativeInstanceField(retobj, kNativeFld1, 40);
5755 result = Dart_SetNativeInstanceField(retobj, kNativeFld2, 400);
5757 result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 4000);
5759 result = Dart_GetNativeInstanceField(retobj, kNativeFld3, &field_value);
5761 EXPECT_EQ(4000, field_value);
5762
5763 // Now re-access various dart instance fields of the returned object
5764 // to ensure that there was no corruption while setting native fields.
5765 result = Dart_GetField(retobj, NewString("fld1"));
5768 EXPECT_EQ(40, value);
5769 result = Dart_GetField(retobj, NewString("fld2"));
5772 EXPECT_EQ(20, value);
5773}
5774
5775TEST_CASE(DartAPI_ImplicitNativeFieldAccess) {
5776 const char* nullable_tag = TestCase::NullableTag();
5777 // clang-format off
5778 auto kScriptChars = Utils::CStringUniquePtr(
5779 OS::SCreate(nullptr,
5780 "import 'dart:nativewrappers';"
5781 "final class NativeFields extends "
5782 "NativeFieldWrapperClass4 {\n"
5783 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5784 " int%s fld0;\n"
5785 " int fld1;\n"
5786 " final int fld2;\n"
5787 " static int%s fld3;\n"
5788 " static const int fld4 = 10;\n"
5789 "}\n"
5790 "NativeFields testMain() {\n"
5791 " NativeFields obj = new NativeFields(10, 20);\n"
5792 " return obj;\n"
5793 "}\n",
5794 nullable_tag, nullable_tag),
5795 std::free);
5796 // clang-format on
5797 // Load up a test script in the test library.
5798 Dart_Handle lib =
5799 TestCase::LoadTestScript(kScriptChars.get(), native_field_lookup);
5800
5801 // Invoke a function which returns an object of type NativeFields.
5802 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
5803 EXPECT_VALID(retobj);
5804
5805 // Now access and set various instance fields of the returned object.
5806 TestNativeFields(retobj);
5807}
5808
5809TEST_CASE(DartAPI_NegativeNativeFieldAccess) {
5810 // clang-format off
5811 auto kScriptChars = Utils::CStringUniquePtr(
5812 OS::SCreate(nullptr,
5813 "import 'dart:nativewrappers';\n"
5814 "class NativeFields {\n"
5815 " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
5816 " int fld1;\n"
5817 " final int fld2;\n"
5818 " static int%s fld3;\n"
5819 " static const int fld4 = 10;\n"
5820 "}\n"
5821 "NativeFields testMain1() {\n"
5822 " NativeFields obj = new NativeFields(10, 20);\n"
5823 " return obj;\n"
5824 "}\n"
5825 "Function testMain2() {\n"
5826 " return () {};\n"
5827 "}\n",
5829 std::free);
5830 // clang-format on
5831
5833 CHECK_API_SCOPE(thread);
5834
5835 // Create a test library and Load up a test script in it.
5836 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(), nullptr);
5837
5838 // Invoke a function which returns an object of type NativeFields.
5839 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain1"), 0, nullptr);
5840 EXPECT_VALID(retobj);
5841
5842 // Now access and set various native instance fields of the returned object.
5843 // All of these tests are expected to return failure as there are no
5844 // native fields in an instance of NativeFields.
5845 const int kNativeFld0 = 0;
5846 const int kNativeFld1 = 1;
5847 const int kNativeFld2 = 2;
5848 const int kNativeFld3 = 3;
5849 const int kNativeFld4 = 4;
5850 intptr_t value = 0;
5851 result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &value);
5853 result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &value);
5855 result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &value);
5857 result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &value);
5859 result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
5861 result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 40);
5863 result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 400);
5865
5866 // Invoke a function which returns a closure object.
5867 retobj = Dart_Invoke(lib, NewString("testMain2"), 0, nullptr);
5868 EXPECT_VALID(retobj);
5869
5870 result = Dart_GetNativeInstanceField(retobj, kNativeFld4, &value);
5872 result = Dart_GetNativeInstanceField(retobj, kNativeFld0, &value);
5874 result = Dart_GetNativeInstanceField(retobj, kNativeFld1, &value);
5876 result = Dart_GetNativeInstanceField(retobj, kNativeFld2, &value);
5878 result = Dart_SetNativeInstanceField(retobj, kNativeFld4, 40);
5880 result = Dart_SetNativeInstanceField(retobj, kNativeFld3, 40);
5882 result = Dart_SetNativeInstanceField(retobj, kNativeFld0, 400);
5884}
5885
5886TEST_CASE(DartAPI_GetStaticField_RunsInitializer) {
5887 const char* kScriptChars =
5888 "class TestClass {\n"
5889 " static const int fld1 = 7;\n"
5890 " static int fld2 = 11;\n"
5891 " static void testMain() {\n"
5892 " }\n"
5893 "}\n";
5895 // Create a test library and Load up a test script in it.
5896 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5898 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, nullptr);
5900
5901 // Invoke a function which returns an object.
5902 result = Dart_Invoke(type, NewString("testMain"), 0, nullptr);
5904
5905 // For uninitialized fields, the getter is returned
5906 result = Dart_GetField(type, NewString("fld1"));
5908 int64_t value = 0;
5910 EXPECT_EQ(7, value);
5911
5912 result = Dart_GetField(type, NewString("fld2"));
5915 EXPECT_EQ(11, value);
5916
5917 // Overwrite fld2
5920
5921 // We now get the new value for fld2, not the initializer
5922 result = Dart_GetField(type, NewString("fld2"));
5925 EXPECT_EQ(13, value);
5926}
5927
5928TEST_CASE(DartAPI_GetField_CheckIsolate) {
5929 const char* kScriptChars =
5930 "class TestClass {\n"
5931 " static int fld2 = 11;\n"
5932 " static void testMain() {\n"
5933 " }\n"
5934 "}\n";
5936 int64_t value = 0;
5937
5938 // Create a test library and Load up a test script in it.
5939 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5941 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, nullptr);
5943
5944 result = Dart_GetField(type, NewString("fld2"));
5947 EXPECT_EQ(11, value);
5948}
5949
5950TEST_CASE(DartAPI_SetField_CheckIsolate) {
5951 const char* kScriptChars =
5952 "class TestClass {\n"
5953 " static int fld2 = 11;\n"
5954 " static void testMain() {\n"
5955 " }\n"
5956 "}\n";
5958 int64_t value = 0;
5959
5960 // Create a test library and Load up a test script in it.
5961 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
5963 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, nullptr);
5965
5968
5969 result = Dart_GetField(type, NewString("fld2"));
5972 EXPECT_EQ(13, value);
5973}
5974
5975TEST_CASE(DartAPI_New) {
5976 const char* kScriptChars =
5977 "class MyClass implements MyExtraHop {\n"
5978 " MyClass() : foo = 7 {}\n"
5979 " MyClass.named(value) : foo = value {}\n"
5980 " MyClass._hidden(value) : foo = -value {}\n"
5981 " MyClass.exception(value) : foo = value {\n"
5982 " throw 'ConstructorDeath';\n"
5983 " }\n"
5984 " factory MyClass.multiply(value) {\n"
5985 " return new MyClass.named(value * 100);\n"
5986 " }\n"
5987 " var foo;\n"
5988 "}\n"
5989 "\n"
5990 "abstract class MyExtraHop implements MyInterface {\n"
5991 " factory MyExtraHop.hop(value) = MyClass.named;\n"
5992 "}\n"
5993 "\n"
5994 "abstract class MyInterface {\n"
5995 " factory MyInterface.named(value) = MyExtraHop.hop;\n"
5996 " factory MyInterface.multiply(value) = MyClass.multiply;\n"
5997 " MyInterface.notfound(value);\n"
5998 "}\n"
5999 "\n"
6000 "class _MyClass {\n"
6001 " _MyClass._() : foo = 7 {}\n"
6002 " var foo;\n"
6003 "}\n"
6004 "\n";
6005
6006 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6008 Dart_GetNonNullableType(lib, NewString("MyClass"), 0, nullptr);
6010 Dart_Handle intf =
6011 Dart_GetNonNullableType(lib, NewString("MyInterface"), 0, nullptr);
6012 EXPECT_VALID(intf);
6013 Dart_Handle private_type =
6014 Dart_GetNonNullableType(lib, NewString("_MyClass"), 0, nullptr);
6015 EXPECT_VALID(private_type);
6016
6017 Dart_Handle args[1];
6018 args[0] = Dart_NewInteger(11);
6019 Dart_Handle bad_args[1];
6020 bad_args[0] = Dart_NewApiError("myerror");
6021
6022 // Allocate and Invoke the unnamed constructor passing in Dart_Null.
6023 Dart_Handle result = Dart_New(type, Dart_Null(), 0, nullptr);
6025 bool instanceOf = false;
6026 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6027 EXPECT(instanceOf);
6028 int64_t int_value = 0;
6030 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6031 EXPECT_EQ(7, int_value);
6032
6033 // Allocate without a constructor.
6035 EXPECT_VALID(obj);
6036 instanceOf = false;
6037 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
6038 EXPECT(instanceOf);
6039 foo = Dart_GetField(obj, NewString("foo"));
6040 EXPECT(Dart_IsNull(foo));
6041
6042 // Allocate and Invoke the unnamed constructor passing in an empty string.
6043 result = Dart_New(type, Dart_EmptyString(), 0, nullptr);
6045 instanceOf = false;
6046 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6047 EXPECT(instanceOf);
6048 int_value = 0;
6049 foo = Dart_GetField(result, NewString("foo"));
6050 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6051 EXPECT_EQ(7, int_value);
6052
6053 // Allocate object and invoke the unnamed constructor with an empty string.
6054 obj = Dart_Allocate(type);
6055 EXPECT_VALID(obj);
6056 instanceOf = false;
6057 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
6058 EXPECT(instanceOf);
6059 // Use the empty string to invoke the unnamed constructor.
6060 result = Dart_InvokeConstructor(obj, Dart_EmptyString(), 0, nullptr);
6062 int_value = 0;
6063 foo = Dart_GetField(result, NewString("foo"));
6064 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6065 EXPECT_EQ(7, int_value);
6066 // use Dart_Null to invoke the unnamed constructor.
6067 result = Dart_InvokeConstructor(obj, Dart_Null(), 0, nullptr);
6069 int_value = 0;
6070 foo = Dart_GetField(result, NewString("foo"));
6071 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6072 EXPECT_EQ(7, int_value);
6073
6074 // Invoke a named constructor.
6075 result = Dart_New(type, NewString("named"), 1, args);
6077 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6078 EXPECT(instanceOf);
6079 int_value = 0;
6080 foo = Dart_GetField(result, NewString("foo"));
6081 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6082 EXPECT_EQ(11, int_value);
6083
6084 // Allocate object and invoke a named constructor.
6085 obj = Dart_Allocate(type);
6086 EXPECT_VALID(obj);
6087 instanceOf = false;
6088 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
6089 EXPECT(instanceOf);
6090 result = Dart_InvokeConstructor(obj, NewString("named"), 1, args);
6092 int_value = 0;
6093 foo = Dart_GetField(result, NewString("foo"));
6094 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6095 EXPECT_EQ(11, int_value);
6096
6097 // Invoke a hidden named constructor.
6098 result = Dart_New(type, NewString("_hidden"), 1, args);
6100 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6101 EXPECT(instanceOf);
6102 int_value = 0;
6103 foo = Dart_GetField(result, NewString("foo"));
6104 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6105 EXPECT_EQ(-11, int_value);
6106
6107 // Invoke a hidden named constructor on a hidden type.
6108 result = Dart_New(private_type, NewString("_"), 0, nullptr);
6110 int_value = 0;
6111 foo = Dart_GetField(result, NewString("foo"));
6112 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6113 EXPECT_EQ(7, int_value);
6114
6115 // Allocate object and invoke a hidden named constructor.
6116 obj = Dart_Allocate(type);
6117 EXPECT_VALID(obj);
6118 instanceOf = false;
6119 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
6120 EXPECT(instanceOf);
6121 result = Dart_InvokeConstructor(obj, NewString("_hidden"), 1, args);
6123 int_value = 0;
6124 foo = Dart_GetField(result, NewString("foo"));
6125 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6126 EXPECT_EQ(-11, int_value);
6127
6128 // Allocate object and Invoke a constructor which throws an exception.
6129 obj = Dart_Allocate(type);
6130 EXPECT_VALID(obj);
6131 instanceOf = false;
6132 EXPECT_VALID(Dart_ObjectIsType(obj, type, &instanceOf));
6133 EXPECT(instanceOf);
6134 result = Dart_InvokeConstructor(obj, NewString("exception"), 1, args);
6135 EXPECT_ERROR(result, "ConstructorDeath");
6136
6137 // Invoke a factory constructor.
6138 result = Dart_New(type, NewString("multiply"), 1, args);
6140 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6141 EXPECT(instanceOf);
6142 int_value = 0;
6143 foo = Dart_GetField(result, NewString("foo"));
6144 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6145 EXPECT_EQ(1100, int_value);
6146
6147 // Pass an error class object. Error is passed through.
6148 result = Dart_New(Dart_NewApiError("myerror"), NewString("named"), 1, args);
6149 EXPECT_ERROR(result, "myerror");
6150
6151 // Pass a bad class object.
6152 result = Dart_New(Dart_Null(), NewString("named"), 1, args);
6153 EXPECT_ERROR(result, "Dart_New expects argument 'type' to be non-null.");
6154
6155 // Pass a negative arg count.
6156 result = Dart_New(type, NewString("named"), -1, args);
6158 result,
6159 "Dart_New expects argument 'number_of_arguments' to be non-negative.");
6160
6161 // Pass the wrong arg count.
6162 result = Dart_New(type, NewString("named"), 0, nullptr);
6164 result,
6165 "Dart_New: wrong argument count for constructor 'MyClass.named': "
6166 "0 passed, 1 expected.");
6167
6168 // Pass a bad argument. Error is passed through.
6169 result = Dart_New(type, NewString("named"), 1, bad_args);
6170 EXPECT_ERROR(result, "myerror");
6171
6172 // Pass a bad constructor name.
6175 result,
6176 "Dart_New expects argument 'constructor_name' to be of type String.");
6177
6178 // Invoke a missing constructor.
6179 result = Dart_New(type, NewString("missing"), 1, args);
6181 "Dart_New: could not find constructor 'MyClass.missing'.");
6182
6183 // Invoke a constructor which throws an exception.
6184 result = Dart_New(type, NewString("exception"), 1, args);
6185 EXPECT_ERROR(result, "ConstructorDeath");
6186
6187 // Invoke a constructor that is missing in the interface.
6188 result = Dart_New(intf, Dart_Null(), 0, nullptr);
6189 EXPECT_ERROR(result, "Dart_New: could not find constructor 'MyInterface.'.");
6190
6191 // Invoke abstract constructor that is present in the interface.
6192 result = Dart_New(intf, NewString("notfound"), 1, args);
6194 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6195 EXPECT(!instanceOf);
6196}
6197
6198// These two cases below currently fail because of issue
6199// https://github.com/dart-lang/sdk/issues/42939
6200TEST_CASE(DartAPI_New_Issue42939) {
6201 const char* kScriptChars =
6202 "class MyClass implements MyExtraHop {\n"
6203 " MyClass() : foo = 7 {}\n"
6204 " MyClass.named(value) : foo = value {}\n"
6205 " MyClass._hidden(value) : foo = -value {}\n"
6206 " MyClass.exception(value) : foo = value {\n"
6207 " throw 'ConstructorDeath';\n"
6208 " }\n"
6209 " factory MyClass.multiply(value) {\n"
6210 " return new MyClass.named(value * 100);\n"
6211 " }\n"
6212 " var foo;\n"
6213 "}\n"
6214 "\n"
6215 "abstract class MyExtraHop implements MyInterface {\n"
6216 " factory MyExtraHop.hop(value) = MyClass.named;\n"
6217 "}\n"
6218 "\n"
6219 "abstract class MyInterface {\n"
6220 " factory MyInterface.named(value) = MyExtraHop.hop;\n"
6221 " factory MyInterface.multiply(value) = MyClass.multiply;\n"
6222 " MyInterface.notfound(value);\n"
6223 "}\n"
6224 "\n";
6225
6226 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6228 Dart_GetNonNullableType(lib, NewString("MyClass"), 0, nullptr);
6230 Dart_Handle intf =
6231 Dart_GetNonNullableType(lib, NewString("MyInterface"), 0, nullptr);
6232 EXPECT_VALID(intf);
6233
6234 Dart_Handle args[1];
6235 args[0] = Dart_NewInteger(11);
6236
6237 // Invoke two-hop redirecting factory constructor.
6238 bool instanceOf = false;
6239 Dart_Handle result = Dart_New(intf, NewString("named"), 1, args);
6241 if (!Dart_IsError(result)) {
6242 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6243 EXPECT(instanceOf);
6244 int64_t int_value = 0;
6246 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6247 EXPECT_EQ(11, int_value);
6248 }
6249
6250 // Invoke one-hop redirecting factory constructor.
6251 result = Dart_New(intf, NewString("multiply"), 1, args);
6253 if (!Dart_IsError(result)) {
6254 EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceOf));
6255 EXPECT(instanceOf);
6256 int64_t int_value = 0;
6258 EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
6259 EXPECT_EQ(1100, int_value);
6260 }
6261}
6262
6263TEST_CASE(DartAPI_New_Issue44205) {
6264 const char* kScriptChars =
6265 "class MyIntClass {\n"
6266 " MyIntClass(this.value);\n"
6267 " int value;\n"
6268 "}\n"
6269 "\n"
6270 "class MyClass<T> {\n"
6271 " T value;\n"
6272 " MyClass(this.value);\n"
6273 " factory MyClass.foo(T x) => MyClass<T>(x);\n"
6274 "}\n"
6275 "\n"
6276 "Type getIntType() { return int; }\n"
6277 "\n";
6278
6279 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6280 EXPECT_VALID(lib);
6281 Dart_Handle int_wrapper_type =
6282 Dart_GetNonNullableType(lib, NewString("MyIntClass"), 0, nullptr);
6283 EXPECT_VALID(int_wrapper_type);
6284
6285 Dart_Handle args[1];
6286 args[0] = Dart_EmptyString();
6287
6288 Dart_Handle result = Dart_New(int_wrapper_type, Dart_EmptyString(), 1, args);
6289 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'value'");
6290
6291 Dart_Handle int_type = Dart_Invoke(lib, NewString("getIntType"), 0, args);
6292 EXPECT_VALID(int_type);
6293 Dart_Handle type_args = Dart_NewList(1);
6294 EXPECT_VALID(type_args);
6295 EXPECT_VALID(Dart_ListSetAt(type_args, 0, int_type));
6296 Dart_Handle my_class_type =
6297 Dart_GetNonNullableType(lib, NewString("MyClass"), 1, &type_args);
6298 EXPECT_VALID(my_class_type);
6299
6300 // Generic generative constructor
6301 args[0] = Dart_EmptyString();
6302 result = Dart_New(my_class_type, Dart_EmptyString(), 1, args);
6303 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'value'");
6304
6305 // Generic factory constructor
6306 result = Dart_New(my_class_type, NewString("foo"), 1, args);
6307 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'x'");
6308}
6309
6310TEST_CASE(DartAPI_InvokeConstructor_Issue44205) {
6311 const char* kScriptChars =
6312 "class MyIntClass {\n"
6313 " MyIntClass(this.value);\n"
6314 " int value;\n"
6315 "}\n"
6316 "\n"
6317 "class MyClass<T> {\n"
6318 " T value;\n"
6319 " MyClass(this.value);\n"
6320 "}\n"
6321 "\n"
6322 "Type getIntType() { return int; }\n"
6323 "\n";
6324
6325 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6326 EXPECT_VALID(lib);
6327 Dart_Handle int_wrapper_type =
6328 Dart_GetNonNullableType(lib, NewString("MyIntClass"), 0, nullptr);
6329 EXPECT_VALID(int_wrapper_type);
6330
6331 Dart_Handle args[1];
6332 args[0] = Dart_EmptyString();
6333 Dart_Handle result = Dart_Allocate(int_wrapper_type);
6335
6337 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'value'");
6338
6339 Dart_Handle int_type = Dart_Invoke(lib, NewString("getIntType"), 0, args);
6340 EXPECT_VALID(int_type);
6341 Dart_Handle type_args = Dart_NewList(1);
6342 EXPECT_VALID(type_args);
6343 EXPECT_VALID(Dart_ListSetAt(type_args, 0, int_type));
6344 Dart_Handle my_class_type =
6345 Dart_GetNonNullableType(lib, NewString("MyClass"), 1, &type_args);
6346 EXPECT_VALID(my_class_type);
6347
6348 result = Dart_Allocate(my_class_type);
6351 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'value'");
6352}
6353
6354TEST_CASE(DartAPI_InvokeClosure_Issue44205) {
6355 const char* kScriptChars =
6356 "class InvokeClosure {\n"
6357 " InvokeClosure(int i, int j) : fld1 = i, fld2 = j {}\n"
6358 " Function method1(int i) {\n"
6359 " f(int j) => j + i + fld1 + fld2 + fld4; \n"
6360 " return f;\n"
6361 " }\n"
6362 " int fld1;\n"
6363 " final int fld2;\n"
6364 " static const int fld4 = 10;\n"
6365 "}\n"
6366 "Function testMain1() {\n"
6367 " InvokeClosure obj = new InvokeClosure(10, 20);\n"
6368 " return obj.method1(10);\n"
6369 "}\n";
6371 CHECK_API_SCOPE(thread);
6372
6373 // Create a test library and Load up a test script in it.
6374 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6375 EXPECT_VALID(lib);
6376
6377 // Invoke a function which returns a closure.
6378 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain1"), 0, nullptr);
6379 EXPECT_VALID(retobj);
6380
6381 // Now invoke the closure and check the result.
6382 Dart_Handle dart_arguments[1];
6383 dart_arguments[0] = Dart_EmptyString();
6384 result = Dart_InvokeClosure(retobj, 1, dart_arguments);
6385 EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'j'");
6386}
6387
6388TEST_CASE(DartAPI_NewListOf) {
6389 const char* kScriptChars =
6390 "String expectListOfString(List<String> o) => '${o.first}';\n"
6391 "String expectListOfDynamic(List<dynamic> o) => '${o.first}';\n"
6392 "String expectListOfInt(List<int> o) => '${o.first}';\n";
6393 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6394
6395 const int kNumArgs = 1;
6396 Dart_Handle args[kNumArgs];
6397 const char* str;
6400 if (!Dart_IsError(string_list)) {
6401 args[0] = string_list;
6403 Dart_Invoke(lib, NewString("expectListOfString"), kNumArgs, args);
6407 EXPECT_STREQ("null", str);
6408 } else {
6409 EXPECT_ERROR(string_list,
6410 "Cannot use legacy types with --sound-null-safety enabled. "
6411 "Use Dart_NewListOfType or Dart_NewListOfTypeFilled instead.");
6412 }
6413
6415 EXPECT_VALID(dynamic_list);
6416 args[0] = dynamic_list;
6417 result = Dart_Invoke(lib, NewString("expectListOfDynamic"), kNumArgs, args);
6420 EXPECT_STREQ("null", str);
6421
6423 if (!Dart_IsError(int_list)) {
6424 args[0] = int_list;
6425 result = Dart_Invoke(lib, NewString("expectListOfInt"), kNumArgs, args);
6428 EXPECT_STREQ("null", str);
6429 } else {
6430 EXPECT_ERROR(int_list,
6431 "Cannot use legacy types with --sound-null-safety enabled. "
6432 "Use Dart_NewListOfType or Dart_NewListOfTypeFilled instead.");
6433 }
6434}
6435
6436TEST_CASE(DartAPI_NewListOfType) {
6437 const char* kScriptChars =
6438 "class ZXHandle {}\n"
6439 "class ChannelReadResult {\n"
6440 " final List<ZXHandle?> handles;\n"
6441 " ChannelReadResult(this.handles);\n"
6442 "}\n"
6443 "void expectListOfString(List<String> _) {}\n"
6444 "void expectListOfDynamic(List<dynamic> _) {}\n"
6445 "void expectListOfVoid(List<void> _) {}\n"
6446 "void expectListOfNever(List<Never> _) {}\n";
6447 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6448
6449 Dart_Handle zxhandle_type =
6450 Dart_GetNullableType(lib, NewString("ZXHandle"), 0, nullptr);
6451 EXPECT_VALID(zxhandle_type);
6452
6453 Dart_Handle zxhandle = Dart_New(zxhandle_type, Dart_Null(), 0, nullptr);
6454 EXPECT_VALID(zxhandle);
6455
6456 Dart_Handle zxhandle_list = Dart_NewListOfType(zxhandle_type, 1);
6457 EXPECT_VALID(zxhandle_list);
6458
6459 EXPECT_VALID(Dart_ListSetAt(zxhandle_list, 0, zxhandle));
6460
6461 Dart_Handle readresult_type =
6462 Dart_GetNonNullableType(lib, NewString("ChannelReadResult"), 0, nullptr);
6463 EXPECT_VALID(zxhandle_type);
6464
6465 const int kNumArgs = 1;
6466 Dart_Handle args[kNumArgs];
6467 args[0] = zxhandle_list;
6468 EXPECT_VALID(Dart_New(readresult_type, Dart_Null(), kNumArgs, args));
6469
6472 "Dart_NewListOfType expects argument 'element_type' to be non-null.");
6475 "Dart_NewListOfType expects argument 'element_type' to be of type Type.");
6476
6477 Dart_Handle dart_core = Dart_LookupLibrary(NewString("dart:core"));
6478 EXPECT_VALID(dart_core);
6479
6480 Dart_Handle string_type =
6481 Dart_GetNonNullableType(dart_core, NewString("String"), 0, nullptr);
6482 EXPECT_VALID(string_type);
6483 Dart_Handle string_list = Dart_NewListOfType(string_type, 0);
6484 EXPECT_VALID(string_list);
6485 args[0] = string_list;
6487 Dart_Invoke(lib, NewString("expectListOfString"), kNumArgs, args));
6488
6489 Dart_Handle dynamic_type = Dart_TypeDynamic();
6490 EXPECT_VALID(dynamic_type);
6491 Dart_Handle dynamic_list = Dart_NewListOfType(dynamic_type, 0);
6492 EXPECT_VALID(dynamic_list);
6493 args[0] = dynamic_list;
6495 Dart_Invoke(lib, NewString("expectListOfDynamic"), kNumArgs, args));
6496
6497 Dart_Handle void_type = Dart_TypeVoid();
6498 EXPECT_VALID(void_type);
6499 Dart_Handle void_list = Dart_NewListOfType(void_type, 0);
6500 EXPECT_VALID(void_list);
6501 args[0] = void_list;
6502 EXPECT_VALID(Dart_Invoke(lib, NewString("expectListOfVoid"), kNumArgs, args));
6503
6504 Dart_Handle never_type = Dart_TypeNever();
6505 EXPECT_VALID(never_type);
6506 Dart_Handle never_list = Dart_NewListOfType(never_type, 0);
6507 EXPECT_VALID(never_list);
6508 args[0] = never_list;
6510 Dart_Invoke(lib, NewString("expectListOfNever"), kNumArgs, args));
6511}
6512
6513TEST_CASE(DartAPI_NewListOfTypeFilled) {
6514 const char* kScriptChars =
6515 "class ZXHandle {}\n"
6516 "class ChannelReadResult {\n"
6517 " final List<ZXHandle> handles;\n"
6518 " ChannelReadResult(this.handles);\n"
6519 "}\n";
6520 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6521
6522 Dart_Handle zxhandle_type =
6523 Dart_GetNonNullableType(lib, NewString("ZXHandle"), 0, nullptr);
6524 EXPECT_VALID(zxhandle_type);
6525
6526 Dart_Handle nullable_zxhandle_type =
6527 Dart_GetNullableType(lib, NewString("ZXHandle"), 0, nullptr);
6528 EXPECT_VALID(nullable_zxhandle_type);
6529
6530 Dart_Handle integer = Dart_NewInteger(42);
6531 EXPECT_VALID(integer);
6532
6533 Dart_Handle zxhandle = Dart_New(zxhandle_type, Dart_Null(), 0, nullptr);
6534 EXPECT_VALID(zxhandle);
6535
6536 Dart_Handle zxhandle_list =
6537 Dart_NewListOfTypeFilled(zxhandle_type, zxhandle, 1);
6538 EXPECT_VALID(zxhandle_list);
6539
6540 Dart_Handle result = Dart_ListGetAt(zxhandle_list, 0);
6542
6543 EXPECT(Dart_IdentityEquals(result, zxhandle));
6544
6545 Dart_Handle readresult_type =
6546 Dart_GetNonNullableType(lib, NewString("ChannelReadResult"), 0, nullptr);
6547 EXPECT_VALID(zxhandle_type);
6548
6549 const int kNumArgs = 1;
6550 Dart_Handle args[kNumArgs];
6551 args[0] = zxhandle_list;
6552 EXPECT_VALID(Dart_New(readresult_type, Dart_Null(), kNumArgs, args));
6553
6555 "Dart_NewListOfTypeFilled expects argument 'element_type' to be "
6556 "non-null.");
6558 "Dart_NewListOfTypeFilled expects argument 'element_type' to be "
6559 "of type Type.");
6561 Dart_NewListOfTypeFilled(zxhandle_type, Dart_Null(), 1),
6562 "Dart_NewListOfTypeFilled expects argument 'fill_object' to be non-null"
6563 " for a non-nullable 'element_type'");
6565 Dart_NewListOfTypeFilled(zxhandle_type, integer, 1),
6566 "Dart_NewListOfTypeFilled expects argument 'fill_object' to have the same"
6567 " type as 'element_type'.");
6568
6570 Dart_NewListOfTypeFilled(nullable_zxhandle_type, Dart_Null(), 1));
6571
6572 // Null is always valid as the fill argument if we're creating an empty list.
6573 EXPECT_VALID(Dart_NewListOfTypeFilled(zxhandle_type, Dart_Null(), 0));
6574
6575 // Test creation of a non nullable list of strings.
6576 Dart_Handle corelib = Dart_LookupLibrary(NewString("dart:core"));
6577 EXPECT_VALID(corelib);
6578 Dart_Handle string_type =
6579 Dart_GetNonNullableType(corelib, NewString("String"), 0, nullptr);
6581}
6582
6583static Dart_Handle PrivateLibName(Dart_Handle lib, const char* str) {
6584 EXPECT(Dart_IsLibrary(lib));
6585 Thread* thread = Thread::Current();
6586 TransitionNativeToVM transition(thread);
6587 const Library& library_obj = Api::UnwrapLibraryHandle(thread->zone(), lib);
6588 const String& name = String::Handle(String::New(str));
6589 return Api::NewHandle(thread, library_obj.PrivateName(name));
6590}
6591
6592TEST_CASE(DartAPI_Invoke) {
6593 const char* kScriptChars =
6594 "class BaseMethods {\n"
6595 " inheritedMethod(arg) => 'inherited $arg';\n"
6596 " static nonInheritedMethod(arg) => 'noninherited $arg';\n"
6597 "}\n"
6598 "\n"
6599 "class Methods extends BaseMethods {\n"
6600 " instanceMethod(arg) => 'instance $arg';\n"
6601 " _instanceMethod(arg) => 'hidden instance $arg';\n"
6602 " static staticMethod(arg) => 'static $arg';\n"
6603 " static _staticMethod(arg) => 'hidden static $arg';\n"
6604 "}\n"
6605 "\n"
6606 "topMethod(arg) => 'top $arg';\n"
6607 "_topMethod(arg) => 'hidden top $arg';\n"
6608 "\n"
6609 "Methods test() {\n"
6610 " return new Methods();\n"
6611 "}\n";
6612
6613 // Shared setup.
6614 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6616 Dart_GetNonNullableType(lib, NewString("Methods"), 0, nullptr);
6618 Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, nullptr);
6620 Dart_Handle args[1];
6621 args[0] = NewString("!!!");
6622 Dart_Handle bad_args[2];
6623 bad_args[0] = NewString("bad1");
6624 bad_args[1] = NewString("bad2");
6627 const char* str;
6628
6629 // Instance method.
6630 name = NewString("instanceMethod");
6636 EXPECT_STREQ("instance !!!", str);
6637
6638 // Instance method, wrong arg count.
6639 EXPECT_ERROR(Dart_Invoke(instance, name, 2, bad_args),
6640 "Class 'Methods' has no instance method 'instanceMethod'"
6641 " with matching arguments");
6642
6643 name = PrivateLibName(lib, "_instanceMethod");
6649 EXPECT_STREQ("hidden instance !!!", str);
6650
6651 // Inherited method.
6652 name = NewString("inheritedMethod");
6658 EXPECT_STREQ("inherited !!!", str);
6659
6660 // Static method.
6661 name = NewString("staticMethod");
6667 EXPECT_STREQ("static !!!", str);
6668
6669 // Static method, wrong arg count.
6670 EXPECT_ERROR(Dart_Invoke(type, name, 2, bad_args),
6671 "NoSuchMethodError: No static method 'staticMethod' with "
6672 "matching arguments");
6673
6674 // Hidden static method.
6675 name = NewString("_staticMethod");
6681 EXPECT_STREQ("hidden static !!!", str);
6682
6683 // Static non-inherited method. Not found at any level.
6684 name = NewString("non_inheritedMethod");
6688
6689 // Top-Level method.
6690 name = NewString("topMethod");
6693 result = Dart_Invoke(lib, name, 1, args);
6696 EXPECT_STREQ("top !!!", str);
6697
6698 // Top-level method, wrong arg count.
6699 EXPECT_ERROR(Dart_Invoke(lib, name, 2, bad_args),
6700 "NoSuchMethodError: No top-level method 'topMethod' with "
6701 "matching arguments");
6702
6703 // Hidden top-level method.
6704 name = NewString("_topMethod");
6707 result = Dart_Invoke(lib, name, 1, args);
6710 EXPECT_STREQ("hidden top !!!", str);
6711}
6712
6713TEST_CASE(DartAPI_Invoke_PrivateStatic) {
6714 const char* kScriptChars =
6715 "class Methods {\n"
6716 " static _staticMethod(arg) => 'hidden static $arg';\n"
6717 "}\n"
6718 "\n";
6719
6720 // Shared setup.
6721 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6723 Dart_GetNonNullableType(lib, NewString("Methods"), 0, nullptr);
6726 Dart_Handle name = NewString("_staticMethod");
6728
6729 Dart_Handle args[1];
6730 args[0] = NewString("!!!");
6733
6734 const char* str = nullptr;
6736 EXPECT_STREQ("hidden static !!!", str);
6737}
6738
6739TEST_CASE(DartAPI_Invoke_FunnyArgs) {
6740 const char* kScriptChars = "test(arg) => 'hello $arg';\n";
6741
6742 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6743 Dart_Handle func_name = NewString("test");
6744 Dart_Handle args[1];
6745 const char* str;
6746
6747 // Make sure that valid args yield valid results.
6748 args[0] = NewString("!!!");
6749 Dart_Handle result = Dart_Invoke(lib, func_name, 1, args);
6752 EXPECT_STREQ("hello !!!", str);
6753
6754 // Make sure that null is legal.
6755 args[0] = Dart_Null();
6756 result = Dart_Invoke(lib, func_name, 1, args);
6759 EXPECT_STREQ("hello null", str);
6760
6761 // Pass an error handle as the target. The error is propagated.
6762 result = Dart_Invoke(Api::NewError("myerror"), func_name, 1, args);
6764 EXPECT_STREQ("myerror", Dart_GetError(result));
6765
6766 // Pass an error handle as the function name. The error is propagated.
6767 result = Dart_Invoke(lib, Api::NewError("myerror"), 1, args);
6769 EXPECT_STREQ("myerror", Dart_GetError(result));
6770
6771 // Pass a non-instance handle as a parameter..
6772 args[0] = lib;
6773 result = Dart_Invoke(lib, func_name, 1, args);
6775 EXPECT_STREQ("Dart_Invoke expects arguments[0] to be an Instance handle.",
6777
6778 // Pass an error handle as a parameter. The error is propagated.
6779 args[0] = Api::NewError("myerror");
6780 result = Dart_Invoke(lib, func_name, 1, args);
6782 EXPECT_STREQ("myerror", Dart_GetError(result));
6783}
6784
6785TEST_CASE(DartAPI_Invoke_BadArgs) {
6786 const char* kScriptChars =
6787 "class BaseMethods {\n"
6788 " inheritedMethod(int arg) => 'inherited $arg';\n"
6789 " static nonInheritedMethod(int arg) => 'noninherited $arg';\n"
6790 "}\n"
6791 "\n"
6792 "class Methods extends BaseMethods {\n"
6793 " instanceMethod(int arg) => 'instance $arg';\n"
6794 " _instanceMethod(int arg) => 'hidden instance $arg';\n"
6795 " static staticMethod(int arg) => 'static $arg';\n"
6796 " static _staticMethod(int arg) => 'hidden static $arg';\n"
6797 "}\n"
6798 "\n"
6799 "topMethod(int arg) => 'top $arg';\n"
6800 "_topMethod(int arg) => 'hidden top $arg';\n"
6801 "\n"
6802 "Methods test() {\n"
6803 " return new Methods();\n"
6804 "}\n";
6805
6806#if defined(PRODUCT)
6807 const char* error_msg =
6808 "type '_OneByteString' is not a subtype of type 'int' of 'arg'";
6809#else
6810 const char* error_msg =
6811 "type 'String' is not a subtype of type 'int' of 'arg'";
6812#endif // defined(PRODUCT)
6813
6814 // Shared setup.
6815 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6817 Dart_GetNonNullableType(lib, NewString("Methods"), 0, nullptr);
6819 Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, nullptr);
6821 Dart_Handle args[1];
6822 args[0] = NewString("!!!");
6825
6826 // Instance method.
6827 name = NewString("instanceMethod");
6830 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6831
6832 name = PrivateLibName(lib, "_instanceMethod");
6835 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6836
6837 // Inherited method.
6838 name = NewString("inheritedMethod");
6841 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6842
6843 // Static method.
6844 name = NewString("staticMethod");
6847 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6848
6849 // Hidden static method.
6850 name = NewString("_staticMethod");
6853 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6854
6855 // Top-Level method.
6856 name = NewString("topMethod");
6857 result = Dart_Invoke(lib, name, 1, args);
6859 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6860
6861 // Hidden top-level method.
6862 name = NewString("_topMethod");
6863 result = Dart_Invoke(lib, name, 1, args);
6865 EXPECT_SUBSTRING(error_msg, Dart_GetError(result));
6866}
6867
6868TEST_CASE(DartAPI_Invoke_Null) {
6870 Dart_Invoke(Dart_Null(), NewString("toString"), 0, nullptr);
6873
6874 const char* value = "";
6876 EXPECT_STREQ("null", value);
6877
6879 result = Dart_Invoke(Dart_Null(), function_name, 0, nullptr);
6882
6883 result = Dart_GetField(Dart_Null(), NewString("toString"));
6886
6887 result =
6888 Dart_SetField(Dart_Null(), NewString("nullHasNoSetters"), Dart_Null());
6889 // Not that Dart_SetField expects a non-null receiver.
6891 result,
6892 "NoSuchMethodError: The setter 'nullHasNoSetters=' was called on null");
6893}
6894
6895TEST_CASE(DartAPI_InvokeNoSuchMethod) {
6896 const char* kScriptChars =
6897 "class Expect {\n"
6898 " static equals(a, b) {\n"
6899 " if (a != b) {\n"
6900 " throw 'not equal. expected: $a, got: $b';\n"
6901 " }\n"
6902 " }\n"
6903 "}\n"
6904 "class TestClass {\n"
6905 " static int fld1 = 0;\n"
6906 " void noSuchMethod(Invocation invocation) {\n"
6907 // This relies on the Symbol.toString() method returning a String of the
6908 // form 'Symbol("name")'. This is to avoid having to import
6909 // dart:_internal just to get access to the name of the symbol.
6910 " var name = invocation.memberName.toString();\n"
6911 " name = name.split('\"')[1];\n"
6912 " if (name == 'fld') {\n"
6913 " Expect.equals(true, invocation.isGetter);\n"
6914 " Expect.equals(false, invocation.isMethod);\n"
6915 " Expect.equals(false, invocation.isSetter);\n"
6916 " } else if (name == 'setfld') {\n"
6917 " Expect.equals(true, invocation.isSetter);\n"
6918 " Expect.equals(false, invocation.isMethod);\n"
6919 " Expect.equals(false, invocation.isGetter);\n"
6920 " } else if (name == 'method') {\n"
6921 " Expect.equals(true, invocation.isMethod);\n"
6922 " Expect.equals(false, invocation.isSetter);\n"
6923 " Expect.equals(false, invocation.isGetter);\n"
6924 " }\n"
6925 " TestClass.fld1 += 1;\n"
6926 " }\n"
6927 " static TestClass testMain() {\n"
6928 " return new TestClass();\n"
6929 " }\n"
6930 "}\n";
6933 // Create a test library and Load up a test script in it.
6934 // The test library must have a dart: url so it can import dart:_internal.
6935 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6937 Dart_GetNonNullableType(lib, NewString("TestClass"), 0, nullptr);
6939
6940 // Invoke a function which returns an object.
6941 instance = Dart_Invoke(type, NewString("testMain"), 0, nullptr);
6943
6944 // Try to get a field that does not exist, should call noSuchMethod.
6947
6948 // Try to set a field that does not exist, should call noSuchMethod.
6951
6952 // Try to invoke a method that does not exist, should call noSuchMethod.
6953 result = Dart_Invoke(instance, NewString("method"), 0, nullptr);
6955
6956 result = Dart_GetField(type, NewString("fld1"));
6958 int64_t value = 0;
6960 EXPECT_EQ(3, value);
6961}
6962
6963TEST_CASE(DartAPI_InvokeClosure) {
6964 const char* kScriptChars =
6965 "class InvokeClosure {\n"
6966 " InvokeClosure(int i, int j) : fld1 = i, fld2 = j {}\n"
6967 " Function method1(int i) {\n"
6968 " f(int j) => j + i + fld1 + fld2 + fld4; \n"
6969 " return f;\n"
6970 " }\n"
6971 " static Function method2(int i) {\n"
6972 " n(int j) { throw new Exception('I am an exception'); return 1; }\n"
6973 " return n;\n"
6974 " }\n"
6975 " int fld1;\n"
6976 " final int fld2;\n"
6977 " static const int fld4 = 10;\n"
6978 "}\n"
6979 "Function testMain1() {\n"
6980 " InvokeClosure obj = new InvokeClosure(10, 20);\n"
6981 " return obj.method1(10);\n"
6982 "}\n"
6983 "Function testMain2() {\n"
6984 " return InvokeClosure.method2(10);\n"
6985 "}\n";
6987 CHECK_API_SCOPE(thread);
6988
6989 // Create a test library and Load up a test script in it.
6990 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
6991
6992 // Invoke a function which returns a closure.
6993 Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain1"), 0, nullptr);
6994 EXPECT_VALID(retobj);
6995
6996 EXPECT(Dart_IsClosure(retobj));
6998
6999 // Now invoke the closure and check the result.
7000 Dart_Handle dart_arguments[1];
7001 dart_arguments[0] = Dart_NewInteger(1);
7002 result = Dart_InvokeClosure(retobj, 1, dart_arguments);
7005 int64_t value = 0;
7007 EXPECT_EQ(51, value);
7008
7009 // Invoke closure with wrong number of args, should result in exception.
7010 result = Dart_InvokeClosure(retobj, 0, nullptr);
7013
7014 // Invoke a function which returns a closure.
7015 retobj = Dart_Invoke(lib, NewString("testMain2"), 0, nullptr);
7016 EXPECT_VALID(retobj);
7017
7018 EXPECT(Dart_IsClosure(retobj));
7019 EXPECT(!Dart_IsClosure(NewString("abcdef")));
7020
7021 // Now invoke the closure and check the result (should be an exception).
7022 dart_arguments[0] = Dart_NewInteger(1);
7023 result = Dart_InvokeClosure(retobj, 1, dart_arguments);
7026}
7027
7030 Dart_ThrowException(NewString("Hello from ExceptionNative!"));
7031 UNREACHABLE();
7032}
7033
7035 int argument_count,
7036 bool* auto_setup_scope) {
7037 ASSERT(auto_setup_scope != nullptr);
7038 *auto_setup_scope = true;
7039 return ExceptionNative;
7040}
7041
7042TEST_CASE(DartAPI_ThrowException) {
7043 const char* kScriptChars =
7044 R"(
7045 @pragma('vm:external-name', 'ThrowException_native')
7046 external int test();
7047 )";
7048
7050 intptr_t size = thread->ZoneSizeInBytes();
7051 Dart_EnterScope(); // Start a Dart API scope for invoking API functions.
7052
7053 // Load up a test script which extends the native wrapper class.
7055
7056 // Throwing an exception here should result in an error.
7057 result = Dart_ThrowException(NewString("This doesn't work"));
7058 EXPECT_ERROR(result, "No Dart frames on stack, cannot throw exception");
7060
7061 // Invoke 'test' and check for an uncaught exception.
7062 result = Dart_Invoke(lib, NewString("test"), 0, nullptr);
7063 EXPECT_ERROR(result, "Hello from ExceptionNative!");
7065
7066 Dart_ExitScope(); // Exit the Dart API scope.
7067 EXPECT_EQ(size, thread->ZoneSizeInBytes());
7070static intptr_t kNativeArgumentNativeField1Value = 30;
7071static intptr_t kNativeArgumentNativeField2Value = 40;
7075 Dart_GetNonNullableType(lib, NewString("MyObject"), 0, nullptr);
7077
7078 // Allocate without a constructor.
7079 const int num_native_fields = 2;
7080 const intptr_t native_fields[] = {kNativeArgumentNativeField1Value,
7082 // Allocate and Setup native fields.
7083 Dart_Handle obj =
7084 Dart_AllocateWithNativeFields(type, num_native_fields, native_fields);
7085 EXPECT_VALID(obj);
7086
7090}
7091
7093 const int kNumNativeFields = 2;
7094
7095 // Test different argument types with a valid descriptor set.
7096 {
7097 const char* cstr = nullptr;
7098 intptr_t native_fields1[kNumNativeFields];
7099 intptr_t native_fields2[kNumNativeFields];
7100 const Dart_NativeArgument_Descriptor arg_descriptors[9] = {
7110 };
7111 Dart_NativeArgument_Value arg_values[9];
7112 arg_values[0].as_native_fields.num_fields = kNumNativeFields;
7113 arg_values[0].as_native_fields.values = native_fields1;
7114 arg_values[7].as_native_fields.num_fields = kNumNativeFields;
7115 arg_values[7].as_native_fields.values = native_fields2;
7117 Dart_GetNativeArguments(args, 9, arg_descriptors, arg_values);
7119
7120 EXPECT(arg_values[0].as_native_fields.values[0] == 30);
7121 EXPECT(arg_values[0].as_native_fields.values[1] == 40);
7122
7123 EXPECT(arg_values[1].as_int32 == 77);
7124
7125 // When wrapped-around, this value should not fit into int32, because this
7126 // unit test verifies that getting it as int32 produces error.
7127 EXPECT(arg_values[2].as_uint64 == 0x8000000000000000LL);
7128
7129 EXPECT(arg_values[3].as_bool == true);
7130
7131 EXPECT(arg_values[4].as_double == 3.14);
7132
7133 EXPECT_VALID(arg_values[5].as_string.dart_str);
7134 EXPECT(Dart_IsString(arg_values[5].as_string.dart_str));
7135 EXPECT_VALID(Dart_StringToCString(arg_values[5].as_string.dart_str, &cstr));
7136 EXPECT_STREQ("abcdefg", cstr);
7137 EXPECT(arg_values[5].as_string.peer == nullptr);
7138
7139 EXPECT_VALID(arg_values[6].as_string.dart_str);
7140 EXPECT(Dart_IsString(arg_values[6].as_string.dart_str));
7141 EXPECT_VALID(Dart_StringToCString(arg_values[6].as_string.dart_str, &cstr));
7142 EXPECT_STREQ("string", cstr);
7143 EXPECT(arg_values[6].as_string.peer == nullptr);
7144
7145 EXPECT(arg_values[7].as_native_fields.values[0] == 60);
7146 EXPECT(arg_values[7].as_native_fields.values[1] == 80);
7147
7148 EXPECT_VALID(arg_values[8].as_instance);
7149 EXPECT(Dart_IsInstance(arg_values[8].as_instance));
7150 int field_count = 0;
7151 EXPECT_VALID(Dart_GetNativeInstanceFieldCount(arg_values[8].as_instance,
7152 &field_count));
7153 EXPECT(field_count == 2);
7154 }
7155
7156 // Test with an invalid descriptor set (invalid type).
7157 {
7158 const Dart_NativeArgument_Descriptor arg_descriptors[8] = {
7167 };
7168 Dart_NativeArgument_Value arg_values[8];
7170 Dart_GetNativeArguments(args, 8, arg_descriptors, arg_values);
7172 }
7173
7174 // Test with an invalid range error.
7175 {
7176 const Dart_NativeArgument_Descriptor arg_descriptors[8] = {
7185 };
7186 Dart_NativeArgument_Value arg_values[8];
7188 Dart_GetNativeArguments(args, 8, arg_descriptors, arg_values);
7190 }
7191
7193}
7194
7196 int argument_count,
7197 bool* auto_scope_setup) {
7198 TransitionNativeToVM transition(Thread::Current());
7199 const Object& obj = Object::Handle(Api::UnwrapHandle(name));
7200 if (!obj.IsString()) {
7201 return nullptr;
7202 }
7203 ASSERT(auto_scope_setup != nullptr);
7204 *auto_scope_setup = true;
7205 const char* function_name = obj.ToCString();
7206 ASSERT(function_name != nullptr);
7207 if (strcmp(function_name, "NativeArgument_Create") == 0) {
7208 return NativeArgumentCreate;
7209 } else if (strcmp(function_name, "NativeArgument_Access") == 0) {
7210 return NativeArgumentAccess;
7211 }
7212 return nullptr;
7213}
7214
7215TEST_CASE(DartAPI_GetNativeArguments) {
7216 const char* kScriptChars = R"(
7217import 'dart:nativewrappers';
7218base class MyObject extends NativeFieldWrapperClass2 {
7219 @pragma("vm:external-name", "NativeArgument_Create")
7220 external static MyObject createObject();
7221 @pragma("vm:external-name", "NativeArgument_Access")
7222 external int accessFields(int arg1,
7223 int arg2,
7224 bool arg3,
7225 double arg4,
7226 String arg5,
7227 String arg6,
7228 MyObject arg7);
7229}
7230int testMain(String extstr) {
7231 String str = 'abcdefg';
7232 MyObject obj1 = MyObject.createObject();
7233 MyObject obj2 = MyObject.createObject();
7234 return obj1.accessFields(77,
7235 0x8000000000000000,
7236 true,
7237 3.14,
7238 str,
7239 extstr,
7240 obj2);
7241})";
7242
7244
7245 const char* ascii_str = "string";
7246 intptr_t ascii_str_length = strlen(ascii_str);
7248 reinterpret_cast<const uint8_t*>(ascii_str), ascii_str_length);
7249
7250 Dart_Handle args[1];
7251 args[0] = str;
7252 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 1, args);
7262}
7263
7265 int argument_count,
7266 bool* auto_setup_scope) {
7267 ASSERT(auto_setup_scope != nullptr);
7268 *auto_setup_scope = true;
7270}
7271
7272TEST_CASE(DartAPI_GetNativeArgumentCount) {
7273 const char* kScriptChars = R"(
7274class MyObject {
7275 @pragma("vm:external-name", "Name_Does_Not_Matter")
7276 external int method1(int i, int j);
7277}
7278testMain() {
7279 MyObject obj = new MyObject();
7280 return obj.method1(77, 125);
7281})";
7282
7284
7285 Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
7288
7289 int64_t value = 0;
7292 EXPECT_EQ(3, value);
7293}
7294
7295TEST_CASE(DartAPI_TypeToNullability) {
7296 const char* kScriptChars =
7297 "library testlib;\n"
7298 "class Class {\n"
7299 " static var name = 'Class';\n"
7300 "}\n";
7301
7302 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7303
7304 const Dart_Handle name = NewString("Class");
7305 // Lookup the legacy type for Class.
7306 Dart_Handle type = Dart_GetType(lib, name, 0, nullptr);
7307 Dart_Handle nonNullableType;
7308 Dart_Handle nullableType;
7309 if (Dart_IsError(type)) {
7311 type,
7312 "Cannot use legacy types with --sound-null-safety enabled. "
7313 "Use Dart_GetNullableType or Dart_GetNonNullableType instead.");
7314
7315 nonNullableType = Dart_GetNonNullableType(lib, name, 0, nullptr);
7316 EXPECT_VALID(nonNullableType);
7317 nullableType = Dart_GetNullableType(lib, name, 0, nullptr);
7318 } else {
7320 bool result = false;
7322 EXPECT(result);
7323
7324 // Legacy -> Nullable
7325 nullableType = Dart_TypeToNullableType(type);
7326 EXPECT_VALID(nullableType);
7327 result = false;
7328 EXPECT_VALID(Dart_IsNullableType(nullableType, &result));
7329 EXPECT(result);
7330 EXPECT(Dart_IdentityEquals(nullableType,
7331 Dart_GetNullableType(lib, name, 0, nullptr)));
7332
7333 // Legacy -> Non-Nullable
7334 nonNullableType = Dart_TypeToNonNullableType(type);
7335 EXPECT_VALID(nonNullableType);
7336 result = false;
7337 EXPECT_VALID(Dart_IsNonNullableType(nonNullableType, &result));
7338 EXPECT(result);
7339 EXPECT(Dart_IdentityEquals(nonNullableType,
7340 Dart_GetNonNullableType(lib, name, 0, nullptr)));
7341 }
7342
7343 // Nullable -> Non-Nullable
7345 nonNullableType,
7347
7348 // Non-Nullable -> Nullable
7350 nullableType,
7352}
7353
7354TEST_CASE(DartAPI_GetNullableType) {
7355 const char* kScriptChars =
7356 "library testlib;\n"
7357 "class Class {\n"
7358 " static var name = 'Class';\n"
7359 "}\n"
7360 "\n"
7361 "class _Class {\n"
7362 " static var name = '_Class';\n"
7363 "}\n";
7364
7365 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7366
7367 // Lookup a class.
7368 Dart_Handle type = Dart_GetNullableType(lib, NewString("Class"), 0, nullptr);
7370 bool result = false;
7372 EXPECT(result);
7375 const char* name_cstr = "";
7377 EXPECT_STREQ("Class?", name_cstr);
7378
7379 name = Dart_GetField(type, NewString("name"));
7382 EXPECT_STREQ("Class", name_cstr);
7383
7384 // Lookup a private class.
7385 type = Dart_GetNullableType(lib, NewString("_Class"), 0, nullptr);
7387 result = false;
7389
7390 name = Dart_GetField(type, NewString("name"));
7392 name_cstr = "";
7394 EXPECT_STREQ("_Class", name_cstr);
7395
7396 // Lookup a class that does not exist.
7397 type = Dart_GetNullableType(lib, NewString("DoesNotExist"), 0, nullptr);
7399 EXPECT_STREQ("Type 'DoesNotExist' not found in library 'testlib'.",
7401
7402 // Lookup a class from an error library. The error propagates.
7403 type = Dart_GetNullableType(Api::NewError("myerror"), NewString("Class"), 0,
7404 nullptr);
7406 EXPECT_STREQ("myerror", Dart_GetError(type));
7407
7408 // Lookup a type using an error class name. The error propagates.
7409 type = Dart_GetNullableType(lib, Api::NewError("myerror"), 0, nullptr);
7411 EXPECT_STREQ("myerror", Dart_GetError(type));
7412}
7413
7414TEST_CASE(DartAPI_GetNonNullableType) {
7415 const char* kScriptChars =
7416 "library testlib;\n"
7417 "class Class {\n"
7418 " static var name = 'Class';\n"
7419 "}\n"
7420 "\n"
7421 "class _Class {\n"
7422 " static var name = '_Class';\n"
7423 "}\n";
7424
7425 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7426
7427 // Lookup a class.
7429 Dart_GetNonNullableType(lib, NewString("Class"), 0, nullptr);
7431 bool result = false;
7433 EXPECT(result);
7436 const char* name_cstr = "";
7438 EXPECT_STREQ("Class", name_cstr);
7439
7440 name = Dart_GetField(type, NewString("name"));
7443 EXPECT_STREQ("Class", name_cstr);
7444
7445 // Lookup a private class.
7446 type = Dart_GetNonNullableType(lib, NewString("_Class"), 0, nullptr);
7448 result = false;
7450 EXPECT(result);
7451
7452 name = Dart_GetField(type, NewString("name"));
7454 name_cstr = "";
7456 EXPECT_STREQ("_Class", name_cstr);
7457
7458 // Lookup a class that does not exist.
7459 type = Dart_GetNonNullableType(lib, NewString("DoesNotExist"), 0, nullptr);
7461 EXPECT_STREQ("Type 'DoesNotExist' not found in library 'testlib'.",
7463
7464 // Lookup a class from an error library. The error propagates.
7465 type = Dart_GetNonNullableType(Api::NewError("myerror"), NewString("Class"),
7466 0, nullptr);
7468 EXPECT_STREQ("myerror", Dart_GetError(type));
7469
7470 // Lookup a type using an error class name. The error propagates.
7471 type = Dart_GetNonNullableType(lib, Api::NewError("myerror"), 0, nullptr);
7473 EXPECT_STREQ("myerror", Dart_GetError(type));
7474}
7475
7476TEST_CASE(DartAPI_InstanceOf) {
7477 const char* kScriptChars =
7478 "class OtherClass {\n"
7479 " static returnNull() { return null; }\n"
7480 "}\n"
7481 "class InstanceOfTest {\n"
7482 " InstanceOfTest() {}\n"
7483 " static InstanceOfTest testMain() {\n"
7484 " return new InstanceOfTest();\n"
7485 " }\n"
7486 "}\n";
7488 // Create a test library and Load up a test script in it.
7489 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7490
7491 // Fetch InstanceOfTest class.
7493 Dart_GetNonNullableType(lib, NewString("InstanceOfTest"), 0, nullptr);
7495
7496 // Invoke a function which returns an object of type InstanceOf..
7497 Dart_Handle instanceOfTestObj =
7498 Dart_Invoke(type, NewString("testMain"), 0, nullptr);
7499 EXPECT_VALID(instanceOfTestObj);
7500
7501 // Now check instanceOfTestObj reported as an instance of
7502 // InstanceOfTest class.
7503 bool is_instance = false;
7504 result = Dart_ObjectIsType(instanceOfTestObj, type, &is_instance);
7506 EXPECT(is_instance);
7507
7508 // Fetch OtherClass and check if instanceOfTestObj is instance of it.
7509 Dart_Handle otherType =
7510 Dart_GetNonNullableType(lib, NewString("OtherClass"), 0, nullptr);
7511 EXPECT_VALID(otherType);
7512
7513 result = Dart_ObjectIsType(instanceOfTestObj, otherType, &is_instance);
7515 EXPECT(!is_instance);
7516
7517 // Check that primitives are not instances of InstanceOfTest class.
7518 result = Dart_ObjectIsType(NewString("a string"), otherType, &is_instance);
7520 EXPECT(!is_instance);
7521
7522 result = Dart_ObjectIsType(Dart_NewInteger(42), otherType, &is_instance);
7524 EXPECT(!is_instance);
7525
7526 result = Dart_ObjectIsType(Dart_NewBoolean(true), otherType, &is_instance);
7528 EXPECT(!is_instance);
7529
7530 // Check that null is not an instance of InstanceOfTest class.
7531 Dart_Handle null =
7532 Dart_Invoke(otherType, NewString("returnNull"), 0, nullptr);
7533 EXPECT_VALID(null);
7534
7535 result = Dart_ObjectIsType(null, otherType, &is_instance);
7537 EXPECT(!is_instance);
7538
7539 // Check that error is returned if null is passed as a class argument.
7540 result = Dart_ObjectIsType(null, null, &is_instance);
7542}
7543
7544TEST_CASE(DartAPI_RootLibrary) {
7545 const char* kScriptChars =
7546 "library testlib;"
7547 "main() {"
7548 " return 12345;"
7549 "}";
7550
7551 Dart_Handle root_lib = Dart_RootLibrary();
7552 EXPECT_VALID(root_lib);
7553 EXPECT(Dart_IsNull(root_lib));
7554
7555 // Load a script.
7556 EXPECT_VALID(LoadScript(TestCase::url(), kScriptChars));
7557
7558 root_lib = Dart_RootLibrary();
7559 Dart_Handle lib_uri = Dart_LibraryUrl(root_lib);
7560 EXPECT_VALID(lib_uri);
7561 EXPECT(!Dart_IsNull(lib_uri));
7562 const char* uri_cstr = "";
7563 EXPECT_VALID(Dart_StringToCString(lib_uri, &uri_cstr));
7564 EXPECT_STREQ(TestCase::url(), uri_cstr);
7565
7566 Dart_Handle core_uri = Dart_NewStringFromCString("dart:core");
7567 Dart_Handle core_lib = Dart_LookupLibrary(core_uri);
7568 EXPECT_VALID(core_lib);
7569 EXPECT(Dart_IsLibrary(core_lib));
7570
7571 Dart_Handle result = Dart_SetRootLibrary(core_uri); // Not a library.
7573 root_lib = Dart_RootLibrary();
7574 lib_uri = Dart_LibraryUrl(root_lib);
7575 EXPECT_VALID(Dart_StringToCString(lib_uri, &uri_cstr));
7576 EXPECT_STREQ(TestCase::url(), uri_cstr); // Root library didn't change.
7577
7578 result = Dart_SetRootLibrary(core_lib);
7580 root_lib = Dart_RootLibrary();
7581 lib_uri = Dart_LibraryUrl(root_lib);
7582 EXPECT_VALID(Dart_StringToCString(lib_uri, &uri_cstr));
7583 EXPECT_STREQ("dart:core", uri_cstr); // Root library did change.
7584
7587 root_lib = Dart_RootLibrary();
7588 EXPECT(Dart_IsNull(root_lib)); // Root library did change.
7589}
7590
7591TEST_CASE(DartAPI_LookupLibrary) {
7592 const char* kScriptChars =
7593 "import 'library1_dart';"
7594 "main() {}";
7595 const char* kLibrary1 = "file:///library1_dart";
7596 const char* kLibrary1Chars =
7597 "library library1;"
7598 "final x = 0;";
7599
7600 Dart_Handle url;
7602
7603 // Create a test library and load up a test script in it.
7604 TestCase::AddTestLib("file:///library1_dart", kLibrary1Chars);
7605 // LoadTestScript resets the LibraryTagHandler, which we don't want when
7606 // using the VM compiler, so we only use it with the Dart frontend for this
7607 // test.
7608 result = TestCase::LoadTestScript(kScriptChars, nullptr, TestCase::url());
7610
7611 url = NewString(kLibrary1);
7614
7617 "Dart_LookupLibrary expects argument 'url' to be non-null.");
7618
7621 result,
7622 "Dart_LookupLibrary expects argument 'url' to be of type String.");
7623
7624 result = Dart_LookupLibrary(Dart_NewApiError("incoming error"));
7626 EXPECT_STREQ("incoming error", Dart_GetError(result));
7627
7628 url = NewString("noodles.dart");
7630 EXPECT_ERROR(result, "Dart_LookupLibrary: library 'noodles.dart' not found.");
7631}
7632
7633TEST_CASE(DartAPI_LibraryUrl) {
7634 const char* kLibrary1Chars = "library library1_name;";
7635 Dart_Handle lib = TestCase::LoadTestLibrary("library1_url", kLibrary1Chars);
7636 Dart_Handle error = Dart_NewApiError("incoming error");
7637 EXPECT_VALID(lib);
7638
7641 "Dart_LibraryUrl expects argument 'library' to be non-null.");
7642
7645 result,
7646 "Dart_LibraryUrl expects argument 'library' to be of type Library.");
7647
7650 EXPECT_STREQ("incoming error", Dart_GetError(result));
7651
7652 result = Dart_LibraryUrl(lib);
7655 const char* cstr = nullptr;
7657 EXPECT_SUBSTRING("library1_url", cstr);
7658}
7659
7670}
7671
7673 int arg_count,
7674 bool* auto_setup_scope) {
7675 ASSERT(auto_setup_scope != nullptr);
7676 *auto_setup_scope = false;
7678}
7679
7681 int arg_count,
7682 bool* auto_setup_scope) {
7683 ASSERT(auto_setup_scope != nullptr);
7684 *auto_setup_scope = false;
7686}
7687
7688TEST_CASE(DartAPI_SetNativeResolver) {
7689 const char* kScriptChars =
7690 R"(
7691 class Test {
7692 @pragma('vm:external-name', 'SomeNativeFunction')
7693 external static foo();
7694
7695 @pragma('vm:external-name', 'SomeNativeFunction2')
7696 external static bar();
7697
7698 @pragma('vm:external-name', 'SomeNativeFunction3')
7699 external static baz();
7700 }
7701 )";
7702 Dart_Handle error = Dart_NewApiError("incoming error");
7704
7705 // Load a test script.
7706 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
7707 EXPECT_VALID(lib);
7710 EXPECT(Dart_IsLibrary(lib));
7712 Dart_GetNonNullableType(lib, NewString("Test"), 0, nullptr);
7714
7717 result,
7718 "Dart_SetNativeResolver expects argument 'library' to be non-null.");
7719
7722 "Dart_SetNativeResolver expects argument 'library' to be of "
7723 "type Library.");
7724
7727 EXPECT_STREQ("incoming error", Dart_GetError(result));
7728
7731
7732 // Call a function and make sure native resolution works.
7733 result = Dart_Invoke(type, NewString("foo"), 0, nullptr);
7736 int64_t value = 0;
7738 EXPECT_EQ(654321, value);
7739
7740 // A second call succeeds.
7743
7744 // 'foo' has already been resolved so gets the old value.
7745 result = Dart_Invoke(type, NewString("foo"), 0, nullptr);
7748 value = 0;
7750 EXPECT_EQ(654321, value);
7751
7752 // 'bar' has not yet been resolved so gets the new value.
7753 result = Dart_Invoke(type, NewString("bar"), 0, nullptr);
7756 value = 0;
7758 EXPECT_EQ(123456, value);
7759
7760 // A nullptr resolver is okay, but resolution will fail.
7761 result = Dart_SetNativeResolver(lib, nullptr, nullptr);
7763
7764 EXPECT_ERROR(Dart_Invoke(type, NewString("baz"), 0, nullptr),
7765 "native function 'SomeNativeFunction3' (0 arguments) "
7766 "cannot be found");
7767}
7768
7769// Test that an imported name does not clash with the same name defined
7770// in the importing library.
7771TEST_CASE(DartAPI_ImportLibrary2) {
7772 const char* kScriptChars =
7773 "import 'library1_dart';\n"
7774 "var foo;\n"
7775 "main() { foo = 0; }\n";
7776 const char* kLibrary1Chars =
7777 "library library1_dart;\n"
7778 "import 'library2_dart';\n"
7779 "var foo;\n";
7780 const char* kLibrary2Chars =
7781 "library library2_dart;\n"
7782 "import 'library1_dart';\n"
7783 "var foo;\n";
7785 Dart_Handle lib;
7786
7787 // Create a test library and Load up a test script in it.
7788 Dart_SourceFile sourcefiles[] = {
7789 {RESOLVED_USER_TEST_URI, kScriptChars},
7790 {"file:///library1_dart", kLibrary1Chars},
7791 {"file:///library2_dart", kLibrary2Chars},
7793 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7794 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, nullptr,
7795 true);
7796 EXPECT_VALID(lib);
7797
7800 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
7802}
7803
7804// Test that if the same name is imported from two libraries, it is
7805// an error if that name is referenced.
7806TEST_CASE(DartAPI_ImportLibrary3) {
7807 const char* kScriptChars =
7808 "import 'file:///library2_dart';\n"
7809 "import 'file:///library1_dart';\n"
7810 "var foo_top = 10; // foo has dup def. So should be an error.\n"
7811 "main() { foo = 0; }\n";
7812 const char* kLibrary1Chars =
7813 "library library1_dart;\n"
7814 "var foo;";
7815 const char* kLibrary2Chars =
7816 "library library2_dart;\n"
7817 "var foo;";
7819 Dart_Handle lib;
7820
7821 // Create a test library and Load up a test script in it.
7822 Dart_SourceFile sourcefiles[] = {
7823 {RESOLVED_USER_TEST_URI, kScriptChars},
7824 {"file:///library2_dart", kLibrary2Chars},
7825 {"file:///library1_dart", kLibrary1Chars},
7826 };
7827 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7828 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, nullptr,
7829 true);
7831 "Compilation failed /test-lib:4:10:"
7832 " Error: Setter not found: 'foo'");
7833 return;
7834
7837 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
7839 EXPECT_SUBSTRING("NoSuchMethodError", Dart_GetError(result));
7840}
7841
7842// Test that if the same name is imported from two libraries, it is
7843// not an error if that name is not used.
7844TEST_CASE(DartAPI_ImportLibrary4) {
7845 const char* kScriptChars =
7846 "import 'library2_dart';\n"
7847 "import 'library1_dart';\n"
7848 "main() { }\n";
7849 const char* kLibrary1Chars =
7850 "library library1_dart;\n"
7851 "var foo;";
7852 const char* kLibrary2Chars =
7853 "library library2_dart;\n"
7854 "var foo;";
7856 Dart_Handle lib;
7857
7858 // Create a test library and Load up a test script in it.
7859 Dart_SourceFile sourcefiles[] = {
7860 {RESOLVED_USER_TEST_URI, kScriptChars},
7861 {"file:///library2_dart", kLibrary2Chars},
7862 {"file:///library1_dart", kLibrary1Chars},
7863 };
7864 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7865 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, nullptr,
7866 true);
7867 EXPECT_VALID(lib);
7868
7871 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
7873}
7874
7875TEST_CASE(DartAPI_ImportLibrary5) {
7876 const char* kScriptChars =
7877 "import 'lib.dart';\n"
7878 "abstract class Y {\n"
7879 " void set handler(void callback(List<int> x));\n"
7880 "}\n"
7881 "void main() {}\n";
7882 const char* kLibraryChars =
7883 "library lib.dart;\n"
7884 "abstract class X {\n"
7885 " void set handler(void callback(List<int> x));\n"
7886 "}\n";
7888 Dart_Handle lib;
7889
7890 // Create a test library and Load up a test script in it.
7891 Dart_SourceFile sourcefiles[] = {
7892 {RESOLVED_USER_TEST_URI, kScriptChars},
7893 {"file:///lib.dart", kLibraryChars},
7894 };
7895 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7896 lib = TestCase::LoadTestScriptWithDFE(sourcefiles_count, sourcefiles, nullptr,
7897 true);
7898 EXPECT_VALID(lib);
7899
7902 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
7904}
7905
7906TEST_CASE(DartAPI_Multiroot_Valid) {
7907 const char* kScriptChars =
7908 "import 'lib.dart';\n"
7909 "void main() {}\n";
7910 const char* kLibraryChars = "library lib.dart;\n";
7912 Dart_Handle lib;
7913
7914 Dart_SourceFile sourcefiles[] = {
7915 {"file:///bar/main.dart", kScriptChars},
7916 {"file:///baz/lib.dart", kLibraryChars},
7917 {"file:///bar/.packages", ""},
7918 };
7919 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7921 sourcefiles_count, sourcefiles, nullptr, /* finalize= */ true,
7922 /* incrementally= */ true, /* allow_compile_errors= */ false,
7923 "foo:///main.dart",
7924 /* multiroot_filepaths= */ "/bar,/baz",
7925 /* multiroot_scheme= */ "foo");
7926 EXPECT_VALID(lib);
7927 {
7928 TransitionNativeToVM transition(thread);
7929 Library& lib_obj = Library::Handle();
7930 lib_obj ^= Api::UnwrapHandle(lib);
7931 EXPECT_STREQ("foo:///main.dart", String::Handle(lib_obj.url()).ToCString());
7932 const Array& lib_scripts = Array::Handle(lib_obj.LoadedScripts());
7933 Script& script = Script::Handle();
7935 for (intptr_t i = 0; i < lib_scripts.Length(); i++) {
7936 script ^= lib_scripts.At(i);
7937 uri = script.url();
7938 const char* uri_str = uri.ToCString();
7939 EXPECT(strstr(uri_str, "foo:///") == uri_str);
7940 }
7941 }
7944 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
7946}
7947
7948TEST_CASE(DartAPI_Multiroot_FailWhenUriIsWrong) {
7949 const char* kScriptChars =
7950 "import 'lib.dart';\n"
7951 "void main() {}\n";
7952 const char* kLibraryChars = "library lib.dart;\n";
7953 Dart_Handle lib;
7954
7955 Dart_SourceFile sourcefiles[] = {
7956 {"file:///bar/main.dart", kScriptChars},
7957 {"file:///baz/lib.dart", kLibraryChars},
7958 {"file:///bar/.packages", "untitled:/"},
7959 };
7960 int sourcefiles_count = sizeof(sourcefiles) / sizeof(Dart_SourceFile);
7962 sourcefiles_count, sourcefiles, nullptr, /* finalize= */ true,
7963 /* incrementally= */ true, /* allow_compile_errors= */ false,
7964 "foo1:///main.dart",
7965 /* multiroot_filepaths= */ "/bar,/baz",
7966 /* multiroot_scheme= */ "foo");
7967 EXPECT_ERROR(lib,
7968 "Compilation failed Invalid argument(s): Exception when reading "
7969 "'foo1:///.dart_tool");
7970}
7971
7972static void NewNativePort_send123(Dart_Port dest_port_id,
7974 // Gets a send port message.
7975 EXPECT_NOTNULL(message);
7976 EXPECT_EQ(Dart_CObject_kArray, message->type);
7977 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
7978
7979 // Post integer value.
7980 Dart_CObject* response =
7981 reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
7982 response->type = Dart_CObject_kInt32;
7983 response->value.as_int32 = 123;
7984 Dart_PostCObject(message->value.as_array.values[0]->value.as_send_port.id,
7985 response);
7986}
7987
7988static void NewNativePort_send321(Dart_Port dest_port_id,
7990 // Gets a null message.
7991 EXPECT_NOTNULL(message);
7992 EXPECT_EQ(Dart_CObject_kArray, message->type);
7993 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
7994
7995 // Post integer value.
7996 Dart_CObject* response =
7997 reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
7998 response->type = Dart_CObject_kInt32;
7999 response->value.as_int32 = 321;
8000 Dart_PostCObject(message->value.as_array.values[0]->value.as_send_port.id,
8001 response);
8003
8004TEST_CASE(DartAPI_IllegalNewSendPort) {
8008}
8009
8010TEST_CASE(DartAPI_IllegalPost) {
8012 bool success = Dart_Post(ILLEGAL_PORT, message);
8013 EXPECT(!success);
8014}
8015
8016static void UnreachableFinalizer(void* isolate_callback_data, void* peer) {
8017 UNREACHABLE();
8018}
8019
8020TEST_CASE(DartAPI_PostCObject_DoesNotRunFinalizerOnFailure) {
8021 char* my_str =
8022 Utils::StrDup("Ownership of this memory remains with the caller");
8023
8026 message.value.as_external_typed_data.type = Dart_TypedData_kUint8;
8027 message.value.as_external_typed_data.length = strlen(my_str);
8028 message.value.as_external_typed_data.data =
8029 reinterpret_cast<uint8_t*>(my_str);
8030 message.value.as_external_typed_data.peer = my_str;
8031 message.value.as_external_typed_data.callback = UnreachableFinalizer;
8032
8033 bool success = Dart_PostCObject(ILLEGAL_PORT, &message);
8034 EXPECT(!success);
8035
8036 free(my_str); // Never a double-free.
8037}
8038
8039VM_UNIT_TEST_CASE(DartAPI_NewNativePort) {
8040 // Create a port with a bogus handler.
8041 Dart_Port error_port = Dart_NewNativePort("Foo", nullptr, true);
8042 EXPECT_EQ(ILLEGAL_PORT, error_port);
8043
8044 // Create the port w/o a current isolate, just to make sure that works.
8045 Dart_Port port_id1 =
8046 Dart_NewNativePort("Port123", NewNativePort_send123, true);
8047
8048 TestIsolateScope __test_isolate__;
8049 const char* kScriptChars =
8050 "import 'dart:isolate';\n"
8051 "void callPort(SendPort port) {\n"
8052 " var receivePort = new RawReceivePort();\n"
8053 " var replyPort = receivePort.sendPort;\n"
8054 " port.send(<dynamic>[replyPort]);\n"
8055 " receivePort.handler = (message) {\n"
8056 " receivePort.close();\n"
8057 " throw new Exception(message);\n"
8058 " };\n"
8059 "}\n";
8060 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8062
8063 // Create a port w/ a current isolate, to make sure that works too.
8064 Dart_Port port_id2 =
8065 Dart_NewNativePort("Port321", NewNativePort_send321, true);
8066
8067 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
8068 EXPECT_VALID(send_port1);
8069 Dart_Handle send_port2 = Dart_NewSendPort(port_id2);
8070 EXPECT_VALID(send_port2);
8071
8072 // Test first port.
8073 Dart_Handle dart_args[1];
8074 dart_args[0] = send_port1;
8075 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8077 result = Dart_RunLoop();
8080 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
8081
8082 // result second port.
8083 dart_args[0] = send_port2;
8084 result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8086 result = Dart_RunLoop();
8089 EXPECT_SUBSTRING("Exception: 321\n", Dart_GetError(result));
8090
8092
8093 // Delete the native ports.
8094 EXPECT(Dart_CloseNativePort(port_id1));
8095 EXPECT(Dart_CloseNativePort(port_id2));
8097
8098static void NewNativePort_sendInteger123(Dart_Port dest_port_id,
8100 // Gets a send port message.
8101 EXPECT_NOTNULL(message);
8102 EXPECT_EQ(Dart_CObject_kArray, message->type);
8103 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
8104
8105 // Post integer value.
8106 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
8107 123);
8109
8110static void NewNativePort_sendInteger321(Dart_Port dest_port_id,
8112 // Gets a null message.
8113 EXPECT_NOTNULL(message);
8114 EXPECT_EQ(Dart_CObject_kArray, message->type);
8115 EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
8116
8117 // Post integer value.
8118 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
8119 321);
8120}
8121
8122TEST_CASE(DartAPI_NativePortPostInteger) {
8123 const char* kScriptChars =
8124 "import 'dart:isolate';\n"
8125 "void callPort(SendPort port) {\n"
8126 " var receivePort = new RawReceivePort();\n"
8127 " var replyPort = receivePort.sendPort;\n"
8128 " port.send(<dynamic>[replyPort]);\n"
8129 " receivePort.handler = (message) {\n"
8130 " receivePort.close();\n"
8131 " throw new Exception(message);\n"
8132 " };\n"
8133 "}\n";
8134 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8136
8137 Dart_Port port_id1 =
8139 Dart_Port port_id2 =
8141
8142 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
8143 EXPECT_VALID(send_port1);
8144 Dart_Handle send_port2 = Dart_NewSendPort(port_id2);
8145 EXPECT_VALID(send_port2);
8146
8147 // Test first port.
8148 Dart_Handle dart_args[1];
8149 dart_args[0] = send_port1;
8150 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8152 result = Dart_RunLoop();
8155 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
8156
8157 // result second port.
8158 dart_args[0] = send_port2;
8159 result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8161 result = Dart_RunLoop();
8164 EXPECT_SUBSTRING("Exception: 321\n", Dart_GetError(result));
8165
8167
8168 // Delete the native ports.
8169 EXPECT(Dart_CloseNativePort(port_id1));
8171}
8172
8173static void NewNativePort_Transferrable1(Dart_Port dest_port_id,
8175 // Gets a send port message.
8176 EXPECT_NOTNULL(message);
8177 EXPECT_EQ(Dart_CObject_kTypedData, message->type);
8178 EXPECT_EQ(Dart_TypedData_kUint8, message->value.as_typed_data.type);
8179 EXPECT_EQ(10, message->value.as_typed_data.length);
8180 EXPECT_EQ(42, message->value.as_typed_data.values[0]);
8181 free(const_cast<uint8_t*>(message->value.as_typed_data.values));
8182}
8183
8186 // Gets a send port message.
8187 EXPECT_NOTNULL(message);
8188 EXPECT_EQ(Dart_CObject_kArray, message->type);
8189 EXPECT_EQ(1, message->value.as_array.length);
8191 EXPECT_EQ(Dart_CObject_kTypedData, cobj->type);
8193 EXPECT_EQ(10, cobj->value.as_typed_data.length);
8194 EXPECT_EQ(42, cobj->value.as_typed_data.values[0]);
8195 free(const_cast<uint8_t*>(cobj->value.as_typed_data.values));
8196}
8197
8198TEST_CASE(DartAPI_NativePortPostTransferrableTypedData) {
8199 const char* kScriptChars =
8200 "import 'dart:typed_data';\n"
8201 "import 'dart:isolate';\n"
8202 "void callPort(SendPort port1, SendPort port2) {\n"
8203 " final td1 ="
8204 " TransferableTypedData.fromList([Uint8List(10)..[0] = 42]);\n"
8205 " final td2 ="
8206 " TransferableTypedData.fromList([Uint8List(10)..[0] = 42]);\n"
8207 " port1.send(td1);\n"
8208 " port2.send([td2]);\n"
8209 "}\n";
8210 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8212
8213 Dart_Port port_id1 =
8215 Dart_Port port_id2 =
8217
8218 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
8219 EXPECT_VALID(send_port1);
8220 Dart_Handle send_port2 = Dart_NewSendPort(port_id2);
8221 EXPECT_VALID(send_port2);
8222
8223 // Test first port.
8224 Dart_Handle dart_args[2];
8225 dart_args[0] = send_port1;
8226 dart_args[1] = send_port2;
8227 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 2, dart_args);
8229 result = Dart_RunLoop();
8231
8233
8234 // Delete the native ports.
8235 EXPECT(Dart_CloseNativePort(port_id1));
8236 EXPECT(Dart_CloseNativePort(port_id2));
8237}
8238
8239static constexpr intptr_t kSendLength = 16;
8240
8241static void NewNativePort_ExternalTypedData(Dart_Port dest_port_id,
8243 // Gets a send port message.
8244 EXPECT_NOTNULL(message);
8245 EXPECT_EQ(Dart_CObject_kTypedData, message->type);
8246 EXPECT_EQ(Dart_TypedData_kUint8, message->value.as_typed_data.type);
8247 EXPECT_EQ(kSendLength, message->value.as_typed_data.length);
8248 for (intptr_t i = 0; i < kSendLength; i++) {
8249 EXPECT_EQ((0x41 + i), message->value.as_typed_data.values[i]);
8250 }
8251}
8252
8253static void FinalizeTypedData(void* isolate_callback_data, void* peer) {
8254 delete[] reinterpret_cast<int8_t*>(peer);
8255}
8256
8257TEST_CASE(DartAPI_NativePortPostExternalTypedData) {
8258 int8_t* extTypedData = new int8_t[kSendLength];
8259 for (int i = 0; i < kSendLength; i++) {
8260 extTypedData[i] = 0x41 + i;
8261 }
8262 const char* kScriptChars =
8263 "import 'dart:typed_data';\n"
8264 "import 'dart:isolate';\n"
8265 "void callPort(SendPort port, Uint8List data) {\n"
8266 " port.send(data);\n"
8267 "}\n";
8268 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8270
8271 Dart_Port port_id =
8273
8274 Dart_Handle send_port = Dart_NewSendPort(port_id);
8275 EXPECT_VALID(send_port);
8276
8278 Dart_TypedData_kUint8, extTypedData, kSendLength, extTypedData,
8280 EXPECT_VALID(extdata);
8281
8282 // Test first port.
8283 Dart_Handle dart_args[2];
8284 dart_args[0] = send_port;
8285 dart_args[1] = extdata;
8286 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 2, dart_args);
8290
8292
8293 // Delete the native ports.
8294 EXPECT(Dart_CloseNativePort(port_id));
8295}
8296
8297static void UnreachableMessageHandler(Dart_Port dest_port_id,
8299 UNREACHABLE();
8300}
8301
8302TEST_CASE(DartAPI_NativePortPostUserClass) {
8303 const char* kScriptChars =
8304 "import 'dart:isolate';\n"
8305 "class ABC {}\n"
8306 "void callPort(SendPort port) {\n"
8307 " port.send(new ABC());\n"
8308 "}\n";
8309 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8311
8312 Dart_Port port_id =
8314
8315 // Test send with port open.
8316 {
8317 Dart_Handle send_port = Dart_NewSendPort(port_id);
8318 EXPECT_VALID(send_port);
8319 Dart_Handle dart_args[1];
8320 dart_args[0] = send_port;
8321 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8322 EXPECT_ERROR(result, "Invalid argument");
8323 }
8324
8325 // Test send with port closed.
8326 {
8327 Dart_CloseNativePort(port_id);
8328 Dart_Handle send_port = Dart_NewSendPort(port_id);
8329 EXPECT_VALID(send_port);
8330 Dart_Handle dart_args[1];
8331 dart_args[0] = send_port;
8332 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8333 EXPECT_ERROR(result, "Invalid argument");
8334 }
8335
8337}
8338
8341 EXPECT_NOTNULL(message);
8342
8343 if ((message->type == Dart_CObject_kArray) &&
8344 (message->value.as_array.values[0]->type == Dart_CObject_kSendPort)) {
8345 // Post integer value.
8346 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
8347 123);
8348 } else {
8349 EXPECT_EQ(message->type, Dart_CObject_kNull);
8350 }
8351}
8352
8353TEST_CASE(DartAPI_NativePortReceiveNull) {
8354 const char* kScriptChars =
8355 "import 'dart:isolate';\n"
8356 "void callPort(SendPort port) {\n"
8357 " var receivePort = new RawReceivePort();\n"
8358 " var replyPort = receivePort.sendPort;\n"
8359 " port.send(null);\n"
8360 " port.send(<dynamic>[replyPort]);\n"
8361 " receivePort.handler = (message) {\n"
8362 " receivePort.close();\n"
8363 " throw new Exception(message);\n"
8364 " };\n"
8365 "}\n";
8366 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8368
8369 Dart_Port port_id1 =
8371 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
8372 EXPECT_VALID(send_port1);
8373
8374 // Test first port.
8375 Dart_Handle dart_args[1];
8376 dart_args[0] = send_port1;
8377 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8379 result = Dart_RunLoop();
8382 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
8383
8385
8386 // Delete the native ports.
8387 EXPECT(Dart_CloseNativePort(port_id1));
8388}
8389
8390static void NewNativePort_nativeReceiveInteger(Dart_Port dest_port_id,
8392 EXPECT_NOTNULL(message);
8393
8394 if ((message->type == Dart_CObject_kArray) &&
8395 (message->value.as_array.values[0]->type == Dart_CObject_kSendPort)) {
8396 // Post integer value.
8397 Dart_PostInteger(message->value.as_array.values[0]->value.as_send_port.id,
8398 123);
8399 } else {
8400 EXPECT_EQ(message->type, Dart_CObject_kInt32);
8401 EXPECT_EQ(message->value.as_int32, 321);
8402 }
8403}
8404
8405TEST_CASE(DartAPI_NativePortReceiveInteger) {
8406 const char* kScriptChars =
8407 "import 'dart:isolate';\n"
8408 "void callPort(SendPort port) {\n"
8409 " var receivePort = new RawReceivePort();\n"
8410 " var replyPort = receivePort.sendPort;\n"
8411 " port.send(321);\n"
8412 " port.send(<dynamic>[replyPort]);\n"
8413 " receivePort.handler = (message) {\n"
8414 " receivePort.close();\n"
8415 " throw new Exception(message);\n"
8416 " };\n"
8417 "}\n";
8418 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8420
8421 Dart_Port port_id1 =
8423 Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
8424 EXPECT_VALID(send_port1);
8425
8426 // Test first port.
8427 Dart_Handle dart_args[1];
8428 dart_args[0] = send_port1;
8429 Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
8431 result = Dart_RunLoop();
8434 EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
8435
8437
8438 // Delete the native ports.
8439 EXPECT(Dart_CloseNativePort(port_id1));
8440}
8441
8442static Dart_Isolate RunLoopTestCallback(const char* script_name,
8443 const char* main,
8444 const char* package_root,
8445 const char* package_config,
8447 void* data,
8448 char** error) {
8449 const char* kScriptChars =
8450 "import 'dart:isolate';\n"
8451 "void main(shouldThrowException) {\n"
8452 " var rp = new RawReceivePort();\n"
8453 " rp.handler = (msg) {\n"
8454 " rp.close();\n"
8455 " if (shouldThrowException) {\n"
8456 " throw new Exception('ExceptionFromTimer');\n"
8457 " }\n"
8458 " };\n"
8459 " rp.sendPort.send(1);\n"
8460 "}\n";
8461
8462 if (Dart_CurrentIsolate() != nullptr) {
8464 }
8465 Dart_Isolate isolate = TestCase::CreateTestIsolate(script_name);
8466 ASSERT(isolate != nullptr);
8467 if (Dart_IsServiceIsolate(isolate)) {
8468 return isolate;
8471 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8472 EXPECT_VALID(lib);
8477 char* err_msg = Dart_IsolateMakeRunnable(isolate);
8478 EXPECT(err_msg == nullptr);
8479 return isolate;
8480}
8481
8482// Common code for RunLoop_Success/RunLoop_Failure.
8483static void RunLoopTest(bool throw_exception) {
8486 Dart_Isolate isolate = RunLoopTestCallback(nullptr, nullptr, nullptr, nullptr,
8487 nullptr, nullptr, nullptr);
8488
8489 Dart_EnterIsolate(isolate);
8492 EXPECT_VALID(lib);
8493
8495 Dart_Handle args[1];
8496 args[0] = (throw_exception ? Dart_True() : Dart_False());
8497 result = Dart_Invoke(lib, NewString("main"), 1, args);
8499 result = Dart_RunLoop();
8500 if (throw_exception) {
8501 EXPECT_ERROR(result, "Exception: ExceptionFromTimer");
8502 } else {
8504 }
8505
8510}
8511
8512VM_UNIT_TEST_CASE(DartAPI_RunLoop_Success) {
8513 RunLoopTest(false);
8514}
8515
8516VM_UNIT_TEST_CASE(DartAPI_RunLoop_Exception) {
8517 RunLoopTest(true);
8518}
8519
8520static void* shutdown_isolate_group_data;
8521static void* shutdown_isolate_data;
8522static void* cleanup_isolate_group_data;
8523static void* cleanup_isolate_data;
8524
8525// Called on isolate shutdown time (which is still allowed to run Dart code)
8526static void IsolateShutdownTestCallback(void* group_data, void* isolate_data) {
8527 // Shutdown runs before cleanup.
8530
8531 // Shutdown must have a current isolate (since it is allowed to execute Dart
8532 // code)
8533 EXPECT(Dart_CurrentIsolate() != nullptr);
8534 EXPECT(Dart_CurrentIsolateGroupData() == group_data);
8535 EXPECT(Dart_CurrentIsolateData() == isolate_data);
8536
8537 shutdown_isolate_group_data = group_data;
8538 shutdown_isolate_data = isolate_data;
8539}
8540
8541// Called on isolate cleanup time (which is after the isolate has been
8542// destroyed)
8543static void IsolateCleanupTestCallback(void* group_data, void* isolate_data) {
8544 // Cleanup runs after shutdown.
8546 EXPECT(shutdown_isolate_data != nullptr);
8548 // The isolate was destroyed and there should not be a current isolate.
8549 EXPECT(Dart_CurrentIsolate() == nullptr);
8550
8551 cleanup_isolate_group_data = group_data;
8552 cleanup_isolate_data = isolate_data;
8553}
8554
8555// Called on isolate group cleanup time (once all isolates have been destroyed)
8556static void* cleanup_group_callback_data;
8557static void IsolateGroupCleanupTestCallback(void* callback_data) {
8558 cleanup_group_callback_data = callback_data;
8559}
8560
8561VM_UNIT_TEST_CASE(DartAPI_IsolateShutdownAndCleanup) {
8563 Dart_IsolateGroupCleanupCallback saved_cleanup =
8568
8570 shutdown_isolate_data = nullptr;
8572 void* my_group_data = reinterpret_cast<void*>(123);
8573 void* my_data = reinterpret_cast<void*>(456);
8574
8575 // Create an isolate.
8576 Dart_Isolate isolate =
8577 TestCase::CreateTestIsolate(nullptr, my_group_data, my_data);
8578 EXPECT(isolate != nullptr);
8579
8580 // The shutdown callback has not been called.
8581 EXPECT(nullptr == shutdown_isolate_data);
8584
8585 // The isolate is the active isolate which allows us to access the isolate
8586 // specific and isolate-group specific data.
8587 EXPECT(Dart_CurrentIsolateData() == my_data);
8588 EXPECT(Dart_CurrentIsolateGroupData() == my_group_data);
8589
8590 // Shutdown the isolate.
8592
8593 // The shutdown & cleanup callbacks have been called.
8594 EXPECT(my_data == shutdown_isolate_data);
8595 EXPECT(my_group_data == shutdown_isolate_group_data);
8596 EXPECT(my_data == cleanup_isolate_data);
8597 EXPECT(my_group_data == cleanup_isolate_group_data);
8598 EXPECT(my_group_data == cleanup_group_callback_data);
8599
8600 Isolate::SetShutdownCallback(saved_shutdown);
8601 Isolate::SetGroupCleanupCallback(saved_cleanup);
8602}
8603
8604static int64_t add_result = 0;
8605static void IsolateShutdownRunDartCodeTestCallback(void* isolate_group_data,
8606 void* isolate_data) {
8608 if (Dart_IsKernelIsolate(isolate) || Dart_IsServiceIsolate(isolate)) {
8609 return;
8610 } else {
8611 ASSERT(add_result == 0);
8612 }
8615 EXPECT_VALID(lib);
8616 Dart_Handle arg1 = Dart_NewInteger(90);
8617 EXPECT_VALID(arg1);
8618 Dart_Handle arg2 = Dart_NewInteger(9);
8619 EXPECT_VALID(arg2);
8620 Dart_Handle dart_args[2] = {arg1, arg2};
8621 Dart_Handle result = Dart_Invoke(lib, NewString("add"), 2, dart_args);
8626}
8627
8628VM_UNIT_TEST_CASE(DartAPI_IsolateShutdownRunDartCode) {
8629 const char* kScriptChars =
8630 "int add(int a, int b) {\n"
8631 " return a + b;\n"
8632 "}\n"
8633 "\n"
8634 "void main() {\n"
8635 " add(4, 5);\n"
8636 "}\n";
8637
8638 // Create an isolate.
8639 auto isolate = reinterpret_cast<Isolate*>(TestCase::CreateTestIsolate());
8640 EXPECT(isolate != nullptr);
8641
8642 isolate->set_on_shutdown_callback(IsolateShutdownRunDartCodeTestCallback);
8643
8644 {
8646 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8647 EXPECT_VALID(lib);
8652 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
8655 }
8656
8657 // The shutdown callback has not been called.
8658 EXPECT_EQ(0, add_result);
8659
8660 // Shutdown the isolate.
8662
8663 // The shutdown callback has been called and ran Dart code.
8664 EXPECT_EQ(99, add_result);
8665}
8666
8667static int64_t GetValue(Dart_Handle arg) {
8668 EXPECT_VALID(arg);
8669 EXPECT(Dart_IsInteger(arg));
8670 int64_t value;
8672 return value;
8673}
8674
8677 intptr_t i = Dart_GetNativeArgumentCount(args);
8678 EXPECT_EQ(1, i);
8680 EXPECT_VALID(arg);
8683}
8684
8687 intptr_t i = Dart_GetNativeArgumentCount(args);
8688 EXPECT_EQ(2, i);
8690 EXPECT_VALID(arg1);
8691 int64_t value = 0;
8692 EXPECT_VALID(Dart_IntegerToInt64(arg1, &value));
8693 int64_t integer_value = 0;
8696 EXPECT_EQ(value, integer_value);
8697 double double_value;
8698 result = Dart_GetNativeDoubleArgument(args, 1, &double_value);
8700 bool bool_value;
8701 result = Dart_GetNativeBooleanArgument(args, 1, &bool_value);
8716
8719 intptr_t i = Dart_GetNativeArgumentCount(args);
8720 EXPECT_EQ(4, i);
8725 args, Dart_NewInteger(GetValue(arg1) + GetValue(arg2) + GetValue(arg3)));
8727}
8728
8730 int arg_count,
8731 bool* auto_setup_scope) {
8732 ASSERT(auto_setup_scope != nullptr);
8733 *auto_setup_scope = false;
8734 TransitionNativeToVM transition(Thread::Current());
8735 const Object& obj = Object::Handle(Api::UnwrapHandle(name));
8736 if (!obj.IsString()) {
8737 return nullptr;
8738 }
8739 const char* function_name = obj.ToCString();
8740 const char* kNativeFoo1 = "NativeFoo1";
8741 const char* kNativeFoo2 = "NativeFoo2";
8742 const char* kNativeFoo3 = "NativeFoo3";
8743 const char* kNativeFoo4 = "NativeFoo4";
8744 if (strncmp(function_name, kNativeFoo1, strlen(kNativeFoo1)) == 0) {
8745 return &NativeFoo1;
8746 } else if (strncmp(function_name, kNativeFoo2, strlen(kNativeFoo2)) == 0) {
8747 return &NativeFoo2;
8748 } else if (strncmp(function_name, kNativeFoo3, strlen(kNativeFoo3)) == 0) {
8749 return &NativeFoo3;
8750 } else if (strncmp(function_name, kNativeFoo4, strlen(kNativeFoo4)) == 0) {
8751 return &NativeFoo4;
8752 } else {
8753 UNREACHABLE();
8754 return nullptr;
8755 }
8756}
8757
8758TEST_CASE(DartAPI_NativeFunctionClosure) {
8759 const char* kScriptChars =
8760 R"(
8761 class Test {
8762 @pragma('vm:external-name', 'NativeFoo1')
8763 external int foo1();
8764
8765 @pragma('vm:external-name', 'NativeFoo2')
8766 external int foo2(int i);
8768 @pragma('vm:external-name', 'NativeFoo3')
8769 external int foo3([int k = 10000, int l = 1]);
8770
8771 @pragma('vm:external-name', 'NativeFoo4')
8772 external int foo4(int i, [int j = 10, int k = 1]);
8773
8774 int bar1() { var func = foo1; return func(); }
8775 int bar2(int i) { var func = foo2; return func(i); }
8776 int bar30() { var func = foo3; return func(); }
8777 int bar31(int i) { var func = foo3; return func(i); }
8778 int bar32(int i, int j) { var func = foo3; return func(i, j); }
8779 int bar41(int i) {
8780 var func = foo4; return func(i); }
8781 int bar42(int i, int j) {
8782 var func = foo4; return func(i, j); }
8783 int bar43(int i, int j, int k) {
8784 var func = foo4; return func(i, j, k); }
8785 }
8786 class Expect {
8787 static equals(a, b) {
8788 if (a != b) {
8789 throw 'not equal. expected: $a, got: $b';
8790 }
8791 }
8792 }
8793 int testMain() {
8794 Test obj = new Test();
8795 Expect.equals(1, obj.foo1());
8796 Expect.equals(1, obj.bar1());
8797
8798 Expect.equals(10, obj.foo2(10));
8799 Expect.equals(10, obj.bar2(10));
8800
8801 Expect.equals(10001, obj.foo3());
8802 Expect.equals(10001, obj.bar30());
8803 Expect.equals(2, obj.foo3(1));
8804 Expect.equals(2, obj.bar31(1));
8805 Expect.equals(4, obj.foo3(2, 2));
8806 Expect.equals(4, obj.bar32(2, 2));
8807
8808 Expect.equals(12, obj.foo4(1));
8809 Expect.equals(12, obj.bar41(1));
8810 Expect.equals(3, obj.foo4(1, 1));
8811 Expect.equals(3, obj.bar42(1, 1));
8812 Expect.equals(6, obj.foo4(2, 2, 2));
8813 Expect.equals(6, obj.bar43(2, 2, 2));
8814
8815 return 0;
8816 }
8817 )";
8818
8820
8821 // Load a test script.
8822 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8823 EXPECT_VALID(lib);
8824 EXPECT(Dart_IsLibrary(lib));
8829
8830 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
8833 int64_t value = 0;
8835 EXPECT_EQ(0, value);
8837
8840 intptr_t i = Dart_GetNativeArgumentCount(args);
8841 EXPECT_EQ(0, i);
8844}
8845
8848 intptr_t i = Dart_GetNativeArgumentCount(args);
8849 EXPECT_EQ(1, i);
8853}
8854
8857 intptr_t i = Dart_GetNativeArgumentCount(args);
8858 EXPECT_EQ(2, i);
8863}
8864
8867 intptr_t i = Dart_GetNativeArgumentCount(args);
8868 EXPECT_EQ(3, i);
8873 args, Dart_NewInteger(GetValue(arg1) + GetValue(arg2) + GetValue(arg3)));
8875}
8876
8879 int arg_count,
8880 bool* auto_setup_scope) {
8881 ASSERT(auto_setup_scope != nullptr);
8882 *auto_setup_scope = false;
8883 TransitionNativeToVM transition(Thread::Current());
8885 if (!obj.IsString()) {
8886 return nullptr;
8887 }
8888 const char* function_name = obj.ToCString();
8889 const char* kNativeFoo1 = "StaticNativeFoo1";
8890 const char* kNativeFoo2 = "StaticNativeFoo2";
8891 const char* kNativeFoo3 = "StaticNativeFoo3";
8892 const char* kNativeFoo4 = "StaticNativeFoo4";
8893 if (strncmp(function_name, kNativeFoo1, strlen(kNativeFoo1)) == 0) {
8894 return &StaticNativeFoo1;
8895 } else if (strncmp(function_name, kNativeFoo2, strlen(kNativeFoo2)) == 0) {
8896 return &StaticNativeFoo2;
8897 } else if (strncmp(function_name, kNativeFoo3, strlen(kNativeFoo3)) == 0) {
8898 return &StaticNativeFoo3;
8899 } else if (strncmp(function_name, kNativeFoo4, strlen(kNativeFoo4)) == 0) {
8900 return &StaticNativeFoo4;
8901 } else {
8902 UNREACHABLE();
8903 return nullptr;
8904 }
8905}
8906
8907TEST_CASE(DartAPI_NativeStaticFunctionClosure) {
8908 const char* kScriptChars =
8909 R"(
8910 class Test {
8911 @pragma('vm:external-name', 'StaticNativeFoo1')
8912 external static int foo1();
8913
8914 @pragma('vm:external-name', 'StaticNativeFoo2')
8915 external static int foo2(int i);
8916
8917 @pragma('vm:external-name', 'StaticNativeFoo3')
8918 external static int foo3([int k = 10000, int l = 1]);
8919
8920 @pragma('vm:external-name', 'StaticNativeFoo4')
8921 external static int foo4(int i, [int j = 10, int k = 1]);
8922
8923 int bar1() { var func = foo1; return func(); }
8924 int bar2(int i) { var func = foo2; return func(i); }
8925 int bar30() { var func = foo3; return func(); }
8926 int bar31(int i) { var func = foo3; return func(i); }
8927 int bar32(int i, int j) { var func = foo3; return func(i, j); }
8928 int bar41(int i) {
8929 var func = foo4; return func(i); }
8930 int bar42(int i, int j) {
8931 var func = foo4; return func(i, j); }
8932 int bar43(int i, int j, int k) {
8933 var func = foo4; return func(i, j, k); }
8934 }
8935 class Expect {
8936 static equals(a, b) {
8937 if (a != b) {
8938 throw 'not equal. expected: $a, got: $b';
8939 }
8941 }
8942 int testMain() {
8943 Test obj = new Test();
8944 Expect.equals(0, Test.foo1());
8945 Expect.equals(0, obj.bar1());
8946
8947 Expect.equals(10, Test.foo2(10));
8948 Expect.equals(10, obj.bar2(10));
8949
8950 Expect.equals(10001, Test.foo3());
8951 Expect.equals(10001, obj.bar30());
8952 Expect.equals(2, Test.foo3(1));
8953 Expect.equals(2, obj.bar31(1));
8954 Expect.equals(4, Test.foo3(2, 2));
8955 Expect.equals(4, obj.bar32(2, 2));
8956
8957 Expect.equals(12, Test.foo4(1));
8958 Expect.equals(12, obj.bar41(1));
8959 Expect.equals(3, Test.foo4(1, 1));
8960 Expect.equals(3, obj.bar42(1, 1));
8961 Expect.equals(6, Test.foo4(2, 2, 2));
8962 Expect.equals(6, obj.bar43(2, 2, 2));
8963
8964 return 0;
8966 )";
8967
8969
8970 // Load a test script.
8971 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
8972 EXPECT_VALID(lib);
8973 EXPECT(Dart_IsLibrary(lib));
8978
8979 result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
8982 int64_t value = 0;
8984 EXPECT_EQ(0, value);
8985}
8986
8987TEST_CASE(DartAPI_RangeLimits) {
8988 uint8_t chars8[1] = {'a'};
8989 uint16_t chars16[1] = {'a'};
8990 int32_t chars32[1] = {'a'};
8991
8993 "expects argument 'length' to be in the range");
8995 "expects argument 'length' to be in the range");
8997 "expects argument 'length' to be in the range");
8999 "expects argument 'length' to be in the range");
9001 "expects argument 'length' to be in the range");
9004 "expects argument 'length' to be in the range");
9006 "expects argument 'length' to be in the range");
9009 "expects argument 'length' to be in the range");
9010}
9011
9012TEST_CASE(DartAPI_NewString_Null) {
9013 Dart_Handle str = Dart_NewStringFromUTF8(nullptr, 0);
9014 EXPECT_VALID(str);
9015 EXPECT(Dart_IsString(str));
9016 intptr_t len = -1;
9017 EXPECT_VALID(Dart_StringLength(str, &len));
9018 EXPECT_EQ(0, len);
9019
9020 str = Dart_NewStringFromUTF16(nullptr, 0);
9021 EXPECT_VALID(str);
9022 EXPECT(Dart_IsString(str));
9023 len = -1;
9024 EXPECT_VALID(Dart_StringLength(str, &len));
9025 EXPECT_EQ(0, len);
9026
9027 str = Dart_NewStringFromUTF32(nullptr, 0);
9028 EXPECT_VALID(str);
9029 EXPECT(Dart_IsString(str));
9030 len = -1;
9031 EXPECT_VALID(Dart_StringLength(str, &len));
9032 EXPECT_EQ(0, len);
9033}
9034
9035// Try to allocate a peer with a handles to objects of prohibited
9036// subtypes.
9037TEST_CASE(DartAPI_InvalidGetSetPeer) {
9038 void* out = &out;
9040 EXPECT(out == &out);
9042 out = &out;
9044 EXPECT(out == &out);
9046 out = &out;
9048 EXPECT(out == &out);
9050 out = &out;
9052 EXPECT(Dart_IsError(Dart_GetPeer(smi, &out)));
9053 EXPECT(out == &out);
9054 EXPECT(Dart_IsError(Dart_SetPeer(smi, &out)));
9055 out = &out;
9056 Dart_Handle big = Dart_NewIntegerFromHexCString("0x10000000000000000");
9057 EXPECT(Dart_IsApiError(big));
9058 out = &out;
9059 Dart_Handle dbl = Dart_NewDouble(0.0);
9060 EXPECT(Dart_IsError(Dart_GetPeer(dbl, &out)));
9061 EXPECT(out == &out);
9062 EXPECT(Dart_IsError(Dart_SetPeer(dbl, &out)));
9063}
9064
9065// Allocates an object in new space and assigns it a peer. Removes
9066// the peer and checks that the count of peer objects is decremented
9067// by one.
9068TEST_CASE(DartAPI_OneNewSpacePeer) {
9069 Heap* heap = IsolateGroup::Current()->heap();
9070 Dart_Handle str = NewString("a string");
9071 EXPECT_VALID(str);
9072 EXPECT(Dart_IsString(str));
9073 EXPECT_EQ(0, heap->PeerCount());
9074 void* out = &out;
9075 EXPECT_VALID(Dart_GetPeer(str, &out));
9076 EXPECT(out == nullptr);
9077 int peer = 1234;
9078 EXPECT_VALID(Dart_SetPeer(str, &peer));
9079 EXPECT_EQ(1, heap->PeerCount());
9080 out = &out;
9081 EXPECT_VALID(Dart_GetPeer(str, &out));
9082 EXPECT(out == reinterpret_cast<void*>(&peer));
9083 EXPECT_VALID(Dart_SetPeer(str, nullptr));
9084 out = &out;
9085 EXPECT_VALID(Dart_GetPeer(str, &out));
9086 EXPECT(out == nullptr);
9087 EXPECT_EQ(0, heap->PeerCount());
9088}
9089
9090// Allocates an object in new space and assigns it a peer. Allows the
9091// peer referent to be garbage collected and checks that the count of
9092// peer objects is decremented by one.
9093TEST_CASE(DartAPI_CollectOneNewSpacePeer) {
9094 Heap* heap = IsolateGroup::Current()->heap();
9096 {
9097 CHECK_API_SCOPE(thread);
9098 Dart_Handle str = NewString("a string");
9099 EXPECT_VALID(str);
9100 EXPECT(Dart_IsString(str));
9101 EXPECT_EQ(0, heap->PeerCount());
9102 void* out = &out;
9103 EXPECT_VALID(Dart_GetPeer(str, &out));
9104 EXPECT(out == nullptr);
9105 int peer = 1234;
9106 EXPECT_VALID(Dart_SetPeer(str, &peer));
9107 EXPECT_EQ(1, heap->PeerCount());
9108 out = &out;
9109 EXPECT_VALID(Dart_GetPeer(str, &out));
9110 EXPECT(out == reinterpret_cast<void*>(&peer));
9111 {
9112 TransitionNativeToVM transition(thread);
9113 GCTestHelper::CollectNewSpace();
9114 EXPECT_EQ(1, heap->PeerCount());
9115 }
9116 out = &out;
9117 EXPECT_VALID(Dart_GetPeer(str, &out));
9118 EXPECT(out == reinterpret_cast<void*>(&peer));
9119 }
9121 {
9122 TransitionNativeToVM transition(thread);
9123 GCTestHelper::CollectNewSpace();
9124 EXPECT_EQ(0, heap->PeerCount());
9125 }
9126}
9127
9128// Allocates two objects in new space and assigns them peers. Removes
9129// the peers and checks that the count of peer objects is decremented
9130// by two.
9131TEST_CASE(DartAPI_TwoNewSpacePeers) {
9132 Heap* heap = IsolateGroup::Current()->heap();
9133 Dart_Handle s1 = NewString("s1");
9134 EXPECT_VALID(s1);
9135 EXPECT(Dart_IsString(s1));
9136 void* o1 = &o1;
9137 EXPECT_VALID(Dart_GetPeer(s1, &o1));
9138 EXPECT(o1 == nullptr);
9139 EXPECT_EQ(0, heap->PeerCount());
9140 int p1 = 1234;
9141 EXPECT_VALID(Dart_SetPeer(s1, &p1));
9142 EXPECT_EQ(1, heap->PeerCount());
9143 EXPECT_VALID(Dart_GetPeer(s1, &o1));
9144 EXPECT(o1 == reinterpret_cast<void*>(&p1));
9145 Dart_Handle s2 = NewString("a string");
9146 EXPECT_VALID(s2);
9147 EXPECT(Dart_IsString(s2));
9148 EXPECT_EQ(1, heap->PeerCount());
9149 void* o2 = &o2;
9150 EXPECT(Dart_GetPeer(s2, &o2));
9151 EXPECT(o2 == nullptr);
9152 int p2 = 5678;
9153 EXPECT_VALID(Dart_SetPeer(s2, &p2));
9154 EXPECT_EQ(2, heap->PeerCount());
9155 EXPECT_VALID(Dart_GetPeer(s2, &o2));
9156 EXPECT(o2 == reinterpret_cast<void*>(&p2));
9158 EXPECT_EQ(1, heap->PeerCount());
9159 EXPECT(Dart_GetPeer(s1, &o1));
9160 EXPECT(o1 == nullptr);
9161 EXPECT_VALID(Dart_SetPeer(s2, nullptr));
9162 EXPECT_EQ(0, heap->PeerCount());
9163 EXPECT(Dart_GetPeer(s2, &o2));
9164 EXPECT(o2 == nullptr);
9165}
9166
9167// Allocates two objects in new space and assigns them a peer. Allow
9168// the peer referents to be garbage collected and check that the count
9169// of peer objects is decremented by two.
9170TEST_CASE(DartAPI_CollectTwoNewSpacePeers) {
9171 Heap* heap = IsolateGroup::Current()->heap();
9173 {
9174 CHECK_API_SCOPE(thread);
9175 Dart_Handle s1 = NewString("s1");
9176 EXPECT_VALID(s1);
9177 EXPECT(Dart_IsString(s1));
9178 EXPECT_EQ(0, heap->PeerCount());
9179 void* o1 = &o1;
9180 EXPECT(Dart_GetPeer(s1, &o1));
9181 EXPECT(o1 == nullptr);
9182 int p1 = 1234;
9183 EXPECT_VALID(Dart_SetPeer(s1, &p1));
9184 EXPECT_EQ(1, heap->PeerCount());
9185 EXPECT_VALID(Dart_GetPeer(s1, &o1));
9186 EXPECT(o1 == reinterpret_cast<void*>(&p1));
9187 Dart_Handle s2 = NewString("s2");
9188 EXPECT_VALID(s2);
9190 EXPECT_EQ(1, heap->PeerCount());
9191 void* o2 = &o2;
9192 EXPECT(Dart_GetPeer(s2, &o2));
9193 EXPECT(o2 == nullptr);
9194 int p2 = 5678;
9195 EXPECT_VALID(Dart_SetPeer(s2, &p2));
9196 EXPECT_EQ(2, heap->PeerCount());
9197 EXPECT_VALID(Dart_GetPeer(s2, &o2));
9198 EXPECT(o2 == reinterpret_cast<void*>(&p2));
9199 }
9201 {
9202 TransitionNativeToVM transition(thread);
9203 GCTestHelper::CollectNewSpace();
9204 EXPECT_EQ(0, heap->PeerCount());
9205 }
9206}
9207
9208// Allocates several objects in new space. Performs successive
9209// garbage collections and checks that the peer count is stable.
9210TEST_CASE(DartAPI_CopyNewSpacePeers) {
9211 const int kPeerCount = 10;
9212 Heap* heap = IsolateGroup::Current()->heap();
9213 Dart_Handle s[kPeerCount];
9214 for (int i = 0; i < kPeerCount; ++i) {
9215 s[i] = NewString("a string");
9216 EXPECT_VALID(s[i]);
9217 EXPECT(Dart_IsString(s[i]));
9218 void* o = &o;
9219 EXPECT_VALID(Dart_GetPeer(s[i], &o));
9220 EXPECT(o == nullptr);
9221 }
9222 EXPECT_EQ(0, heap->PeerCount());
9223 int p[kPeerCount];
9224 for (int i = 0; i < kPeerCount; ++i) {
9225 EXPECT_VALID(Dart_SetPeer(s[i], &p[i]));
9226 EXPECT_EQ(i + 1, heap->PeerCount());
9227 void* o = &o;
9228 EXPECT_VALID(Dart_GetPeer(s[i], &o));
9229 EXPECT(o == reinterpret_cast<void*>(&p[i]));
9230 }
9231 EXPECT_EQ(kPeerCount, heap->PeerCount());
9232 {
9233 TransitionNativeToVM transition(thread);
9234 GCTestHelper::CollectNewSpace();
9235 EXPECT_EQ(kPeerCount, heap->PeerCount());
9236 GCTestHelper::CollectNewSpace();
9237 EXPECT_EQ(kPeerCount, heap->PeerCount());
9238 }
9239}
9240
9241// Allocates an object in new space and assigns it a peer. Promotes
9242// the peer to old space. Removes the peer and check that the count
9243// of peer objects is decremented by one.
9244TEST_CASE(DartAPI_OnePromotedPeer) {
9245 Heap* heap = IsolateGroup::Current()->heap();
9246 Dart_Handle str = NewString("a string");
9247 EXPECT_VALID(str);
9248 EXPECT(Dart_IsString(str));
9249 EXPECT_EQ(0, heap->PeerCount());
9250 void* out = &out;
9251 EXPECT(Dart_GetPeer(str, &out));
9252 EXPECT(out == nullptr);
9253 int peer = 1234;
9254 EXPECT_VALID(Dart_SetPeer(str, &peer));
9255 out = &out;
9256 EXPECT(Dart_GetPeer(str, &out));
9257 EXPECT(out == reinterpret_cast<void*>(&peer));
9258 EXPECT_EQ(1, heap->PeerCount());
9259 {
9260 TransitionNativeToVM transition(thread);
9261 GCTestHelper::CollectNewSpace();
9262 GCTestHelper::CollectNewSpace();
9263 }
9264 {
9265 CHECK_API_SCOPE(thread);
9266 TransitionNativeToVM transition(thread);
9267 HANDLESCOPE(thread);
9268 String& handle = String::Handle();
9269 handle ^= Api::UnwrapHandle(str);
9270 EXPECT(handle.IsOld());
9271 }
9272 EXPECT_VALID(Dart_GetPeer(str, &out));
9273 EXPECT(out == reinterpret_cast<void*>(&peer));
9274 EXPECT_EQ(1, heap->PeerCount());
9275 EXPECT_VALID(Dart_SetPeer(str, nullptr));
9276 out = &out;
9277 EXPECT_VALID(Dart_GetPeer(str, &out));
9278 EXPECT(out == nullptr);
9279 EXPECT_EQ(0, heap->PeerCount());
9280}
9281
9282// Allocates an object in old space and assigns it a peer. Removes
9283// the peer and checks that the count of peer objects is decremented
9284// by one.
9285TEST_CASE(DartAPI_OneOldSpacePeer) {
9286 Heap* heap = IsolateGroup::Current()->heap();
9287 Dart_Handle str = AllocateOldString("str");
9288 EXPECT_VALID(str);
9289 EXPECT(Dart_IsString(str));
9290 EXPECT_EQ(0, heap->PeerCount());
9291 void* out = &out;
9292 EXPECT(Dart_GetPeer(str, &out));
9293 EXPECT(out == nullptr);
9294 int peer = 1234;
9295 EXPECT_VALID(Dart_SetPeer(str, &peer));
9296 EXPECT_EQ(1, heap->PeerCount());
9297 out = &out;
9298 EXPECT_VALID(Dart_GetPeer(str, &out));
9299 EXPECT(out == reinterpret_cast<void*>(&peer));
9300 {
9301 TransitionNativeToVM transition(thread);
9302 GCTestHelper::CollectOldSpace();
9303 EXPECT_EQ(1, heap->PeerCount());
9304 }
9305 EXPECT_VALID(Dart_GetPeer(str, &out));
9306 EXPECT(out == reinterpret_cast<void*>(&peer));
9307 EXPECT_VALID(Dart_SetPeer(str, nullptr));
9308 out = &out;
9309 EXPECT_VALID(Dart_GetPeer(str, &out));
9310 EXPECT(out == nullptr);
9311 EXPECT_EQ(0, heap->PeerCount());
9312}
9313
9314// Allocates an object in old space and assigns it a peer. Allow the
9315// peer referent to be garbage collected and check that the count of
9316// peer objects is decremented by one.
9317TEST_CASE(DartAPI_CollectOneOldSpacePeer) {
9318 Heap* heap = IsolateGroup::Current()->heap();
9320 {
9321 Thread* T = Thread::Current();
9323 Dart_Handle str = AllocateOldString("str");
9324 EXPECT_VALID(str);
9325 EXPECT(Dart_IsString(str));
9326 EXPECT_EQ(0, heap->PeerCount());
9327 void* out = &out;
9328 EXPECT(Dart_GetPeer(str, &out));
9329 EXPECT(out == nullptr);
9330 int peer = 1234;
9331 EXPECT_VALID(Dart_SetPeer(str, &peer));
9332 EXPECT_EQ(1, heap->PeerCount());
9333 out = &out;
9334 EXPECT_VALID(Dart_GetPeer(str, &out));
9335 EXPECT(out == reinterpret_cast<void*>(&peer));
9336 {
9337 TransitionNativeToVM transition(thread);
9338 GCTestHelper::CollectOldSpace();
9339 EXPECT_EQ(1, heap->PeerCount());
9340 }
9341 EXPECT_VALID(Dart_GetPeer(str, &out));
9342 EXPECT(out == reinterpret_cast<void*>(&peer));
9343 }
9345 {
9346 TransitionNativeToVM transition(thread);
9347 GCTestHelper::CollectOldSpace();
9348 EXPECT_EQ(0, heap->PeerCount());
9349 }
9350}
9351
9352// Allocates two objects in old space and assigns them peers. Removes
9353// the peers and checks that the count of peer objects is decremented
9354// by two.
9355TEST_CASE(DartAPI_TwoOldSpacePeers) {
9356 Heap* heap = IsolateGroup::Current()->heap();
9357 Dart_Handle s1 = AllocateOldString("s1");
9358 EXPECT_VALID(s1);
9359 EXPECT(Dart_IsString(s1));
9360 EXPECT_EQ(0, heap->PeerCount());
9361 void* o1 = &o1;
9362 EXPECT(Dart_GetPeer(s1, &o1));
9363 EXPECT(o1 == nullptr);
9364 int p1 = 1234;
9365 EXPECT_VALID(Dart_SetPeer(s1, &p1));
9366 EXPECT_EQ(1, heap->PeerCount());
9367 o1 = &o1;
9368 EXPECT_VALID(Dart_GetPeer(s1, &o1));
9369 EXPECT(o1 == reinterpret_cast<void*>(&p1));
9370 Dart_Handle s2 = AllocateOldString("s2");
9371 EXPECT_VALID(s2);
9372 EXPECT(Dart_IsString(s2));
9373 EXPECT_EQ(1, heap->PeerCount());
9374 void* o2 = &o2;
9375 EXPECT(Dart_GetPeer(s2, &o2));
9376 EXPECT(o2 == nullptr);
9377 int p2 = 5678;
9378 EXPECT_VALID(Dart_SetPeer(s2, &p2));
9379 EXPECT_EQ(2, heap->PeerCount());
9380 o2 = &o2;
9381 EXPECT_VALID(Dart_GetPeer(s2, &o2));
9382 EXPECT(o2 == reinterpret_cast<void*>(&p2));
9383 EXPECT_VALID(Dart_SetPeer(s1, nullptr));
9384 EXPECT_EQ(1, heap->PeerCount());
9385 o1 = &o1;
9386 EXPECT(Dart_GetPeer(s1, &o1));
9387 EXPECT(o1 == nullptr);
9388 EXPECT_VALID(Dart_SetPeer(s2, nullptr));
9389 EXPECT_EQ(0, heap->PeerCount());
9390 o2 = &o2;
9391 EXPECT_VALID(Dart_GetPeer(s2, &o2));
9392 EXPECT(o2 == nullptr);
9393}
9394
9395// Allocates two objects in old space and assigns them a peer. Allows
9396// the peer referents to be garbage collected and checks that the
9397// count of peer objects is decremented by two.
9398TEST_CASE(DartAPI_CollectTwoOldSpacePeers) {
9399 Heap* heap = IsolateGroup::Current()->heap();
9401 {
9402 Thread* T = Thread::Current();
9404 Dart_Handle s1 = AllocateOldString("s1");
9405 EXPECT_VALID(s1);
9406 EXPECT(Dart_IsString(s1));
9407 EXPECT_EQ(0, heap->PeerCount());
9408 void* o1 = &o1;
9409 EXPECT(Dart_GetPeer(s1, &o1));
9410 EXPECT(o1 == nullptr);
9411 int p1 = 1234;
9412 EXPECT_VALID(Dart_SetPeer(s1, &p1));
9413 EXPECT_EQ(1, heap->PeerCount());
9414 o1 = &o1;
9415 EXPECT_VALID(Dart_GetPeer(s1, &o1));
9416 EXPECT(o1 == reinterpret_cast<void*>(&p1));
9417 Dart_Handle s2 = AllocateOldString("s2");
9418 EXPECT_VALID(s2);
9419 EXPECT(Dart_IsString(s2));
9420 EXPECT_EQ(1, heap->PeerCount());
9421 void* o2 = &o2;
9422 EXPECT(Dart_GetPeer(s2, &o2));
9423 EXPECT(o2 == nullptr);
9424 int p2 = 5678;
9425 EXPECT_VALID(Dart_SetPeer(s2, &p2));
9426 EXPECT_EQ(2, heap->PeerCount());
9427 o2 = &o2;
9428 EXPECT_VALID(Dart_GetPeer(s2, &o2));
9429 EXPECT(o2 == reinterpret_cast<void*>(&p2));
9430 }
9432 {
9433 TransitionNativeToVM transition(thread);
9434 GCTestHelper::CollectOldSpace();
9435 EXPECT_EQ(0, heap->PeerCount());
9436 }
9437}
9438
9439TEST_CASE(DartAPI_StringFromExternalTypedData) {
9440 const char* kScriptChars =
9441 "test(external) {\n"
9442 " var str1 = new String.fromCharCodes(external);\n"
9443 " var str2 = new String.fromCharCodes(new List.from(external));\n"
9444 " if (str2 != str1) throw 'FAIL';\n"
9445 " return str1;\n"
9446 "}\n"
9447 "testView8(external) {\n"
9448 " return test(external.buffer.asUint8List());\n"
9449 "}\n"
9450 "testView16(external) {\n"
9451 " return test(external.buffer.asUint16List());\n"
9452 "}\n";
9453 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
9454
9455 {
9456 uint8_t data[64];
9457 for (int i = 0; i < 64; i++) {
9458 data[i] = i * 4;
9459 }
9460 // LATIN-1 in external Uint8List.
9461 Dart_Handle external =
9463 EXPECT_VALID(external);
9464 Dart_Handle dart_args[1];
9465 dart_args[0] = external;
9466 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 1, dart_args);
9469
9470 result = Dart_Invoke(lib, NewString("testView8"), 1, dart_args);
9473 }
9474
9475 {
9476 uint16_t data[64];
9477 for (int i = 0; i < 64; i++) {
9478 data[i] = i * 4;
9479 }
9480 // LATIN-1 in external Uint16List.
9481 Dart_Handle external =
9483 EXPECT_VALID(external);
9484 Dart_Handle dart_args[1];
9485 dart_args[0] = external;
9486 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 1, dart_args);
9489
9490 result = Dart_Invoke(lib, NewString("testView16"), 1, dart_args);
9493 }
9494
9495 {
9496 uint16_t data[64];
9497 for (int i = 0; i < 64; i++) {
9498 data[i] = 0x2000 + i * 4;
9499 }
9500 // Non-LATIN-1 in external Uint16List.
9501 Dart_Handle external =
9503 EXPECT_VALID(external);
9504 Dart_Handle dart_args[1];
9505 dart_args[0] = external;
9506 Dart_Handle result = Dart_Invoke(lib, NewString("test"), 1, dart_args);
9509
9510 result = Dart_Invoke(lib, NewString("testView16"), 1, dart_args);
9513 }
9514}
9515
9516#ifndef PRODUCT
9517
9518TEST_CASE(DartAPI_TimelineDuration) {
9519 Isolate* isolate = Isolate::Current();
9520 // Grab embedder stream.
9521 TimelineStream* stream = Timeline::GetEmbedderStream();
9522 // Make sure it is enabled.
9523 stream->set_enabled(true);
9524 // Add a duration event.
9525 Dart_RecordTimelineEvent("testDurationEvent", 500, 1500, 0, nullptr,
9526 Dart_Timeline_Event_Duration, 0, nullptr, nullptr);
9527 // Check that it is in the output.
9528 TimelineEventRecorder* recorder = Timeline::recorder();
9529 JSONStream js;
9530 IsolateTimelineEventFilter filter(isolate->main_port());
9531 recorder->PrintJSON(&js, &filter);
9532 const char* json = js.ToCString();
9533 EXPECT_SUBSTRING("\"name\":\"testDurationEvent\"", json);
9534 EXPECT_SUBSTRING("\"ph\":\"X\"", json);
9535 EXPECT_SUBSTRING("\"ts\":500", json);
9536 EXPECT_SUBSTRING("\"dur\":1000", json);
9537}
9538
9539TEST_CASE(DartAPI_TimelineBegin) {
9540 Isolate* isolate = Isolate::Current();
9541 // Grab embedder stream.
9542 TimelineStream* stream = Timeline::GetEmbedderStream();
9543 // Make sure it is enabled.
9544 stream->set_enabled(true);
9545 // Add a begin event.
9546 Dart_RecordTimelineEvent("testBeginEvent", 1000, 1, 0, nullptr,
9547 Dart_Timeline_Event_Begin, 0, nullptr, nullptr);
9548 // Check that it is in the output.
9549 TimelineEventRecorder* recorder = Timeline::recorder();
9550 JSONStream js;
9551 IsolateTimelineEventFilter filter(isolate->main_port());
9552 recorder->PrintJSON(&js, &filter);
9553 const char* json = js.ToCString();
9554 EXPECT_SUBSTRING("\"name\":\"testBeginEvent\"", json);
9555 EXPECT_SUBSTRING("\"ph\":\"B\"", json);
9556 EXPECT_SUBSTRING("\"ts\":1000", json);
9557}
9558
9559TEST_CASE(DartAPI_TimelineEnd) {
9560 Isolate* isolate = Isolate::Current();
9561 // Grab embedder stream.
9562 TimelineStream* stream = Timeline::GetEmbedderStream();
9563 // Make sure it is enabled.
9564 stream->set_enabled(true);
9565 // Add a begin event.
9566 Dart_RecordTimelineEvent("testEndEvent", 1000, 1, 0, nullptr,
9567 Dart_Timeline_Event_End, 0, nullptr, nullptr);
9568 // Check that it is in the output.
9569 TimelineEventRecorder* recorder = Timeline::recorder();
9570 JSONStream js;
9571 IsolateTimelineEventFilter filter(isolate->main_port());
9572 recorder->PrintJSON(&js, &filter);
9573 const char* json = js.ToCString();
9574 EXPECT_SUBSTRING("\"name\":\"testEndEvent\"", json);
9575 EXPECT_SUBSTRING("\"ph\":\"E\"", json);
9576 EXPECT_SUBSTRING("\"ts\":1000", json);
9577}
9578
9579TEST_CASE(DartAPI_TimelineInstant) {
9580 Isolate* isolate = Isolate::Current();
9581 // Grab embedder stream.
9582 TimelineStream* stream = Timeline::GetEmbedderStream();
9583 // Make sure it is enabled.
9584 stream->set_enabled(true);
9585 Dart_RecordTimelineEvent("testInstantEvent", 1000, 1, 0, nullptr,
9586 Dart_Timeline_Event_Instant, 0, nullptr, nullptr);
9587 // Check that it is in the output.
9588 TimelineEventRecorder* recorder = Timeline::recorder();
9590 IsolateTimelineEventFilter filter(isolate->main_port());
9591 recorder->PrintJSON(&js, &filter);
9592 const char* json = js.ToCString();
9593 EXPECT_SUBSTRING("\"name\":\"testInstantEvent\"", json);
9594 EXPECT_SUBSTRING("\"ph\":\"i\"", json);
9595 EXPECT_SUBSTRING("\"ts\":1000", json);
9596}
9597
9598TEST_CASE(DartAPI_TimelineAsyncDisabled) {
9599 // Grab embedder stream.
9600 TimelineStream* stream = Timeline::GetEmbedderStream();
9601 // Make sure it is disabled.
9602 stream->set_enabled(false);
9603 int64_t async_id = 99;
9604 Dart_RecordTimelineEvent("testAsyncEvent", 0, async_id, 0, nullptr,
9606 nullptr);
9607 // Check that testAsync is not in the output.
9608 TimelineEventRecorder* recorder = Timeline::recorder();
9609 JSONStream js;
9610 TimelineEventFilter filter;
9611 recorder->PrintJSON(&js, &filter);
9612 EXPECT_NOTSUBSTRING("testAsyncEvent", js.ToCString());
9613}
9614
9615TEST_CASE(DartAPI_TimelineAsync) {
9616 Isolate* isolate = Isolate::Current();
9617 // Grab embedder stream.
9618 TimelineStream* stream = Timeline::GetEmbedderStream();
9619 // Make sure it is enabled.
9620 stream->set_enabled(true);
9621 int64_t async_id = 99;
9622 Dart_RecordTimelineEvent("testAsyncEvent", 1000, async_id, 0, nullptr,
9624 nullptr);
9625
9626 // Check that it is in the output.
9627 TimelineEventRecorder* recorder = Timeline::recorder();
9628 JSONStream js;
9629 IsolateTimelineEventFilter filter(isolate->main_port());
9630 recorder->PrintJSON(&js, &filter);
9631 const char* json = js.ToCString();
9632 EXPECT_SUBSTRING("\"name\":\"testAsyncEvent\"", json);
9633 EXPECT_SUBSTRING("\"ph\":\"b\"", json);
9634 EXPECT_SUBSTRING("\"ts\":1000", json);
9635 EXPECT_SUBSTRING("\"id\":\"63\"", json); // Hex for some reason.
9636}
9637
9638#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
9639TEST_CASE(DartAPI_TimelineAsyncInstantRace) {
9640 struct ReportAsyncEventArguments {
9641 Monitor& synchronization_monitor;
9642 ThreadJoinId join_id = OSThread::kInvalidThreadJoinId;
9643 };
9644
9645 Monitor synchronization_monitor;
9646 ReportAsyncEventArguments report_async_event_1_arguments{
9647 synchronization_monitor};
9648 ReportAsyncEventArguments report_async_event_2_arguments{
9649 synchronization_monitor};
9650 TimelineEventRecorder& recorder = *Timeline::recorder();
9651 JSONStream js;
9652 TimelineEventFilter filter;
9653
9654 // Grab embedder stream.
9655 TimelineStream* stream = Timeline::GetEmbedderStream();
9656 // Make sure it is enabled.
9657 stream->set_enabled(true);
9658 // Try concurrently writing async events and reading from the async track
9659 // metadata map. It is not possible to assert anything about the outcome,
9660 // because of scheduling uncertainty. This test is just used to ensure that
9661 // TSAN checks the async track metadata map code.
9663 "ReportAsyncEvent1",
9664 [](uword arguments_ptr) {
9665 ReportAsyncEventArguments& arguments =
9666 *reinterpret_cast<ReportAsyncEventArguments*>(arguments_ptr);
9667 Dart_RecordTimelineEvent("async1", /*timestamp0=*/0, /*async_id=*/1, 0,
9669 /*argument_count=*/0, nullptr, nullptr);
9670 MonitorLocker ml(&arguments.synchronization_monitor);
9671 arguments.join_id =
9673 ml.Notify();
9674 },
9675 reinterpret_cast<uword>(&report_async_event_1_arguments));
9677 "ReportAsyncEvent2",
9678 [](uword arguments_ptr) {
9679 ReportAsyncEventArguments& arguments =
9680 *reinterpret_cast<ReportAsyncEventArguments*>(arguments_ptr);
9681 Dart_RecordTimelineEvent("async2", /*timestamp0=*/0, /*async_id=*/2, 0,
9683 /*argument_count=*/0, nullptr, nullptr);
9684 MonitorLocker ml(&arguments.synchronization_monitor);
9685 arguments.join_id =
9687 ml.Notify();
9688 },
9689 reinterpret_cast<uword>(&report_async_event_2_arguments));
9690 recorder.PrintPerfettoTimeline(&js, filter);
9691
9692 MonitorLocker ml(&synchronization_monitor);
9693 while (report_async_event_1_arguments.join_id ==
9695 report_async_event_2_arguments.join_id ==
9697 ml.Wait();
9699 OSThread::Join(report_async_event_1_arguments.join_id);
9700 OSThread::Join(report_async_event_2_arguments.join_id);
9701}
9702#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT)
9703
9704TEST_CASE(DartAPI_TimelineClock) {
9705 int64_t micros1 = Dart_TimelineGetMicros();
9706 int64_t ticks1 = Dart_TimelineGetTicks();
9707 int64_t frequency1 = Dart_TimelineGetTicksFrequency();
9708 OS::Sleep(1);
9709 int64_t micros2 = Dart_TimelineGetMicros();
9710 int64_t ticks2 = Dart_TimelineGetTicks();
9711 int64_t frequency2 = Dart_TimelineGetTicksFrequency();
9712 EXPECT_NE(micros1, micros2);
9713 EXPECT_NE(ticks1, ticks2);
9714 EXPECT_EQ(frequency1, frequency2);
9715}
9716
9717TEST_CASE(DartAPI_TimelineCategories) {
9718 bool result;
9719 {
9721 EXPECT_EQ(true, result);
9722 JSONStream js;
9723 JSONObject obj(&js);
9724 JSONArray jstream(&obj, "available");
9725 Timeline::PrintFlagsToJSONArray(&jstream);
9726 const char* js_str = js.ToCString();
9727#define TIMELINE_STREAM_CHECK(name, ...) EXPECT_SUBSTRING(#name, js_str);
9728 TIMELINE_STREAM_LIST(TIMELINE_STREAM_CHECK)
9729#undef TIMELINE_STREAM_CHECK
9730 }
9734 EXPECT_EQ(false, result);
9736 EXPECT_EQ(false, result);
9737 }
9738
9739 {
9740 result = Dart_SetEnabledTimelineCategory("GC,API,Compiler");
9741 EXPECT_EQ(true, result);
9743 JSONObject obj(&js);
9744 JSONArray jstream(&obj, "available");
9745 Timeline::PrintFlagsToJSONArray(&jstream);
9746 const char* js_str = js.ToCString();
9747 EXPECT_SUBSTRING("GC", js_str);
9748 EXPECT_SUBSTRING("API", js_str);
9749 EXPECT_SUBSTRING("Compiler", js_str);
9750 EXPECT_NOTSUBSTRING("CompilerVerbose", js_str);
9751 EXPECT_NOTSUBSTRING("Debugger", js_str);
9752 EXPECT_NOTSUBSTRING("Embedder", js_str);
9753 EXPECT_NOTSUBSTRING("Isolate", js_str);
9754 EXPECT_NOTSUBSTRING("VM", js_str);
9755 }
9756
9757 {
9759 EXPECT_EQ(true, result);
9760 JSONStream js;
9761 JSONObject obj(&js);
9762 JSONArray jstream(&obj, "available");
9763 Timeline::PrintFlagsToJSONArray(&jstream);
9764 const char* js_str = js.ToCString();
9765 EXPECT_NOTSUBSTRING("GC", js_str);
9766 EXPECT_NOTSUBSTRING("API", js_str);
9767 EXPECT_NOTSUBSTRING("Compiler", js_str);
9768 EXPECT_NOTSUBSTRING("CompilerVerbose", js_str);
9769 EXPECT_NOTSUBSTRING("Debugger", js_str);
9770 EXPECT_NOTSUBSTRING("Embedder", js_str);
9771 EXPECT_SUBSTRING("Isolate", js_str);
9772 EXPECT_NOTSUBSTRING("VM", js_str);
9773 }
9774
9775 {
9777 EXPECT_EQ(true, result);
9778 JSONStream js;
9779 JSONObject obj(&js);
9780 JSONArray jstream(&obj, "available");
9781 Timeline::PrintFlagsToJSONArray(&jstream);
9782 const char* js_str = js.ToCString();
9783 EXPECT_NOTSUBSTRING("GC", js_str);
9784 EXPECT_NOTSUBSTRING("API", js_str);
9785 EXPECT_NOTSUBSTRING("Compiler", js_str);
9786 EXPECT_NOTSUBSTRING("CompilerVerbose", js_str);
9787 EXPECT_NOTSUBSTRING("Debugger", js_str);
9788 EXPECT_NOTSUBSTRING("Embedder", js_str);
9789 EXPECT_NOTSUBSTRING("Isolate", js_str);
9790 EXPECT_NOTSUBSTRING("VM", js_str);
9791 }
9792}
9793
9796}
9797
9800 int argument_count,
9801 bool* auto_setup_scope) {
9802 return NotifyIdleShortNative;
9803}
9804
9805TEST_CASE(DartAPI_NotifyIdleShort) {
9806 const char* kScriptChars = R"(
9807@pragma("vm:external-name", "Test_nativeFunc")
9808external void notifyIdle();
9809void main() {
9810 var v;
9811 for (var i = 0; i < 100; i++) {
9812 var t = [];
9813 for (var j = 0; j < 10000; j++) {
9814 t.add(List.filled(100, null));
9815 }
9816 v = t;
9817 notifyIdle();
9818 }
9819})";
9820 Dart_Handle lib =
9822 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
9824}
9825
9828}
9829
9832 int argument_count,
9833 bool* auto_setup_scope) {
9834 return NotifyIdleLongNative;
9835}
9836
9837TEST_CASE(DartAPI_NotifyIdleLong) {
9838 const char* kScriptChars = R"(
9839@pragma("vm:external-name", "Test_nativeFunc")
9840external void notifyIdle();
9841void main() {
9842 var v;
9843 for (var i = 0; i < 100; i++) {
9844 var t = [];
9845 for (var j = 0; j < 10000; j++) {
9846 t.add(List.filled(100, null));
9847 }
9848 v = t;
9849 notifyIdle();
9850 }
9851}
9852)";
9853 Dart_Handle lib =
9855 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
9857}
9858
9861}
9862
9865 int argument_count,
9866 bool* auto_setup_scope) {
9867 return NotifyDestroyedNative;
9869
9870TEST_CASE(DartAPI_NotifyDestroyed) {
9871 const char* kScriptChars = R"(
9872import 'dart:isolate';
9873@pragma("vm:external-name", "Test_nativeFunc")
9874external void notifyDetach();
9875void main() {
9876 var v;
9877 for (var i = 0; i < 100; i++) {
9878 var t = [];
9879 for (var j = 0; j < 10000; j++) {
9880 t.add(List.filled(100, null));
9881 }
9882 v = t;
9883 notifyDetach();
9884 }
9885})";
9886 Dart_Handle lib =
9888 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
9890}
9891
9894}
9897}
9901 bool* auto_setup_scope) {
9902 const char* cstr = nullptr;
9904 if (strcmp(cstr, "SetPerformanceModeDefault") == 0) {
9906 } else if (strcmp(cstr, "SetPerformanceModeLatency") == 0) {
9908 }
9909 return nullptr;
9910}
9911
9912TEST_CASE(DartAPI_SetPerformanceMode) {
9913 const char* kScriptChars = R"(
9914import "dart:typed_data";
9915@pragma("vm:external-name", "SetPerformanceModeDefault")
9916external void setPerformanceModeDefault();
9917@pragma("vm:external-name", "SetPerformanceModeLatency")
9918external void setPerformanceModeLatency();
9919void main() {
9920 for (var i = 0; i < 10; i++) {
9921 setPerformanceModeLatency();
9922 var t = [];
9923 for (var j = 0; j < 32; j++) {
9924 t.add(Uint8List(1000000));
9925 }
9926 setPerformanceModeDefault();
9927 }
9928}
9929)";
9930 Dart_Handle lib =
9932 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
9942 int argument_count,
9943 bool* auto_setup_scope) {
9945}
9946
9947TEST_CASE(DartAPI_NotifyLowMemory) {
9948 const char* kScriptChars = R"(
9949import 'dart:isolate';
9950@pragma("vm:external-name", "Test_nativeFunc")
9951external void notifyLowMemory();
9952void main() {
9953 var v;
9954 for (var i = 0; i < 100; i++) {
9955 var t = [];
9956 for (var j = 0; j < 10000; j++) {
9957 t.add(List.filled(100, null));
9958 }
9959 v = t;
9960 notifyLowMemory();
9961 }
9962})";
9963 Dart_Handle lib =
9965 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
9967}
9968
9969// There exists another test by name DartAPI_Invoke_CrossLibrary.
9970// However, that currently fails for the dartk configuration as it
9971// uses Dart_LoadLibrary. This test here effectively tests the same
9972// functionality but invokes a function from an imported standard
9973// library.
9974TEST_CASE(DartAPI_InvokeImportedFunction) {
9975 const char* kScriptChars =
9976 "import 'dart:math';\n"
9977 "import 'dart:developer';\n"
9978 "main() {}";
9979 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
9980 EXPECT_VALID(lib);
9981
9983
9987 "NoSuchMethodError: No top-level method 'max' declared.");
9988
9989 Dart_Handle getCurrentTag = Dart_NewStringFromCString("getCurrentTag");
9990 result = Dart_Invoke(lib, getCurrentTag, 0, nullptr);
9992 result,
9993 "NoSuchMethodError: No top-level method 'getCurrentTag' declared.");
9994}
9995
9996TEST_CASE(DartAPI_InvokeVMServiceMethod) {
9997 char buffer[1024];
9998 Utils::SNPrint(buffer, sizeof(buffer),
9999 R"({
10000 "jsonrpc": 2.0,
10001 "id": "foo",
10002 "method": "getVM",
10003 "params": { }
10004 })");
10005 uint8_t* response_json = nullptr;
10006 intptr_t response_json_length = 0;
10007 char* error = nullptr;
10008 const bool success = Dart_InvokeVMServiceMethod(
10009 reinterpret_cast<uint8_t*>(buffer), strlen(buffer), &response_json,
10010 &response_json_length, &error);
10011 EXPECT(success);
10012 EXPECT(error == nullptr);
10013
10015 Dart_TypedData_kUint8, response_json, response_json_length, response_json,
10016 response_json_length, [](void* ignored, void* peer) { free(peer); });
10017 EXPECT_VALID(bytes);
10018
10019 // We don't have a C++ JSON decoder so we'll invoke dart to validate the
10020 // result.
10021 const char* kScript =
10022 R"(
10023 import 'dart:convert';
10024 import 'dart:typed_data';
10025 bool validate(bool condition) {
10026 if (!condition) {
10027 throw 'Failed to validate InvokeVMServiceMethod() response.';
10028 }
10029 return false;
10030 }
10031 bool validateResult(Uint8List bytes) {
10032 final map = json.decode(utf8.decode(bytes));
10033 validate(map['jsonrpc'] == '2.0');
10034 validate(map['id'] == 'foo');
10035 validate(map['result']['name'] == 'vm');
10036 validate(map['result']['type'] == 'VM');
10037 validate(map['result'].containsKey('architectureBits'));
10038 validate(map['result'].containsKey('pid'));
10039 validate(map['result'].containsKey('startTime'));
10040 validate(map['result'].containsKey('hostCPU'));
10041 validate(map['result'].containsKey('targetCPU'));
10042 validate(map['result'].containsKey('version'));
10043 return true;
10044 }
10045 )";
10046
10047 Dart_Handle lib = TestCase::LoadTestScript(kScript, nullptr);
10048 EXPECT_VALID(lib);
10049 Dart_Handle result = Dart_Invoke(lib, NewString("validateResult"), 1, &bytes);
10051 EXPECT(result == Dart_True());
10052}
10053
10054static Monitor* loop_test_lock = new Monitor();
10055static bool loop_test_exit = false;
10056static bool loop_reset_count = false;
10057
10058#if !defined(PRODUCT)
10059static void InvokeServiceMessages(uword param) {
10060 char buffer[1024];
10062 R"({
10063 "jsonrpc": 2.0,
10064 "id": "foo",
10065 "method": "getVM",
10066 "params": { }
10067 })");
10068 uint8_t* response_json = nullptr;
10069 intptr_t response_json_length = 0;
10070 char* error = nullptr;
10071 uint32_t count = 0;
10072 do {
10073 error = nullptr;
10074 response_json = nullptr;
10075 response_json_length = 0;
10076 const bool success = Dart_InvokeVMServiceMethod(
10077 reinterpret_cast<uint8_t*>(buffer), strlen(buffer), &response_json,
10078 &response_json_length, &error);
10079 if (success) {
10081 EXPECT(error == nullptr);
10082 free(response_json);
10083 if (count == 10) {
10084 loop_test_exit = true;
10085 ml.Notify();
10086 }
10087 count++;
10088 } else {
10089 free(error);
10090 }
10091 } while (count < 100);
10092}
10093
10094TEST_CASE(DartAPI_InvokeVMServiceMethod_Loop) {
10095 MonitorLocker ml(loop_test_lock);
10096 loop_test_exit = false;
10097 loop_reset_count = false;
10098 OSThread::Start("InvokeServiceMessages", InvokeServiceMessages, 0);
10099 while (!loop_test_exit) {
10100 ml.Wait();
10101 }
10102}
10103#endif // !defined(PRODUCT)
10104
10105static void HandleResponse(Dart_Port dest_port_id, Dart_CObject* message) {
10106 printf("Response received\n");
10107}
10108
10109static void CreateNativePorts(uword param) {
10110 uint32_t count = 0;
10111 do {
10112 const Dart_Port port_id = Dart_NewNativePort("tst", &HandleResponse, false);
10113 if (port_id != ILLEGAL_PORT) {
10114 Dart_CloseNativePort(port_id);
10116 if (count == 10) {
10117 loop_test_exit = true;
10118 ml.Notify();
10119 }
10121 }
10122 } while (count < 100);
10123}
10124
10125TEST_CASE(DartAPI_NativePort_Loop) {
10127 loop_test_exit = false;
10128 loop_reset_count = false;
10129 OSThread::Start("NativePort", CreateNativePorts, 0);
10130 while (!loop_test_exit) {
10131 ml.Wait();
10132 }
10133}
10134
10135#if !defined(PRODUCT)
10136static void ReportTimelineEvents() {
10137 intptr_t flow_id_count = 1;
10138 const int64_t flow_ids[1] = {123};
10139
10140 Dart_RecordTimelineEvent("T1", 0, 1, /*flow_id_count=*/0, nullptr,
10141 Dart_Timeline_Event_Begin, 0, nullptr, nullptr);
10142 Dart_RecordTimelineEvent("T1", 10, 1, /*flow_id_count=*/0, nullptr,
10143 Dart_Timeline_Event_End, /*argument_count=*/0,
10144 nullptr, nullptr);
10145
10146 Dart_RecordTimelineEvent("T2", 20, 2, /*flow_id_count=*/0, nullptr,
10147 Dart_Timeline_Event_Instant, /*argument_count=*/0,
10148 nullptr, nullptr);
10149
10150 Dart_RecordTimelineEvent("T3", 30, /*timestamp1=*/40, /*flow_id_count=*/0,
10152 /*argument_count=*/0, nullptr, nullptr);
10153
10154 Dart_RecordTimelineEvent("T4", 50, 4, /*flow_id_count=*/0, nullptr,
10156 /*argument_count=*/0, nullptr, nullptr);
10157 Dart_RecordTimelineEvent("T4", 60, 4, /*flow_id_count=*/0, nullptr,
10158 Dart_Timeline_Event_Async_End, /*argument_count=*/0,
10159 nullptr, nullptr);
10160
10161 Dart_RecordTimelineEvent("T5", 70, 5, /*flow_id_count=*/0, nullptr,
10163 /*argument_count=*/0, nullptr, nullptr);
10164
10165 Dart_RecordTimelineEvent("T6", 80, -1, /*flow_id_count=*/0, nullptr,
10166 Dart_Timeline_Event_Counter, /*argument_count=*/0,
10167 nullptr, nullptr);
10168
10169 Dart_RecordTimelineEvent("T7", 90, 7, flow_id_count, flow_ids,
10170 Dart_Timeline_Event_Begin, /*argument_count=*/0,
10171 nullptr, nullptr);
10172 Dart_RecordTimelineEvent("F", 90, 10, /*flow_id_count=*/0, nullptr,
10174 /*argument_count=*/0, nullptr, nullptr);
10175 Dart_RecordTimelineEvent("T7", 100, 7, /*flow_id_count=*/0, nullptr,
10176 Dart_Timeline_Event_End, /*argument_count=*/0,
10177 nullptr, nullptr);
10178
10179 Dart_RecordTimelineEvent("T8", 110, 8, flow_id_count, flow_ids,
10180 Dart_Timeline_Event_Begin, 0, nullptr, nullptr);
10181 Dart_RecordTimelineEvent("F", 110, 10, /*flow_id_count=*/0, nullptr,
10183 /*argument_count=*/0, nullptr, nullptr);
10184 Dart_RecordTimelineEvent("T8", 120, 8, /*flow_id_count=*/0, nullptr,
10185 Dart_Timeline_Event_End, /*argument_count=*/0,
10186 nullptr, nullptr);
10187
10188 Dart_RecordTimelineEvent("T9", 130, 9, flow_id_count, flow_ids,
10189 Dart_Timeline_Event_Begin, /*argument_count=*/0,
10190 nullptr, nullptr);
10191 Dart_RecordTimelineEvent("F", 130, 10, /*flow_id_count=*/0, nullptr,
10193 /*argument_count=*/0, nullptr, nullptr);
10194 Dart_RecordTimelineEvent("T9", 140, 9, /*flow_id_count=*/0, nullptr,
10195 Dart_Timeline_Event_End, /*argument_count=*/0,
10196 nullptr, nullptr);
10197}
10198
10199TEST_CASE(DartAPI_TimelineEvents_Serialization) {
10200 // We do not check the contents of the JSON output here because we have
10201 // pkg/vm_service/test/get_perfetto_vm_timeline_rpc_test.dart and
10202 // runtime/observatory/tests/get_vm_timeline_rpc_test.dart for that. This test
10203 // is used to ensure that assertions in timeline code are checked by debug
10204 // tryjobs, and that the sanitizers run on the timeline code.
10205
10206 // Grab embedder stream.
10207 TimelineStream* stream = Timeline::GetEmbedderStream();
10208 // Make sure it is enabled.
10209 stream->set_enabled(true);
10210
10212 TimelineEventRecorder* recorder = Timeline::recorder();
10213 JSONStream js_chrome_timeline;
10214 JSONStream js_perfetto_timeline;
10215 TimelineEventFilter filter;
10216 recorder->PrintJSON(&js_chrome_timeline, &filter);
10217#if defined(SUPPORT_PERFETTO)
10218 recorder->PrintPerfettoTimeline(&js_perfetto_timeline, filter);
10219#endif // defined(SUPPORT_PERFETTO)
10220}
10221
10222static void CreateTimelineEvents(uword param) {
10223 {
10224 MonitorLocker ml(loop_test_lock);
10225 loop_test_exit = true;
10226 ml.Notify();
10227 }
10228 do {
10230 } while (true);
10231}
10232
10233UNIT_TEST_CASE(DartAPI_TimelineEvents_Loop) {
10235 FLAG_complete_timeline = true;
10237 memset(&params, 0, sizeof(Dart_InitializeParams));
10241 params.shutdown_isolate = TesterState::shutdown_callback;
10243 params.start_kernel_isolate = true;
10244 char* result = nullptr;
10245
10247 EXPECT(result == nullptr);
10248 {
10251 loop_reset_count = false;
10252 OSThread::Start("TimelineEvents", CreateTimelineEvents, 0);
10253 while (!loop_test_exit) {
10254 printf("VM waiting for notification\n");
10255 ml.Wait();
10256 }
10257 loop_test_exit = false;
10258 }
10259 result = Dart_Cleanup();
10260 EXPECT(result == nullptr);
10261 for (intptr_t i = 0; i < 50; i++) {
10264 EXPECT(result == nullptr);
10265 result = Dart_Cleanup();
10266 EXPECT(result == nullptr);
10267 }
10268}
10269
10270UNIT_TEST_CASE(DartAPI_TimelineEvents_NullFlowIdsHandledGracefully) {
10271 Dart_RecordTimelineEvent("T1", 0, 10, /*flow_id_count=*/1, nullptr,
10272 Dart_Timeline_Event_Duration, /*argument_count=*/0,
10273 nullptr, nullptr);
10274}
10275#endif // !defined(PRODUCT)
10276
10277static intptr_t EchoInt(double x) {
10278 return x;
10279}
10280
10281static void* FfiNativeResolver(const char* name, uintptr_t args_n) {
10282 ASSERT(strcmp(name, "EchoInt") == 0);
10283 ASSERT(args_n == 1);
10284 return reinterpret_cast<void*>(EchoInt);
10285}
10286
10288 const char* kScriptChars = R"(
10289 import 'dart:ffi';
10290 @Native<IntPtr Function(Double)>(symbol: 'EchoInt', isLeaf:true)
10291 external int echoInt(double x);
10292 main() => echoInt(7.0);
10293 )";
10294 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
10295 EXPECT_VALID(lib);
10296
10299
10300 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
10302
10303 int64_t value = 0;
10306 EXPECT_EQ(7, value);
10307}
10308
10309TEST_CASE(Dart_SetFfiNativeResolver_MissingResolver) {
10310 const char* kScriptChars = R"(
10311 import 'dart:ffi';
10312 @Native<IntPtr Function(Double)>(symbol: 'EchoInt', isLeaf:true)
10313 external int echoInt(double x);
10314 main() => echoInt(7.0);
10315 )";
10316 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
10317 EXPECT_VALID(lib);
10318
10319 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
10320
10321 // With no resolver, we resolve in process. Expect to not find the symbol
10322 // in processes. Error message depends on architecture.
10323 EXPECT_ERROR(result, "Invalid argument(s):");
10325
10326static void* NopResolver(const char* name, uintptr_t args_n) {
10327 return nullptr;
10328}
10329
10330TEST_CASE(Dart_SetFfiNativeResolver_DoesNotResolve) {
10331 const char* kScriptChars = R"(
10332 import 'dart:ffi';
10333 @Native<Void Function()>(symbol: 'DoesNotResolve')
10334 external void doesNotResolve();
10335 main() => doesNotResolve();
10336 )";
10337 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
10338 EXPECT_VALID(lib);
10339
10342
10343 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
10344 EXPECT_ERROR(result, "Couldn't resolve function: 'DoesNotResolve'");
10345}
10346
10347TEST_CASE(DartAPI_UserTags) {
10348 Dart_Handle default_tag = Dart_GetDefaultUserTag();
10349 EXPECT_VALID(default_tag);
10350
10351 auto default_label =
10352 Utils::CStringUniquePtr(Dart_GetUserTagLabel(default_tag), std::free);
10353 EXPECT_STREQ(default_label.get(), "Default");
10354
10355 Dart_Handle current_tag = Dart_GetCurrentUserTag();
10356 EXPECT(Dart_IdentityEquals(default_tag, current_tag));
10357
10358 auto current_label =
10359 Utils::CStringUniquePtr(Dart_GetUserTagLabel(current_tag), std::free);
10360 EXPECT_STREQ(default_label.get(), current_label.get());
10361
10362 Dart_Handle new_tag = Dart_NewUserTag("Foo");
10363 EXPECT_VALID(new_tag);
10364
10365 auto new_tag_label =
10366 Utils::CStringUniquePtr(Dart_GetUserTagLabel(new_tag), std::free);
10367 EXPECT_STREQ(new_tag_label.get(), "Foo");
10368
10369 Dart_Handle old_tag = Dart_SetCurrentUserTag(new_tag);
10370 EXPECT_VALID(old_tag);
10371
10372 auto old_label =
10373 Utils::CStringUniquePtr(Dart_GetUserTagLabel(old_tag), std::free);
10374 EXPECT_STREQ(old_label.get(), default_label.get());
10375
10376 current_tag = Dart_GetCurrentUserTag();
10377 EXPECT(Dart_IdentityEquals(new_tag, current_tag));
10378
10379 current_label =
10380 Utils::CStringUniquePtr(Dart_GetUserTagLabel(current_tag), std::free);
10381 EXPECT_STREQ(current_label.get(), new_tag_label.get());
10382
10383 EXPECT(Dart_GetUserTagLabel(Dart_Null()) == nullptr);
10384
10386 "Dart_NewUserTag expects argument 'label' to be non-null");
10387
10390 "Dart_SetCurrentUserTag expects argument 'user_tag' to be non-null");
10391}
10392
10393#endif // !PRODUCT
10394
10395#if !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
10396
10397static void* last_allocation_context = nullptr;
10398static const char* last_allocation_cls = nullptr;
10399static intptr_t heap_samples = 0;
10400static const char* expected_allocation_cls = nullptr;
10401static bool found_allocation = false;
10402
10403static void* HeapSamplingCreate(Dart_Isolate isolate,
10404 Dart_IsolateGroup isolate_group,
10405 const char* cls_name,
10406 intptr_t heap_size) {
10407 last_allocation_cls = cls_name;
10408 return strdup(cls_name);
10409}
10410
10411static void HeapSamplingDelete(void* data) {
10412 free(data);
10413}
10414
10415void HeapSamplingReport(void* context, void* data) {
10416 last_allocation_context = context;
10417 if (strcmp(reinterpret_cast<char*>(data), expected_allocation_cls) == 0) {
10418 found_allocation = true;
10419 }
10420 heap_samples++;
10421}
10422
10423void ResetHeapSamplingState(const char* expected_cls = nullptr) {
10424 heap_samples = 0;
10425 expected_allocation_cls = expected_cls;
10426 found_allocation = false;
10427 last_allocation_context = nullptr;
10428 last_allocation_cls = nullptr;
10429}
10430
10431// Threads won't pick up heap sampling profiler state changes until they
10432// process outstanding VM interrupts. Invoke this method after calling
10433// any of the following APIs in a test to ensure changes are applied:
10434//
10435// - Dart_EnableHeapSampling()
10436// - Dart_DisableHeapSampling()
10437// - Dart_SetHeapSamplingPeriod(...)
10438void HandleInterrupts(Thread* thread) {
10439 TransitionNativeToVM transition(thread);
10440 thread->HandleInterrupts();
10441}
10442
10443void InitHeapSampling(Thread* thread, const char* expected_cls) {
10444 ResetHeapSamplingState(expected_cls);
10447 // Start with sampling on every byte allocated.
10449 HandleInterrupts(thread);
10450}
10451
10452TEST_CASE(DartAPI_HeapSampling_UserDefinedClass) {
10453 DisableBackgroundCompilationScope scope;
10454 const char* kScriptChars = R"(
10455 class Bar {}
10456 final list = [];
10457 foo() {
10458 for (int i = 0; i < 100000; ++i) {
10459 list.add(Bar());
10460 }
10461 }
10462 )";
10463
10464 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
10465 EXPECT_VALID(lib);
10466
10467 InitHeapSampling(thread, "Bar");
10468 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, nullptr);
10470
10471 // Exit the isolate before getting the profile.
10474
10475 void* context = reinterpret_cast<void*>(42); // Fake data, not used.
10477 /*force_gc=*/true);
10478 EXPECT(heap_samples > 0);
10479 EXPECT(heap_samples < 100000);
10480 EXPECT(last_allocation_context == context);
10482 Dart_EnterIsolate(isolate);
10483}
10484
10485TEST_CASE(DartAPI_HeapSampling_APIAllocations) {
10486 InitHeapSampling(thread, "List");
10487
10488 // Some simple allocations
10490
10491 // Exit the isolate before getting the profile.
10493 EXPECT(isolate != nullptr);
10495
10497 /*force_gc=*/true);
10498 EXPECT(heap_samples > 0);
10499#if !defined(PRODUCT)
10500 EXPECT_STREQ("List", last_allocation_cls);
10501 ResetHeapSamplingState("String");
10502#else
10503 EXPECT_STREQ("_List", last_allocation_cls);
10504 ResetHeapSamplingState("_OneByteString");
10505#endif
10506
10507 // Re-enter the isolate.
10508 Dart_EnterIsolate(isolate);
10509
10510 const intptr_t kNumAllocations = 1000;
10511 for (intptr_t i = 0; i < kNumAllocations; ++i) {
10513 }
10514
10515 // Exit the isolate after performing allocations.
10517
10519 /*force_gc=*/true);
10520 EXPECT(heap_samples > 0);
10522
10523#if !defined(PRODUCT)
10524 ResetHeapSamplingState("String");
10525#else
10526 ResetHeapSamplingState("_OneByteString");
10527#endif
10528
10529 // Re-enter the isolate.
10530 Dart_EnterIsolate(isolate);
10531
10533
10534 // Exit the isolate after performing allocations.
10536
10538 /*force_gc=*/true);
10539 EXPECT(heap_samples > 0);
10541
10542 ResetHeapSamplingState("Uint8List");
10543
10544 // Re-enter the isolate.
10545 Dart_EnterIsolate(isolate);
10546
10548
10549 // Exit the isolate after performing allocations.
10551
10553 /*force_gc=*/true);
10554 EXPECT(heap_samples > 0);
10556
10557 Dart_EnterIsolate(isolate);
10558}
10559
10560TEST_CASE(DartAPI_HeapSampling_NonTrivialSamplingPeriod) {
10561 DisableBackgroundCompilationScope scope;
10562 InitHeapSampling(thread, "List");
10563
10564 // Increase the sampling period and check that we don't sample each
10565 // allocation. This should cause samples to be collected for approximately
10566 // every 1KiB allocated.
10568 HandleInterrupts(thread);
10569
10570 // Allocate via the embedding API.
10571 const intptr_t kNumAllocations = 1000;
10572 for (intptr_t i = 0; i < kNumAllocations; ++i) {
10574 }
10575
10576 // Exit the isolate before getting the profile.
10578 EXPECT(isolate != nullptr);
10580
10582 /*force_gc=*/true);
10583 EXPECT(heap_samples > 0);
10584 EXPECT(heap_samples < kNumAllocations);
10585
10586 // Re-enter the isolate.
10587 Dart_EnterIsolate(isolate);
10588
10589 const char* kScriptChars = R"(
10590 final list = [];
10591 foo() {
10592 for (int i = 0; i < 1000; ++i) {
10593 list.add(List.filled(100, 0));
10594 }
10595 }
10596 )";
10598 HandleInterrupts(thread);
10599
10600 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
10601 EXPECT_VALID(lib);
10602
10603 ResetHeapSamplingState("List");
10604
10606 HandleInterrupts(thread);
10607
10608 // Allocate via Dart code.
10609 Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, nullptr);
10611
10612 // Exit the isolate after performing allocations.
10614
10616 /*force_gc=*/true);
10617 EXPECT(heap_samples > 0);
10618 EXPECT(heap_samples < kNumAllocations);
10619
10620 Dart_EnterIsolate(isolate);
10622}
10623
10624// Check that we set correct sampling interval for old space allocations
10625// during initial isolate startup (before the first TLAB is created).
10626// This is a regression test for a bug that was causing each old space
10627// allocation to be sampled.
10629 DartAPI_HeapSampling_CorrectSamplingIntervalForOldSpaceAllocations) {
10631 [](Dart_Isolate isolate, Dart_IsolateGroup isolate_group,
10632 const char* cls_name, intptr_t allocation_size) -> void* {
10633 // Should not be called because sampling interval is very large.
10634 UNREACHABLE();
10635 return nullptr;
10636 },
10637 [](void* data) {
10638 // Nothing to do.
10639 });
10645}
10646#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_SAMPLING_HEAP_PROFILER)
10647
10648#if defined(DART_ENABLE_HEAP_SNAPSHOT_WRITER)
10649TEST_CASE(DartAPI_WriteHeapSnapshot) {
10650 struct WriterContext {
10651 intptr_t bytes_written;
10652 bool saw_last_chunk;
10653 };
10654
10655 WriterContext context = {0, false};
10657 [](void* context, uint8_t* buffer, intptr_t size, bool is_last) {
10658 auto ctx = static_cast<WriterContext*>(context);
10659 ctx->bytes_written += size;
10660 EXPECT(!ctx->saw_last_chunk);
10661 ctx->saw_last_chunk = is_last;
10662
10663 free(buffer);
10664 },
10665 &context);
10666 EXPECT(error == nullptr);
10667 EXPECT_GT(context.bytes_written, 0);
10668 EXPECT(context.saw_last_chunk);
10669}
10670#endif // defined(DART_ENABLE_HEAP_SNAPSHOT_WRITER)
10671
10672} // 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
static bool equal(const SkBitmap &a, const SkBitmap &b)
float e1
static bool is_equal(SkSurface *a, SkSurface *b)
static bool contains(const SkRect &r, SkPoint p)
static bool equals(T *a, T *b)
static const size_t kBufferSize
Definition SkString.cpp:27
#define EXPECT(type, expectedAlignment, expectedSize)
#define UNREACHABLE()
Definition assert.h:248
#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:10898
BackgroundGCTask(IsolateGroup *isolate_group, Monitor *monitor, bool *done)
uint16_t num_native_fields() const
Definition object.h:1790
intptr_t host_instance_size() const
Definition object.h:1145
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:824
intptr_t ExternalInWords(Space space) const
Definition heap.cc:800
InfiniteLoopTask(Dart_Isolate *isolate, Monitor *monitor, bool *interrupted)
Heap * heap() const
Definition isolate.h:295
static IsolateGroup * Current()
Definition isolate.h:534
ApiState * api_state() const
Definition isolate.h:693
static Isolate * Current()
Definition isolate.h:939
static Dart_IsolateShutdownCallback ShutdownCallback()
Definition isolate.h:1170
static void SetShutdownCallback(Dart_IsolateShutdownCallback cb)
Definition isolate.h:1167
IsolateGroup * group() const
Definition isolate.h:990
static void SetCleanupCallback(Dart_IsolateCleanupCallback cb)
Definition isolate.h:1174
static Dart_IsolateGroupCreateCallback CreateGroupCallback()
Definition isolate.h:1156
Dart_MessageNotifyCallback message_notify_callback() const
Definition isolate.h:964
static Dart_IsolateGroupCleanupCallback GroupCleanupCallback()
Definition isolate.h:1184
static void SetGroupCleanupCallback(Dart_IsolateGroupCleanupCallback cb)
Definition isolate.h:1181
static void SetCreateGroupCallback(Dart_IsolateGroupCreateCallback cb)
Definition isolate.h:1153
StringPtr PrivateName(const String &name) const
Definition object.cc:14751
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:175
static ThreadJoinId GetCurrentThreadJoinId(OSThread *thread)
static const ThreadJoinId kInvalidThreadJoinId
Definition os_thread.h:245
static void Sleep(int64_t millis)
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
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:13192
static constexpr intptr_t kMaxElements
Definition object.h:10522
static PersistentHandle * Cast(Dart_PersistentHandle handle)
ObjectPtr ptr() const
static SmiPtr New(intptr_t value)
Definition object.h:9985
intptr_t Value() const
Definition object.h:9969
static constexpr int kPreallocatedStackdepth
Definition object.h:12532
bool Equals(const String &str) const
Definition object.h:13311
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition object.cc:23777
static const char * ToCString(Thread *thread, StringPtr ptr)
Definition object.cc:24205
static void AddToKernelBuffers(const uint8_t *kernel_buffer)
Definition unit_test.cc:100
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:476
static void AddTestLib(const char *url, const char *source)
Definition unit_test.cc:188
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:422
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:300
static const char * url()
Definition unit_test.cc:184
static Dart_Handle LoadTestLibrary(const char *lib_uri, const char *script, Dart_NativeEntryResolver resolver=nullptr)
Definition unit_test.cc:441
static bool IsNNBD()
Definition unit_test.cc:217
static const char * NullableTag()
Definition unit_test.h:421
static Dart_Handle library_handler(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url)
Definition unit_test.cc:637
static Dart_Isolate CreateTestIsolate(const char *name=nullptr, void *isolate_group_data=nullptr, void *isolate_data=nullptr)
Definition unit_test.cc:139
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
ApiLocalScope * api_top_scope() const
Definition thread.h:512
static Thread * Current()
Definition thread.h:361
Heap * heap() const
Definition thread.cc:876
int ZoneSizeInBytes() const
Definition thread.cc:1225
intptr_t CountLocalHandles() const
Definition thread.cc:1215
static void ExitIsolateGroupAsHelper(bool bypass_safepoint)
Definition thread.cc:494
Isolate * isolate() const
Definition thread.h:533
static bool EnterIsolateGroupAsHelper(IsolateGroup *isolate_group, TaskKind kind, bool bypass_safepoint)
Definition thread.cc:476
static constexpr intptr_t kMaxElements
Definition object.h:10663
static TypePtr BoolType()
Definition object.cc:21882
static TypePtr NullType()
Definition object.cc:21862
static UnwindErrorPtr New(const String &message, Heap::Space space=Heap::kNew)
Definition object.cc:20055
static int SNPrint(char *str, size_t size, const char *format,...) PRINTF_ATTRIBUTE(3
static char * StrDup(const char *s)
std::unique_ptr< char, decltype(std::free) * > CStringUniquePtr
Definition utils.h:644
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition utils.h:105
static constexpr int kSize
#define UNIT_TEST_CASE(name)
Definition unit_test.h:23
@ Dart_CoreType_Dynamic
Definition dart_api.h:2424
@ Dart_CoreType_Int
Definition dart_api.h:2425
@ Dart_CoreType_String
Definition dart_api.h:2426
#define DART_INITIALIZE_PARAMS_CURRENT_VERSION
Definition dart_api.h:839
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:653
#define ILLEGAL_PORT
Definition dart_api.h:1530
@ Dart_PerformanceMode_Default
Definition dart_api.h:1372
@ Dart_PerformanceMode_Latency
Definition dart_api.h:1379
int64_t Dart_Port
Definition dart_api.h:1524
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:3010
Dart_TypedData_Type
Definition dart_api.h:2603
@ Dart_TypedData_kFloat32x4
Definition dart_api.h:2617
@ Dart_TypedData_kUint8
Definition dart_api.h:2606
@ Dart_TypedData_kUint32
Definition dart_api.h:2611
@ Dart_TypedData_kInt32
Definition dart_api.h:2610
@ Dart_TypedData_kUint16
Definition dart_api.h:2609
@ Dart_TypedData_kUint64
Definition dart_api.h:2613
@ Dart_TypedData_kFloat32
Definition dart_api.h:2614
@ Dart_TypedData_kInt16
Definition dart_api.h:2608
@ Dart_TypedData_kFloat64
Definition dart_api.h:2615
@ Dart_TypedData_kUint8Clamped
Definition dart_api.h:2607
@ Dart_TypedData_kByteData
Definition dart_api.h:2604
@ Dart_TypedData_kInt8
Definition dart_api.h:2605
@ Dart_TypedData_kInt64
Definition dart_api.h:2612
@ Dart_TypedData_kInvalid
Definition dart_api.h:2619
Dart_Handle Dart_PersistentHandle
Definition dart_api.h:259
void(* Dart_IsolateGroupCleanupCallback)(void *isolate_group_data)
Definition dart_api.h:744
struct _Dart_FinalizableHandle * Dart_FinalizableHandle
Definition dart_api.h:261
void(* Dart_IsolateShutdownCallback)(void *isolate_group_data, void *isolate_data)
Definition dart_api.h:710
void(* Dart_NativeFunction)(Dart_NativeArguments arguments)
Definition dart_api.h:3198
@ Dart_NativeArgument_kString
Definition dart_api.h:3024
@ Dart_NativeArgument_kNativeFields
Definition dart_api.h:3026
@ Dart_NativeArgument_kInstance
Definition dart_api.h:3025
@ Dart_NativeArgument_kInt32
Definition dart_api.h:3019
@ Dart_NativeArgument_kUint64
Definition dart_api.h:3022
@ Dart_NativeArgument_kDouble
Definition dart_api.h:3023
@ Dart_NativeArgument_kBool
Definition dart_api.h:3018
struct _Dart_WeakPersistentHandle * Dart_WeakPersistentHandle
Definition dart_api.h:260
#define CHECK_API_SCOPE(thread)
#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
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
GAsyncResult * result
#define DECLARE_FLAG(type, name)
Definition flags.h:14
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
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)
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)
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)
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)
DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id, intptr_t length)
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)
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:1112
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 Dart_Handle Dart_IsLegacyType(Dart_Handle type, bool *result)
DART_EXPORT void Dart_EnableHeapSampling()
static constexpr intptr_t kNativeField2Value
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
Definition main.py:1
#define Pd64
Definition globals.h:416
#define DART_INT64_C(x)
Definition globals.h:433
#define T
Dart_OnNewCodeCallback on_new_code
Definition dart_api.h:862
union _Dart_CObject::@86 value
Dart_CObject_Type type
struct _Dart_CObject::@86::@90 as_typed_data
struct _Dart_CObject::@86::@89 as_array
struct _Dart_CObject ** values
struct _Dart_NativeArgument_Value::@84 as_native_fields
#define VM_UNIT_TEST_CASE(name)
Definition unit_test.h:33
#define ZONE_STR(FMT,...)
Definition unit_test.h:226
#define EXPECT_ERROR(handle, substring)
Definition unit_test.h:670
#define TEST_CASE(name)
Definition unit_test.h:85
#define RESOLVED_USER_TEST_URI
Definition unit_test.h:317
#define EXPECT_VALID(handle)
Definition unit_test.h:650
#define USER_TEST_URI
Definition unit_test.h:316
#define ARRAY_SIZE(array)
Definition globals.h:72