Flutter Engine
The Flutter Engine
snapshot_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 "platform/globals.h"
6
8#include "platform/assert.h"
9#include "platform/unicode.h"
10#include "vm/app_snapshot.h"
11#include "vm/class_finalizer.h"
12#include "vm/dart_api_impl.h"
13#include "vm/dart_api_message.h"
14#include "vm/dart_api_state.h"
16#include "vm/flags.h"
17#include "vm/message_snapshot.h"
18#include "vm/snapshot.h"
19#include "vm/symbols.h"
20#include "vm/timer.h"
21#include "vm/unit_test.h"
22
23namespace dart {
24
25// Check if serialized and deserialized objects are equal.
26static bool Equals(const Object& expected, const Object& actual) {
27 if (expected.IsNull()) {
28 return actual.IsNull();
29 }
30 if (expected.IsSmi()) {
31 if (actual.IsSmi()) {
32 return expected.ptr() == actual.ptr();
33 }
34 return false;
35 }
36 if (expected.IsDouble()) {
37 if (actual.IsDouble()) {
38 Double& dbl1 = Double::Handle();
39 Double& dbl2 = Double::Handle();
40 dbl1 ^= expected.ptr();
41 dbl2 ^= actual.ptr();
42 return dbl1.value() == dbl2.value();
43 }
44 return false;
45 }
46 if (expected.IsBool()) {
47 if (actual.IsBool()) {
48 return expected.ptr() == actual.ptr();
49 }
50 return false;
51 }
52 return false;
53}
54
55// Compare two Dart_CObject object graphs rooted in first and
56// second. The second graph will be destroyed by this operation no matter
57// whether the graphs are equal or not.
58static void CompareDartCObjects(Dart_CObject* first, Dart_CObject* second) {
59 // Return immediately if entering a cycle.
60 if (second->type == Dart_CObject_kNumberOfTypes) return;
61
62 EXPECT_EQ(first->type, second->type);
63 switch (first->type) {
65 // Nothing more to compare.
66 break;
68 EXPECT_EQ(first->value.as_bool, second->value.as_bool);
69 break;
71 EXPECT_EQ(first->value.as_int32, second->value.as_int32);
72 break;
74 EXPECT_EQ(first->value.as_int64, second->value.as_int64);
75 break;
77 EXPECT_EQ(first->value.as_double, second->value.as_double);
78 break;
80 EXPECT_STREQ(first->value.as_string, second->value.as_string);
81 break;
83 EXPECT_EQ(first->value.as_typed_data.length,
84 second->value.as_typed_data.length);
85 for (int i = 0; i < first->value.as_typed_data.length; i++) {
86 EXPECT_EQ(first->value.as_typed_data.values[i],
87 second->value.as_typed_data.values[i]);
88 }
89 break;
91 // Use invalid type as a visited marker to avoid infinite
92 // recursion on graphs with cycles.
94 EXPECT_EQ(first->value.as_array.length, second->value.as_array.length);
95 for (int i = 0; i < first->value.as_array.length; i++) {
97 second->value.as_array.values[i]);
98 }
99 break;
101 EXPECT_EQ(first->value.as_capability.id, second->value.as_capability.id);
102 break;
103 default:
104 EXPECT(false);
105 }
106}
107
109 // Encode and decode the message.
110 std::unique_ptr<Message> message =
112
113 Dart_CObject* new_root = ReadApiMessage(zone, message.get());
114
115 // Check that the two messages are the same.
116 CompareDartCObjects(root, new_root);
117}
118
120 std::unique_ptr<Message> message =
122 EXPECT(message == nullptr);
123}
124
126 StackZone zone(thread);
127
128 // Write snapshot with object content.
129 const Object& null_object = Object::Handle();
130 std::unique_ptr<Message> message =
131 WriteMessage(/* same_group */ false, null_object, ILLEGAL_PORT,
133
134 // Read object back from the snapshot.
135 const Object& serialized_object =
136 Object::Handle(ReadMessage(thread, message.get()));
137 EXPECT(Equals(null_object, serialized_object));
138
139 // Read object back from the snapshot into a C structure.
140 ApiNativeScope scope;
141 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
142 EXPECT_NOTNULL(root);
143 EXPECT_EQ(Dart_CObject_kNull, root->type);
145}
146
148 StackZone zone(thread);
149
150 // Write snapshot with object content.
151 const Smi& smi = Smi::Handle(Smi::New(124));
152 std::unique_ptr<Message> message = WriteMessage(
153 /* same_group */ false, smi, ILLEGAL_PORT, Message::kNormalPriority);
154
155 // Read object back from the snapshot.
156 const Object& serialized_object =
157 Object::Handle(ReadMessage(thread, message.get()));
158 EXPECT(Equals(smi, serialized_object));
159
160 // Read object back from the snapshot into a C structure.
161 ApiNativeScope scope;
162 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
163 EXPECT_NOTNULL(root);
164 EXPECT_EQ(Dart_CObject_kInt32, root->type);
165 EXPECT_EQ(smi.Value(), root->value.as_int32);
167}
168
170 StackZone zone(thread);
171
172 // Write snapshot with object content.
173 const Smi& smi = Smi::Handle(Smi::New(-1));
174 std::unique_ptr<Message> message = WriteMessage(
175 /* same_group */ false, smi, ILLEGAL_PORT, Message::kNormalPriority);
176
177 // Read object back from the snapshot.
178 const Object& serialized_object =
179 Object::Handle(ReadMessage(thread, message.get()));
180 EXPECT(Equals(smi, serialized_object));
181
182 // Read object back from the snapshot into a C structure.
183 ApiNativeScope scope;
184 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
185 EXPECT_NOTNULL(root);
186 EXPECT_EQ(Dart_CObject_kInt32, root->type);
187 EXPECT_EQ(smi.Value(), root->value.as_int32);
189}
190
192 // Write snapshot with object content.
193 std::unique_ptr<Message> message = WriteMessage(
194 /* same_group */ false, mint, ILLEGAL_PORT, Message::kNormalPriority);
195
196 {
197 // Switch to a regular zone, where VM handle allocation is allowed.
198 Thread* thread = Thread::Current();
199 StackZone zone(thread);
200 // Read object back from the snapshot.
201 const Object& serialized_object =
202 Object::Handle(ReadMessage(thread, message.get()));
203 EXPECT(serialized_object.IsMint());
204 }
205
206 // Read object back from the snapshot into a C structure.
207 Dart_CObject* root = ReadApiMessage(zone, message.get());
208 EXPECT_NOTNULL(root);
210 return root;
211}
212
213void CheckMint(int64_t value) {
214 ApiNativeScope scope;
216
217 Mint& mint = Mint::Handle();
218 mint ^= Integer::New(value);
219 Dart_CObject* mint_cobject =
221// On 64-bit platforms mints always require 64-bits as the smi range
222// here covers most of the 64-bit range. On 32-bit platforms the smi
223// range covers most of the 32-bit range and values outside that
224// range are also represented as mints.
225#if defined(ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
226 EXPECT_EQ(Dart_CObject_kInt64, mint_cobject->type);
227 EXPECT_EQ(value, mint_cobject->value.as_int64);
228#else
229 if (kMinInt32 < value && value < kMaxInt32) {
230 EXPECT_EQ(Dart_CObject_kInt32, mint_cobject->type);
231 EXPECT_EQ(value, mint_cobject->value.as_int32);
232 } else {
233 EXPECT_EQ(Dart_CObject_kInt64, mint_cobject->type);
234 EXPECT_EQ(value, mint_cobject->value.as_int64);
235 }
236#endif
237}
238
239ISOLATE_UNIT_TEST_CASE(SerializeMints) {
240 // Min positive mint.
242 // Min positive mint + 1.
244 // Max negative mint.
246 // Max negative mint - 1.
248 // Max positive mint.
250 // Max positive mint - 1.
251 CheckMint(kMaxInt64 - 1);
252 // Min negative mint.
254 // Min negative mint + 1.
255 CheckMint(kMinInt64 + 1);
256}
257
258ISOLATE_UNIT_TEST_CASE(SerializeDouble) {
259 StackZone zone(thread);
260
261 // Write snapshot with object content.
262 const Double& dbl = Double::Handle(Double::New(101.29));
263 std::unique_ptr<Message> message = WriteMessage(
264 /* same_group */ false, dbl, ILLEGAL_PORT, Message::kNormalPriority);
265
266 // Read object back from the snapshot.
267 const Object& serialized_object =
268 Object::Handle(ReadMessage(thread, message.get()));
269 EXPECT(Equals(dbl, serialized_object));
270
271 // Read object back from the snapshot into a C structure.
272 ApiNativeScope scope;
273 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
274 EXPECT_NOTNULL(root);
275 EXPECT_EQ(Dart_CObject_kDouble, root->type);
276 EXPECT_EQ(dbl.value(), root->value.as_double);
278}
279
281 StackZone zone(thread);
282
283 // Write snapshot with true object.
284 const Bool& bl = Bool::True();
285 std::unique_ptr<Message> message = WriteMessage(
286 /* same_group */ false, bl, ILLEGAL_PORT, Message::kNormalPriority);
287
288 // Read object back from the snapshot.
289 const Object& serialized_object =
290 Object::Handle(ReadMessage(thread, message.get()));
291 fprintf(stderr, "%s / %s\n", bl.ToCString(), serialized_object.ToCString());
292
293 EXPECT(Equals(bl, serialized_object));
294
295 // Read object back from the snapshot into a C structure.
296 ApiNativeScope scope;
297 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
298 EXPECT_NOTNULL(root);
299 EXPECT_EQ(Dart_CObject_kBool, root->type);
300 EXPECT_EQ(true, root->value.as_bool);
302}
303
304ISOLATE_UNIT_TEST_CASE(SerializeFalse) {
305 StackZone zone(thread);
306
307 // Write snapshot with false object.
308 const Bool& bl = Bool::False();
309 std::unique_ptr<Message> message = WriteMessage(
310 /* same_group */ false, bl, ILLEGAL_PORT, Message::kNormalPriority);
311
312 // Read object back from the snapshot.
313 const Object& serialized_object =
314 Object::Handle(ReadMessage(thread, message.get()));
315 EXPECT(Equals(bl, serialized_object));
316
317 // Read object back from the snapshot into a C structure.
318 ApiNativeScope scope;
319 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
320 EXPECT_NOTNULL(root);
321 EXPECT_EQ(Dart_CObject_kBool, root->type);
322 EXPECT_EQ(false, root->value.as_bool);
324}
325
326ISOLATE_UNIT_TEST_CASE(SerializeCapability) {
327 // Write snapshot with object content.
328 const Capability& capability = Capability::Handle(Capability::New(12345));
329 std::unique_ptr<Message> message =
330 WriteMessage(/* same_group */ false, capability, ILLEGAL_PORT,
332
333 // Read object back from the snapshot.
335 obj ^= ReadMessage(thread, message.get());
336
337 EXPECT_EQ(static_cast<uint64_t>(12345), obj.Id());
338
339 // Read object back from the snapshot into a C structure.
340 ApiNativeScope scope;
341 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
342 EXPECT_NOTNULL(root);
343 EXPECT_EQ(Dart_CObject_kCapability, root->type);
344 int64_t id = root->value.as_capability.id;
345 EXPECT_EQ(12345, id);
347}
348
349#define TEST_ROUND_TRIP_IDENTICAL(object) \
350 { \
351 const Object& before = Object::Handle(object); \
352 std::unique_ptr<Message> message = \
353 WriteMessage(/* same_group */ false, before, ILLEGAL_PORT, \
354 Message::kNormalPriority); \
355 const Object& after = Object::Handle(ReadMessage(thread, message.get())); \
356 EXPECT(before.ptr() == after.ptr()); \
357 }
358
359ISOLATE_UNIT_TEST_CASE(SerializeSingletons) {
372}
373
374static void TestString(const char* cstr) {
375 Thread* thread = Thread::Current();
376 EXPECT(Utf8::IsValid(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr)));
377 // Write snapshot with object content.
378 String& str = String::Handle(String::New(cstr));
379 std::unique_ptr<Message> message = WriteMessage(
380 /* same_group */ false, str, ILLEGAL_PORT, Message::kNormalPriority);
381
382 // Read object back from the snapshot.
383 String& serialized_str = String::Handle();
384 serialized_str ^= ReadMessage(thread, message.get());
385 EXPECT(str.Equals(serialized_str));
386
387 // Read object back from the snapshot into a C structure.
388 ApiNativeScope scope;
389 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
390 EXPECT_EQ(Dart_CObject_kString, root->type);
391 EXPECT_STREQ(cstr, root->value.as_string);
393}
394
395ISOLATE_UNIT_TEST_CASE(SerializeString) {
396 TestString("This string shall be serialized");
397 TestString("æøå"); // This file is UTF-8 encoded.
398 const char* data =
399 "\x01"
400 "\x7F"
401 "\xC2\x80" // U+0080
402 "\xDF\xBF" // U+07FF
403 "\xE0\xA0\x80" // U+0800
404 "\xEF\xBF\xBF"; // U+FFFF
405
407 // TODO(sgjesse): Add tests with non-BMP characters.
408}
409
410ISOLATE_UNIT_TEST_CASE(SerializeArray) {
411 // Write snapshot with object content.
412 const int kArrayLength = 10;
413 Array& array = Array::Handle(Array::New(kArrayLength));
414 Smi& smi = Smi::Handle();
415 for (int i = 0; i < kArrayLength; i++) {
416 smi ^= Smi::New(i);
417 array.SetAt(i, smi);
418 }
419 std::unique_ptr<Message> message = WriteMessage(
420 /* same_group */ false, array, ILLEGAL_PORT, Message::kNormalPriority);
421
422 // Read object back from the snapshot.
423 Array& serialized_array = Array::Handle();
424 serialized_array ^= ReadMessage(thread, message.get());
425 EXPECT(array.CanonicalizeEquals(serialized_array));
426
427 // Read object back from the snapshot into a C structure.
428 ApiNativeScope scope;
429 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
430 EXPECT_EQ(Dart_CObject_kArray, root->type);
431 EXPECT_EQ(kArrayLength, root->value.as_array.length);
432 for (int i = 0; i < kArrayLength; i++) {
433 Dart_CObject* element = root->value.as_array.values[i];
434 EXPECT_EQ(Dart_CObject_kInt32, element->type);
435 EXPECT_EQ(i, element->value.as_int32);
436 }
438}
439
440ISOLATE_UNIT_TEST_CASE(SerializeArrayWithTypeArgument) {
441 // Write snapshot with object content.
442 const int kArrayLength = 10;
443 Array& array =
445
446 Smi& smi = Smi::Handle();
447 for (int i = 0; i < kArrayLength; i++) {
448 smi ^= Smi::New(i);
449 array.SetAt(i, smi);
450 }
451 std::unique_ptr<Message> message = WriteMessage(
452 /* same_group */ false, array, ILLEGAL_PORT, Message::kNormalPriority);
453
454 // Read object back from the snapshot.
455 Array& serialized_array = Array::Handle();
456 serialized_array ^= ReadMessage(thread, message.get());
457 EXPECT(array.CanonicalizeEquals(serialized_array));
458
459 // Read object back from the snapshot into a C structure.
460 ApiNativeScope scope;
461 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
462 EXPECT_EQ(Dart_CObject_kArray, root->type);
463 EXPECT_EQ(kArrayLength, root->value.as_array.length);
464 for (int i = 0; i < kArrayLength; i++) {
465 Dart_CObject* element = root->value.as_array.values[i];
466 EXPECT_EQ(Dart_CObject_kInt32, element->type);
467 EXPECT_EQ(i, element->value.as_int32);
468 }
470}
471
472TEST_CASE(FailSerializeLargeArray) {
475 root.value.as_array.length = Array::kMaxElements + 1;
476 root.value.as_array.values = nullptr;
477 ApiNativeScope scope;
478 ExpectEncodeFail(scope.zone(), &root);
479}
480
481TEST_CASE(FailSerializeLargeNestedArray) {
482 Dart_CObject parent;
483 Dart_CObject child;
484 Dart_CObject* values[1] = {&child};
485
486 parent.type = Dart_CObject_kArray;
487 parent.value.as_array.length = 1;
488 parent.value.as_array.values = values;
491 ApiNativeScope scope;
492 ExpectEncodeFail(scope.zone(), &parent);
493}
494
495TEST_CASE(FailSerializeLargeTypedDataInt8) {
498 root.value.as_typed_data.type = Dart_TypedData_kInt8;
499 root.value.as_typed_data.length =
500 TypedData::MaxElements(kTypedDataInt8ArrayCid) + 1;
501 ApiNativeScope scope;
502 ExpectEncodeFail(scope.zone(), &root);
503}
504
505TEST_CASE(FailSerializeLargeTypedDataUint8) {
508 root.value.as_typed_data.type = Dart_TypedData_kUint8;
509 root.value.as_typed_data.length =
510 TypedData::MaxElements(kTypedDataUint8ArrayCid) + 1;
511 ApiNativeScope scope;
512 ExpectEncodeFail(scope.zone(), &root);
513}
514
515TEST_CASE(FailSerializeLargeExternalTypedData) {
518 root.value.as_external_typed_data.type = Dart_TypedData_kUint8;
519 root.value.as_external_typed_data.length =
520 ExternalTypedData::MaxElements(kExternalTypedDataUint8ArrayCid) + 1;
521 ApiNativeScope scope;
522 ExpectEncodeFail(scope.zone(), &root);
523}
524
525TEST_CASE(FailSerializeLargeUnmodifiableExternalTypedData) {
528 root.value.as_external_typed_data.type = Dart_TypedData_kUint8;
529 root.value.as_external_typed_data.length =
530 ExternalTypedData::MaxElements(kExternalTypedDataUint8ArrayCid) + 1;
531 ApiNativeScope scope;
532 ExpectEncodeFail(scope.zone(), &root);
533}
534
535ISOLATE_UNIT_TEST_CASE(SerializeEmptyArray) {
536 // Write snapshot with object content.
537 const int kArrayLength = 0;
538 Array& array = Array::Handle(Array::New(kArrayLength));
539 std::unique_ptr<Message> message = WriteMessage(
540 /* same_group */ false, array, ILLEGAL_PORT, Message::kNormalPriority);
541
542 // Read object back from the snapshot.
543 Array& serialized_array = Array::Handle();
544 serialized_array ^= ReadMessage(thread, message.get());
545 EXPECT(array.CanonicalizeEquals(serialized_array));
546
547 // Read object back from the snapshot into a C structure.
548 ApiNativeScope scope;
549 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
550 EXPECT_EQ(Dart_CObject_kArray, root->type);
551 EXPECT_EQ(kArrayLength, root->value.as_array.length);
552 EXPECT(root->value.as_array.values == nullptr);
554}
555
556ISOLATE_UNIT_TEST_CASE(SerializeByteArray) {
557 // Write snapshot with object content.
558 const int kTypedDataLength = 256;
559 TypedData& typed_data = TypedData::Handle(
560 TypedData::New(kTypedDataUint8ArrayCid, kTypedDataLength));
561 for (int i = 0; i < kTypedDataLength; i++) {
562 typed_data.SetUint8(i, i);
563 }
564 std::unique_ptr<Message> message =
565 WriteMessage(/* same_group */ false, typed_data, ILLEGAL_PORT,
567
568 // Read object back from the snapshot.
569 TypedData& serialized_typed_data = TypedData::Handle();
570 serialized_typed_data ^= ReadMessage(thread, message.get());
571 EXPECT(serialized_typed_data.IsTypedData());
572
573 // Read object back from the snapshot into a C structure.
574 ApiNativeScope scope;
575 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
576 EXPECT_EQ(Dart_CObject_kTypedData, root->type);
577 EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
578 for (int i = 0; i < kTypedDataLength; i++) {
579 EXPECT(root->value.as_typed_data.values[i] == i);
580 }
582}
583
584#define TEST_TYPED_ARRAY(darttype, ctype) \
585 { \
586 StackZone zone(thread); \
587 const int kArrayLength = 127; \
588 TypedData& array = TypedData::Handle( \
589 TypedData::New(kTypedData##darttype##ArrayCid, kArrayLength)); \
590 intptr_t scale = array.ElementSizeInBytes(); \
591 for (int i = 0; i < kArrayLength; i++) { \
592 array.Set##darttype((i * scale), i); \
593 } \
594 std::unique_ptr<Message> message = \
595 WriteMessage(/* same_group */ false, array, ILLEGAL_PORT, \
596 Message::kNormalPriority); \
597 TypedData& serialized_array = TypedData::Handle(); \
598 serialized_array ^= ReadMessage(thread, message.get()); \
599 for (int i = 0; i < kArrayLength; i++) { \
600 EXPECT_EQ(static_cast<ctype>(i), \
601 serialized_array.Get##darttype(i* scale)); \
602 } \
603 }
604
605#define TEST_EXTERNAL_TYPED_ARRAY(darttype, ctype) \
606 { \
607 StackZone zone(thread); \
608 ctype data[] = {0, 11, 22, 33, 44, 55, 66, 77}; \
609 intptr_t length = ARRAY_SIZE(data); \
610 ExternalTypedData& array = ExternalTypedData::Handle( \
611 ExternalTypedData::New(kExternalTypedData##darttype##ArrayCid, \
612 reinterpret_cast<uint8_t*>(data), length)); \
613 intptr_t scale = array.ElementSizeInBytes(); \
614 std::unique_ptr<Message> message = \
615 WriteMessage(/* same_group */ false, array, ILLEGAL_PORT, \
616 Message::kNormalPriority); \
617 ExternalTypedData& serialized_array = ExternalTypedData::Handle(); \
618 serialized_array ^= ReadMessage(thread, message.get()); \
619 for (int i = 0; i < length; i++) { \
620 EXPECT_EQ(static_cast<ctype>(data[i]), \
621 serialized_array.Get##darttype(i* scale)); \
622 } \
623 }
624
625#define TEST_UNMODIFIABLE_EXTERNAL_TYPED_ARRAY(darttype, ctype) \
626 { \
627 StackZone zone(thread); \
628 ctype data[] = {0, 11, 22, 33, 44, 55, 66, 77}; \
629 intptr_t length = ARRAY_SIZE(data); \
630 ExternalTypedData& array = ExternalTypedData::Handle( \
631 ExternalTypedData::New(kExternalTypedData##darttype##ArrayCid, \
632 reinterpret_cast<uint8_t*>(data), length)); \
633 TypedDataView& view = TypedDataView::Handle(TypedDataView::New( \
634 kUnmodifiableTypedData##darttype##ArrayViewCid, array, 0, length)); \
635 intptr_t scale = array.ElementSizeInBytes(); \
636 std::unique_ptr<Message> message = WriteMessage( \
637 /* same_group */ false, view, ILLEGAL_PORT, Message::kNormalPriority); \
638 TypedDataView& serialized_view = TypedDataView::Handle(); \
639 serialized_view ^= ReadMessage(thread, message.get()); \
640 for (int i = 0; i < length; i++) { \
641 EXPECT_EQ(static_cast<ctype>(data[i]), \
642 serialized_view.Get##darttype(i* scale)); \
643 } \
644 }
645
646ISOLATE_UNIT_TEST_CASE(SerializeTypedArray) {
647 TEST_TYPED_ARRAY(Int8, int8_t);
648 TEST_TYPED_ARRAY(Uint8, uint8_t);
649 TEST_TYPED_ARRAY(Int16, int16_t);
650 TEST_TYPED_ARRAY(Uint16, uint16_t);
651 TEST_TYPED_ARRAY(Int32, int32_t);
652 TEST_TYPED_ARRAY(Uint32, uint32_t);
653 TEST_TYPED_ARRAY(Int64, int64_t);
654 TEST_TYPED_ARRAY(Uint64, uint64_t);
655 TEST_TYPED_ARRAY(Float32, float);
656 TEST_TYPED_ARRAY(Float64, double);
657}
658
659ISOLATE_UNIT_TEST_CASE(SerializeExternalTypedArray) {
660 TEST_EXTERNAL_TYPED_ARRAY(Int8, int8_t);
661 TEST_EXTERNAL_TYPED_ARRAY(Uint8, uint8_t);
662 TEST_EXTERNAL_TYPED_ARRAY(Int16, int16_t);
663 TEST_EXTERNAL_TYPED_ARRAY(Uint16, uint16_t);
664 TEST_EXTERNAL_TYPED_ARRAY(Int32, int32_t);
665 TEST_EXTERNAL_TYPED_ARRAY(Uint32, uint32_t);
666 TEST_EXTERNAL_TYPED_ARRAY(Int64, int64_t);
667 TEST_EXTERNAL_TYPED_ARRAY(Uint64, uint64_t);
668 TEST_EXTERNAL_TYPED_ARRAY(Float32, float);
669 TEST_EXTERNAL_TYPED_ARRAY(Float64, double);
670}
671
672ISOLATE_UNIT_TEST_CASE(SerializeUnmodifiableExternalTypedArray) {
683}
684
685ISOLATE_UNIT_TEST_CASE(SerializeEmptyByteArray) {
686 // Write snapshot with object content.
687 const int kTypedDataLength = 0;
688 TypedData& typed_data = TypedData::Handle(
689 TypedData::New(kTypedDataUint8ArrayCid, kTypedDataLength));
690 std::unique_ptr<Message> message =
691 WriteMessage(/* same_group */ false, typed_data, ILLEGAL_PORT,
693
694 // Read object back from the snapshot.
695 TypedData& serialized_typed_data = TypedData::Handle();
696 serialized_typed_data ^= ReadMessage(thread, message.get());
697 EXPECT(serialized_typed_data.IsTypedData());
698
699 // Read object back from the snapshot into a C structure.
700 ApiNativeScope scope;
701 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
702 EXPECT_EQ(Dart_CObject_kTypedData, root->type);
703 EXPECT_EQ(Dart_TypedData_kUint8, root->value.as_typed_data.type);
704 EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
705 EXPECT(root->value.as_typed_data.values == nullptr);
707}
708
709VM_UNIT_TEST_CASE(FullSnapshot) {
710 // clang-format off
711 const char* kScriptChars =
712 "class Fields {\n"
713 " Fields(int i, int j) : fld1 = i, fld2 = j {}\n"
714 " int fld1;\n"
715 " final int fld2;\n"
716 " final int bigint_fld = 0xfffffffffff;\n"
717 " static int? fld3;\n"
718 " static const int smi_sfld = 10;\n"
719 " static const int bigint_sfld = 0xfffffffffff;\n"
720 "}\n"
721 "class Expect {\n"
722 " static void equals(x, y) {\n"
723 " if (x != y) throw new ArgumentError('not equal');\n"
724 " }\n"
725 "}\n"
726 "class FieldsTest {\n"
727 " static Fields testMain() {\n"
728 " Expect.equals(true, Fields.bigint_sfld == 0xfffffffffff);\n"
729 " Fields obj = new Fields(10, 20);\n"
730 " Expect.equals(true, obj.bigint_fld == 0xfffffffffff);\n"
731 " return obj;\n"
732 " }\n"
733 "}\n";
734 // clang-format on
736
737 uint8_t* isolate_snapshot_data_buffer;
738
739 // Start an Isolate, load a script and create a full snapshot.
740 Timer timer1;
741 timer1.Start();
742 {
743 TestIsolateScope __test_isolate__;
744
745 // Create a test library and Load up a test script in it.
746 TestCase::LoadTestScript(kScriptChars, nullptr);
747
748 Thread* thread = Thread::Current();
749 TransitionNativeToVM transition(thread);
750 StackZone zone(thread);
751 HandleScope scope(thread);
752
754 {
755 TransitionVMToNative to_native(thread);
757 }
758 timer1.Stop();
759 OS::PrintErr("Without Snapshot: %" Pd64 "us\n", timer1.TotalElapsedTime());
760
761 // Write snapshot with object content.
763 FullSnapshotWriter writer(
764 Snapshot::kFull, /*vm_snapshot_data=*/nullptr, &isolate_snapshot_data,
765 /*vm_image_writer=*/nullptr, /*iso_image_writer=*/nullptr);
766 writer.WriteFullSnapshot();
767 // Take ownership so it doesn't get freed by the stream destructor.
768 intptr_t unused;
769 isolate_snapshot_data_buffer = isolate_snapshot_data.Steal(&unused);
770 }
771
772 // Now Create another isolate using the snapshot and execute a method
773 // from the script.
774 Timer timer2;
775 timer2.Start();
776 TestCase::CreateTestIsolateFromSnapshot(isolate_snapshot_data_buffer);
777 {
778 Dart_EnterScope(); // Start a Dart API scope for invoking API functions.
779 timer2.Stop();
780 OS::PrintErr("From Snapshot: %" Pd64 "us\n", timer2.TotalElapsedTime());
781
782 // Invoke a function which returns an object.
783 Dart_Handle cls = Dart_GetClass(TestCase::lib(), NewString("FieldsTest"));
784 result = Dart_Invoke(cls, NewString("testMain"), 0, nullptr);
787 }
789 free(isolate_snapshot_data_buffer);
790}
791
792// Helper function to call a top level Dart function and serialize the result.
793static std::unique_ptr<Message> GetSerialized(Dart_Handle lib,
794 const char* dart_function) {
796 {
798 result = Dart_Invoke(lib, NewString(dart_function), 0, nullptr);
800 }
802
803 // Serialize the object into a message.
804 return WriteMessage(/* same_group */ false, obj, ILLEGAL_PORT,
806}
807
808static void CheckString(Dart_Handle dart_string, const char* expected) {
810 String& str = String::Handle();
811 str ^= Api::UnwrapHandle(dart_string);
812 std::unique_ptr<Message> message = WriteMessage(
813 /* same_group */ false, str, ILLEGAL_PORT, Message::kNormalPriority);
814
815 // Read object back from the snapshot into a C structure.
816 ApiNativeScope scope;
818 EXPECT_NOTNULL(root);
819 EXPECT_EQ(Dart_CObject_kString, root->type);
820 EXPECT_STREQ(expected, root->value.as_string);
822}
823
824static void CheckStringInvalid(Dart_Handle dart_string) {
826 String& str = String::Handle();
827 str ^= Api::UnwrapHandle(dart_string);
828 std::unique_ptr<Message> message = WriteMessage(
829 /* same_group */ false, str, ILLEGAL_PORT, Message::kNormalPriority);
830
831 // Read object back from the snapshot into a C structure.
832 ApiNativeScope scope;
834 EXPECT_NOTNULL(root);
835 EXPECT_EQ(Dart_CObject_kUnsupported, root->type);
836}
837
838VM_UNIT_TEST_CASE(DartGeneratedMessages) {
839 static const char* kCustomIsolateScriptChars =
840 "final int kArrayLength = 10;\n"
841 "getSmi() {\n"
842 " return 42;\n"
843 "}\n"
844 "getAsciiString() {\n"
845 " return \"Hello, world!\";\n"
846 "}\n"
847 "getNonAsciiString() {\n"
848 " return \"Blåbærgrød\";\n"
849 "}\n"
850 "getNonBMPString() {\n"
851 " return \"\\u{10000}\\u{1F601}\\u{1F637}\\u{20000}\";\n"
852 "}\n"
853 "getLeadSurrogateString() {\n"
854 " return String.fromCharCodes([0xd800]);\n"
855 "}\n"
856 "getTrailSurrogateString() {\n"
857 " return \"\\u{10000}\".substring(1);\n"
858 "}\n"
859 "getSurrogatesString() {\n"
860 " return String.fromCharCodes([0xdc00, 0xdc00, 0xd800, 0xd800]);\n"
861 "}\n"
862 "getCrappyString() {\n"
863 " return String.fromCharCodes([0xd800, 32, 0xdc00, 32]);\n"
864 "}\n"
865 "getList() {\n"
866 " return List.filled(kArrayLength, null);\n"
867 "}\n";
868
870 Isolate* isolate = Isolate::Current();
871 EXPECT(isolate != nullptr);
873
874 Dart_Handle lib =
876 EXPECT_VALID(lib);
877 Dart_Handle smi_result;
878 smi_result = Dart_Invoke(lib, NewString("getSmi"), 0, nullptr);
879 EXPECT_VALID(smi_result);
880
881 Dart_Handle ascii_string_result;
882 ascii_string_result =
883 Dart_Invoke(lib, NewString("getAsciiString"), 0, nullptr);
884 EXPECT_VALID(ascii_string_result);
885 EXPECT(Dart_IsString(ascii_string_result));
886
887 Dart_Handle non_ascii_string_result;
888 non_ascii_string_result =
889 Dart_Invoke(lib, NewString("getNonAsciiString"), 0, nullptr);
890 EXPECT_VALID(non_ascii_string_result);
891 EXPECT(Dart_IsString(non_ascii_string_result));
892
893 Dart_Handle non_bmp_string_result;
894 non_bmp_string_result =
895 Dart_Invoke(lib, NewString("getNonBMPString"), 0, nullptr);
896 EXPECT_VALID(non_bmp_string_result);
897 EXPECT(Dart_IsString(non_bmp_string_result));
898
899 Dart_Handle lead_surrogate_string_result;
900 lead_surrogate_string_result =
901 Dart_Invoke(lib, NewString("getLeadSurrogateString"), 0, nullptr);
902 EXPECT_VALID(lead_surrogate_string_result);
903 EXPECT(Dart_IsString(lead_surrogate_string_result));
904
905 Dart_Handle trail_surrogate_string_result;
906 trail_surrogate_string_result =
907 Dart_Invoke(lib, NewString("getTrailSurrogateString"), 0, nullptr);
908 EXPECT_VALID(trail_surrogate_string_result);
909 EXPECT(Dart_IsString(trail_surrogate_string_result));
910
911 Dart_Handle surrogates_string_result;
912 surrogates_string_result =
913 Dart_Invoke(lib, NewString("getSurrogatesString"), 0, nullptr);
914 EXPECT_VALID(surrogates_string_result);
915 EXPECT(Dart_IsString(surrogates_string_result));
916
917 Dart_Handle crappy_string_result;
918 crappy_string_result =
919 Dart_Invoke(lib, NewString("getCrappyString"), 0, nullptr);
920 EXPECT_VALID(crappy_string_result);
921 EXPECT(Dart_IsString(crappy_string_result));
922
923 {
924 Thread* thread = Thread::Current();
925 CHECK_API_SCOPE(thread);
926 TransitionNativeToVM transition(thread);
927 HANDLESCOPE(thread);
928
929 {
930 StackZone zone(thread);
931 Smi& smi = Smi::Handle();
932 smi ^= Api::UnwrapHandle(smi_result);
933 std::unique_ptr<Message> message = WriteMessage(
934 /* same_group */ false, smi, ILLEGAL_PORT, Message::kNormalPriority);
935
936 // Read object back from the snapshot into a C structure.
937 ApiNativeScope scope;
938 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
939 EXPECT_NOTNULL(root);
940 EXPECT_EQ(Dart_CObject_kInt32, root->type);
941 EXPECT_EQ(42, root->value.as_int32);
943 }
944 CheckString(ascii_string_result, "Hello, world!");
945 CheckString(non_ascii_string_result, "Blåbærgrød");
946 CheckString(non_bmp_string_result,
947 "\xf0\x90\x80\x80"
948 "\xf0\x9f\x98\x81"
949 "\xf0\x9f\x98\xb7"
950 "\xf0\xa0\x80\x80");
951 CheckStringInvalid(lead_surrogate_string_result);
952 CheckStringInvalid(trail_surrogate_string_result);
953 CheckStringInvalid(crappy_string_result);
954 CheckStringInvalid(surrogates_string_result);
955 }
958}
959
960VM_UNIT_TEST_CASE(DartGeneratedListMessages) {
961 const int kArrayLength = 10;
962 const char* kScriptChars =
963 "final int kArrayLength = 10;\n"
964 "getList() {\n"
965 " return List.filled(kArrayLength, null);\n"
966 "}\n"
967 "getIntList() {\n"
968 " var list = List<int>.filled(kArrayLength, 0);\n"
969 " for (var i = 0; i < kArrayLength; i++) list[i] = i;\n"
970 " return list;\n"
971 "}\n"
972 "getStringList() {\n"
973 " var list = List<String>.filled(kArrayLength, '');\n"
974 " for (var i = 0; i < kArrayLength; i++) list[i] = i.toString();\n"
975 " return list;\n"
976 "}\n"
977 "getMixedList() {\n"
978 " var list = List<dynamic>.filled(kArrayLength, null);\n"
979 " list[0] = 0;\n"
980 " list[1] = '1';\n"
981 " list[2] = 2.2;\n"
982 " list[3] = true;\n"
983 " return list;\n"
984 "}\n";
985
987 Thread* thread = Thread::Current();
988 EXPECT(thread->isolate() != nullptr);
990
991 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
992 EXPECT_VALID(lib);
993
994 {
995 CHECK_API_SCOPE(thread);
996 TransitionNativeToVM transition(thread);
997 HANDLESCOPE(thread);
998 StackZone zone(thread);
999 {
1000 // Generate a list of nulls from Dart code.
1001 std::unique_ptr<Message> message = GetSerialized(lib, "getList");
1002 ApiNativeScope scope;
1003 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1004 EXPECT_NOTNULL(root);
1005 EXPECT_EQ(Dart_CObject_kArray, root->type);
1006 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1007 for (int i = 0; i < kArrayLength; i++) {
1008 EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
1009 }
1011 }
1012 {
1013 // Generate a list of ints from Dart code.
1014 std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
1015 ApiNativeScope scope;
1016 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1017 EXPECT_NOTNULL(root);
1018 EXPECT_EQ(Dart_CObject_kArray, root->type);
1019 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1020 for (int i = 0; i < kArrayLength; i++) {
1021 EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[i]->type);
1022 EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
1023 }
1025 }
1026 {
1027 // Generate a list of strings from Dart code.
1028 std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
1029 ApiNativeScope scope;
1030 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1031 EXPECT_NOTNULL(root);
1032 EXPECT_EQ(Dart_CObject_kArray, root->type);
1033 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1034 for (int i = 0; i < kArrayLength; i++) {
1035 EXPECT_EQ(Dart_CObject_kString, root->value.as_array.values[i]->type);
1036 char buffer[3];
1037 snprintf(buffer, sizeof(buffer), "%d", i);
1038 EXPECT_STREQ(buffer, root->value.as_array.values[i]->value.as_string);
1039 }
1040 }
1041 {
1042 // Generate a list of objects of different types from Dart code.
1043 std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
1044 ApiNativeScope scope;
1045 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1046 EXPECT_NOTNULL(root);
1047 EXPECT_EQ(Dart_CObject_kArray, root->type);
1048 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1049
1050 EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[0]->type);
1051 EXPECT_EQ(0, root->value.as_array.values[0]->value.as_int32);
1052 EXPECT_EQ(Dart_CObject_kString, root->value.as_array.values[1]->type);
1053 EXPECT_STREQ("1", root->value.as_array.values[1]->value.as_string);
1054 EXPECT_EQ(Dart_CObject_kDouble, root->value.as_array.values[2]->type);
1055 EXPECT_EQ(2.2, root->value.as_array.values[2]->value.as_double);
1056 EXPECT_EQ(Dart_CObject_kBool, root->value.as_array.values[3]->type);
1057 EXPECT_EQ(true, root->value.as_array.values[3]->value.as_bool);
1058
1059 for (int i = 0; i < kArrayLength; i++) {
1060 if (i > 3) {
1061 EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
1062 }
1063 }
1064 }
1065 }
1068}
1069
1070VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessages) {
1071 const int kArrayLength = 10;
1072 const char* kScriptChars =
1073 "final int kArrayLength = 10;\n"
1074 "getList() {\n"
1075 " return [null, null, null, null, null, null, null, null, null, null];\n"
1076 "}\n"
1077 "getIntList() {\n"
1078 " return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\n"
1079 "}\n"
1080 "getStringList() {\n"
1081 " return ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];\n"
1082 "}\n"
1083 "getListList() {\n"
1084 " return <dynamic>[[],"
1085 " [0],"
1086 " [0, 1],"
1087 " [0, 1, 2],"
1088 " [0, 1, 2, 3],"
1089 " [0, 1, 2, 3, 4],"
1090 " [0, 1, 2, 3, 4, 5],"
1091 " [0, 1, 2, 3, 4, 5, 6],"
1092 " [0, 1, 2, 3, 4, 5, 6, 7],"
1093 " [0, 1, 2, 3, 4, 5, 6, 7, 8]];\n"
1094 "}\n"
1095 "getMixedList() {\n"
1096 " var list = [];\n"
1097 " list.add(0);\n"
1098 " list.add('1');\n"
1099 " list.add(2.2);\n"
1100 " list.add(true);\n"
1101 " list.add([]);\n"
1102 " list.add(<dynamic>[[]]);\n"
1103 " list.add(<dynamic>[<dynamic>[[]]]);\n"
1104 " list.add(<dynamic>[1, <dynamic>[2, [3]]]);\n"
1105 " list.add(<dynamic>[1, <dynamic>[1, 2, [1, 2, 3]]]);\n"
1106 " list.add([1, 2, 3]);\n"
1107 " return list;\n"
1108 "}\n";
1109
1111 Thread* thread = Thread::Current();
1112 EXPECT(thread->isolate() != nullptr);
1114
1115 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1116 EXPECT_VALID(lib);
1117
1118 {
1119 CHECK_API_SCOPE(thread);
1120 TransitionNativeToVM transition(thread);
1121 HANDLESCOPE(thread);
1122 StackZone zone(thread);
1123 {
1124 // Generate a list of nulls from Dart code.
1125 std::unique_ptr<Message> message = GetSerialized(lib, "getList");
1126 ApiNativeScope scope;
1127 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1128 EXPECT_NOTNULL(root);
1129 EXPECT_EQ(Dart_CObject_kArray, root->type);
1130 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1131 for (int i = 0; i < kArrayLength; i++) {
1132 EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
1133 }
1135 }
1136 {
1137 // Generate a list of ints from Dart code.
1138 std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
1139 ApiNativeScope scope;
1140 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1141 EXPECT_NOTNULL(root);
1142 EXPECT_EQ(Dart_CObject_kArray, root->type);
1143 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1144 for (int i = 0; i < kArrayLength; i++) {
1145 EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[i]->type);
1146 EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
1147 }
1149 }
1150 {
1151 // Generate a list of strings from Dart code.
1152 std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
1153 ApiNativeScope scope;
1154 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1155 EXPECT_NOTNULL(root);
1156 EXPECT_EQ(Dart_CObject_kArray, root->type);
1157 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1158 for (int i = 0; i < kArrayLength; i++) {
1159 EXPECT_EQ(Dart_CObject_kString, root->value.as_array.values[i]->type);
1160 char buffer[3];
1161 snprintf(buffer, sizeof(buffer), "%d", i);
1162 EXPECT_STREQ(buffer, root->value.as_array.values[i]->value.as_string);
1163 }
1164 }
1165 {
1166 // Generate a list of lists from Dart code.
1167 std::unique_ptr<Message> message = GetSerialized(lib, "getListList");
1168 ApiNativeScope scope;
1169 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1170 EXPECT_NOTNULL(root);
1171 EXPECT_EQ(Dart_CObject_kArray, root->type);
1172 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1173 for (int i = 0; i < kArrayLength; i++) {
1174 Dart_CObject* element = root->value.as_array.values[i];
1175 EXPECT_EQ(Dart_CObject_kArray, element->type);
1176 EXPECT_EQ(i, element->value.as_array.length);
1177 for (int j = 0; j < i; j++) {
1178 EXPECT_EQ(Dart_CObject_kInt32,
1179 element->value.as_array.values[j]->type);
1180 EXPECT_EQ(j, element->value.as_array.values[j]->value.as_int32);
1181 }
1182 }
1183 }
1184 {
1185 // Generate a list of objects of different types from Dart code.
1186 std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
1187 ApiNativeScope scope;
1188 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1189 EXPECT_NOTNULL(root);
1190 EXPECT_EQ(Dart_CObject_kArray, root->type);
1191 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1192
1193 EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[0]->type);
1194 EXPECT_EQ(0, root->value.as_array.values[0]->value.as_int32);
1195 EXPECT_EQ(Dart_CObject_kString, root->value.as_array.values[1]->type);
1196 EXPECT_STREQ("1", root->value.as_array.values[1]->value.as_string);
1197 EXPECT_EQ(Dart_CObject_kDouble, root->value.as_array.values[2]->type);
1198 EXPECT_EQ(2.2, root->value.as_array.values[2]->value.as_double);
1199 EXPECT_EQ(Dart_CObject_kBool, root->value.as_array.values[3]->type);
1200 EXPECT_EQ(true, root->value.as_array.values[3]->value.as_bool);
1201
1202 for (int i = 0; i < kArrayLength; i++) {
1203 if (i > 3) {
1204 EXPECT_EQ(Dart_CObject_kArray, root->value.as_array.values[i]->type);
1205 }
1206 }
1207
1208 Dart_CObject* element;
1209 Dart_CObject* e;
1210
1211 // []
1212 element = root->value.as_array.values[4];
1213 EXPECT_EQ(0, element->value.as_array.length);
1214
1215 // [[]]
1216 element = root->value.as_array.values[5];
1217 EXPECT_EQ(1, element->value.as_array.length);
1218 element = element->value.as_array.values[0];
1219 EXPECT_EQ(Dart_CObject_kArray, element->type);
1220 EXPECT_EQ(0, element->value.as_array.length);
1221
1222 // [[[]]]"
1223 element = root->value.as_array.values[6];
1224 EXPECT_EQ(1, element->value.as_array.length);
1225 element = element->value.as_array.values[0];
1226 EXPECT_EQ(Dart_CObject_kArray, element->type);
1227 EXPECT_EQ(1, element->value.as_array.length);
1228 element = element->value.as_array.values[0];
1229 EXPECT_EQ(Dart_CObject_kArray, element->type);
1230 EXPECT_EQ(0, element->value.as_array.length);
1231
1232 // [1, [2, [3]]]
1233 element = root->value.as_array.values[7];
1234 EXPECT_EQ(2, element->value.as_array.length);
1235 e = element->value.as_array.values[0];
1236 EXPECT_EQ(Dart_CObject_kInt32, e->type);
1237 EXPECT_EQ(1, e->value.as_int32);
1238 element = element->value.as_array.values[1];
1239 EXPECT_EQ(Dart_CObject_kArray, element->type);
1240 EXPECT_EQ(2, element->value.as_array.length);
1241 e = element->value.as_array.values[0];
1242 EXPECT_EQ(Dart_CObject_kInt32, e->type);
1243 EXPECT_EQ(2, e->value.as_int32);
1244 element = element->value.as_array.values[1];
1245 EXPECT_EQ(Dart_CObject_kArray, element->type);
1246 EXPECT_EQ(1, element->value.as_array.length);
1247 e = element->value.as_array.values[0];
1248 EXPECT_EQ(Dart_CObject_kInt32, e->type);
1249 EXPECT_EQ(3, e->value.as_int32);
1250
1251 // [1, [1, 2, [1, 2, 3]]]
1252 element = root->value.as_array.values[8];
1253 EXPECT_EQ(2, element->value.as_array.length);
1254 e = element->value.as_array.values[0];
1255 EXPECT_EQ(Dart_CObject_kInt32, e->type);
1256 e = element->value.as_array.values[0];
1257 EXPECT_EQ(Dart_CObject_kInt32, e->type);
1258 EXPECT_EQ(1, e->value.as_int32);
1259 element = element->value.as_array.values[1];
1260 EXPECT_EQ(Dart_CObject_kArray, element->type);
1261 EXPECT_EQ(3, element->value.as_array.length);
1262 for (int i = 0; i < 2; i++) {
1263 e = element->value.as_array.values[i];
1264 EXPECT_EQ(Dart_CObject_kInt32, e->type);
1265 EXPECT_EQ(i + 1, e->value.as_int32);
1266 }
1267 element = element->value.as_array.values[2];
1268 EXPECT_EQ(Dart_CObject_kArray, element->type);
1269 EXPECT_EQ(3, element->value.as_array.length);
1270 for (int i = 0; i < 3; i++) {
1271 e = element->value.as_array.values[i];
1272 EXPECT_EQ(Dart_CObject_kInt32, e->type);
1273 EXPECT_EQ(i + 1, e->value.as_int32);
1274 }
1275
1276 // [1, 2, 3]
1277 element = root->value.as_array.values[9];
1278 EXPECT_EQ(3, element->value.as_array.length);
1279 for (int i = 0; i < 3; i++) {
1280 e = element->value.as_array.values[i];
1281 EXPECT_EQ(Dart_CObject_kInt32, e->type);
1282 EXPECT_EQ(i + 1, e->value.as_int32);
1283 }
1284 }
1285 }
1288}
1289
1290VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
1291 const int kArrayLength = 10;
1292 const char* kScriptChars =
1293 "import 'dart:typed_data';\n"
1294 "final int kArrayLength = 10;\n"
1295 "getStringList() {\n"
1296 " var s = 'Hello, world!';\n"
1297 " var list = List<String>.filled(kArrayLength, '');\n"
1298 " for (var i = 0; i < kArrayLength; i++) list[i] = s;\n"
1299 " return list;\n"
1300 "}\n"
1301 "getMintList() {\n"
1302 " var mint = 0x7FFFFFFFFFFFFFFF;\n"
1303 " var list = List.filled(kArrayLength, 0);\n"
1304 " for (var i = 0; i < kArrayLength; i++) list[i] = mint;\n"
1305 " return list;\n"
1306 "}\n"
1307 "getDoubleList() {\n"
1308 " var d = 3.14;\n"
1309 " var list = List<double>.filled(kArrayLength, 0.0);\n"
1310 " for (var i = 0; i < kArrayLength; i++) list[i] = d;\n"
1311 " return list;\n"
1312 "}\n"
1313 "getTypedDataList() {\n"
1314 " var byte_array = Uint8List(256);\n"
1315 " var list = List<dynamic>.filled(kArrayLength, null);\n"
1316 " for (var i = 0; i < kArrayLength; i++) list[i] = byte_array;\n"
1317 " return list;\n"
1318 "}\n"
1319 "getTypedDataViewList() {\n"
1320 " var uint8_list = Uint8List(256);\n"
1321 " uint8_list[64] = 1;\n"
1322 " var uint8_list_view =\n"
1323 " Uint8List.view(uint8_list.buffer, 64, 128);\n"
1324 " var list = List<dynamic>.filled(kArrayLength, null);\n"
1325 " for (var i = 0; i < kArrayLength; i++) list[i] = uint8_list_view;\n"
1326 " return list;\n"
1327 "}\n"
1328 "getMixedList() {\n"
1329 " var list = List<dynamic>.filled(kArrayLength, null);\n"
1330 " for (var i = 0; i < kArrayLength; i++) {\n"
1331 " list[i] = ((i % 2) == 0) ? 'A' : 2.72;\n"
1332 " }\n"
1333 " return list;\n"
1334 "}\n"
1335 "getSelfRefList() {\n"
1336 " var list = List<dynamic>.filled(kArrayLength, null, growable: true);\n"
1337 " for (var i = 0; i < kArrayLength; i++) {\n"
1338 " list[i] = list;\n"
1339 " }\n"
1340 " return list;\n"
1341 "}\n";
1342
1344 Thread* thread = Thread::Current();
1345 EXPECT(thread->isolate() != nullptr);
1347
1348 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1349 EXPECT_VALID(lib);
1350
1351 {
1352 CHECK_API_SCOPE(thread);
1353 TransitionNativeToVM transition(thread);
1354 HANDLESCOPE(thread);
1355 StackZone zone(thread);
1356 {
1357 // Generate a list of strings from Dart code.
1358 std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
1359 ApiNativeScope scope;
1360 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1361 EXPECT_NOTNULL(root);
1362 EXPECT_EQ(Dart_CObject_kArray, root->type);
1363 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1364 for (int i = 0; i < kArrayLength; i++) {
1365 Dart_CObject* element = root->value.as_array.values[i];
1366 EXPECT_EQ(root->value.as_array.values[0], element);
1367 EXPECT_EQ(Dart_CObject_kString, element->type);
1368 EXPECT_STREQ("Hello, world!", element->value.as_string);
1369 }
1370 }
1371 {
1372 // Generate a list of medium ints from Dart code.
1373 std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
1374 ApiNativeScope scope;
1375 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1376 EXPECT_NOTNULL(root);
1377 EXPECT_EQ(Dart_CObject_kArray, root->type);
1378 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1379 for (int i = 0; i < kArrayLength; i++) {
1380 Dart_CObject* element = root->value.as_array.values[i];
1381 EXPECT_EQ(root->value.as_array.values[0], element);
1382 EXPECT_EQ(Dart_CObject_kInt64, element->type);
1383 EXPECT_EQ(DART_INT64_C(0x7FFFFFFFFFFFFFFF), element->value.as_int64);
1384 }
1385 }
1386 {
1387 // Generate a list of doubles from Dart code.
1388 std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
1389 ApiNativeScope scope;
1390 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1391 EXPECT_NOTNULL(root);
1392 EXPECT_EQ(Dart_CObject_kArray, root->type);
1393 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1394 Dart_CObject* element = root->value.as_array.values[0];
1395 EXPECT_EQ(Dart_CObject_kDouble, element->type);
1396 EXPECT_EQ(3.14, element->value.as_double);
1397 for (int i = 1; i < kArrayLength; i++) {
1398 element = root->value.as_array.values[i];
1399 EXPECT_EQ(Dart_CObject_kDouble, element->type);
1400 EXPECT_EQ(3.14, element->value.as_double);
1401 }
1402 }
1403 {
1404 // Generate a list of Uint8Lists from Dart code.
1405 std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
1406 ApiNativeScope scope;
1407 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1408 EXPECT_NOTNULL(root);
1409 EXPECT_EQ(Dart_CObject_kArray, root->type);
1410 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1411 for (int i = 0; i < kArrayLength; i++) {
1412 Dart_CObject* element = root->value.as_array.values[i];
1413 EXPECT_EQ(root->value.as_array.values[0], element);
1414 EXPECT_EQ(Dart_CObject_kTypedData, element->type);
1415 EXPECT_EQ(Dart_TypedData_kUint8, element->value.as_typed_data.type);
1416 EXPECT_EQ(256, element->value.as_typed_data.length);
1417 }
1418 }
1419 {
1420 // Generate a list of Uint8List views from Dart code.
1421 std::unique_ptr<Message> message =
1422 GetSerialized(lib, "getTypedDataViewList");
1423 ApiNativeScope scope;
1424 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1425 EXPECT_NOTNULL(root);
1426 EXPECT_EQ(Dart_CObject_kArray, root->type);
1427 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1428 for (int i = 0; i < kArrayLength; i++) {
1429 Dart_CObject* element = root->value.as_array.values[i];
1430 EXPECT_EQ(root->value.as_array.values[0], element);
1431 EXPECT_EQ(Dart_CObject_kTypedData, element->type);
1432 EXPECT_EQ(Dart_TypedData_kUint8, element->value.as_typed_data.type);
1433 EXPECT_EQ(128, element->value.as_typed_data.length);
1434 EXPECT_EQ(1, element->value.as_typed_data.values[0]);
1435 EXPECT_EQ(0, element->value.as_typed_data.values[1]);
1436 }
1437 }
1438 {
1439 // Generate a list of objects of different types from Dart code.
1440 std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
1441 ApiNativeScope scope;
1442 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1443 EXPECT_NOTNULL(root);
1444 EXPECT_EQ(Dart_CObject_kArray, root->type);
1445 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1446 Dart_CObject* element = root->value.as_array.values[0];
1447 EXPECT_EQ(Dart_CObject_kString, element->type);
1448 EXPECT_STREQ("A", element->value.as_string);
1449 element = root->value.as_array.values[1];
1450 EXPECT_EQ(Dart_CObject_kDouble, element->type);
1451 EXPECT_EQ(2.72, element->value.as_double);
1452 for (int i = 2; i < kArrayLength; i++) {
1453 element = root->value.as_array.values[i];
1454 if ((i % 2) == 0) {
1455 EXPECT_EQ(root->value.as_array.values[0], element);
1456 EXPECT_EQ(Dart_CObject_kString, element->type);
1457 EXPECT_STREQ("A", element->value.as_string);
1458 } else {
1459 EXPECT_EQ(Dart_CObject_kDouble, element->type);
1460 EXPECT_EQ(2.72, element->value.as_double);
1461 }
1462 }
1463 }
1464 {
1465 // Generate a list of objects of different types from Dart code.
1466 std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
1467 ApiNativeScope scope;
1468 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1469 EXPECT_NOTNULL(root);
1470 EXPECT_EQ(Dart_CObject_kArray, root->type);
1471 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1472 for (int i = 0; i < kArrayLength; i++) {
1473 Dart_CObject* element = root->value.as_array.values[i];
1474 EXPECT_EQ(Dart_CObject_kArray, element->type);
1475 EXPECT_EQ(root, element);
1476 }
1477 }
1478 }
1481}
1482
1483VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
1484 const int kArrayLength = 10;
1485 const char* kScriptChars =
1486 "import 'dart:typed_data';\n"
1487 "final int kArrayLength = 10;\n"
1488 "getStringList() {\n"
1489 " var s = 'Hello, world!';\n"
1490 " var list = [s, s, s, s, s, s, s, s, s, s];\n"
1491 " return list;\n"
1492 "}\n"
1493 "getMintList() {\n"
1494 " var mint = 0x7FFFFFFFFFFFFFFF;\n"
1495 " var list = [mint, mint, mint, mint, mint,\n"
1496 " mint, mint, mint, mint, mint];\n"
1497 " return list;\n"
1498 "}\n"
1499 "getDoubleList() {\n"
1500 " var d = 3.14;\n"
1501 " var list = [3.14, 3.14, 3.14, 3.14, 3.14, 3.14];\n"
1502 " list.add(3.14);\n"
1503 " list.add(3.14);\n"
1504 " list.add(3.14);\n"
1505 " list.add(3.14);\n"
1506 " return list;\n"
1507 "}\n"
1508 "getTypedDataList() {\n"
1509 " var byte_array = new Uint8List(256);\n"
1510 " var list = [];\n"
1511 " for (var i = 0; i < kArrayLength; i++) {\n"
1512 " list.add(byte_array);\n"
1513 " }\n"
1514 " return list;\n"
1515 "}\n"
1516 "getTypedDataViewList() {\n"
1517 " var uint8_list = new Uint8List(256);\n"
1518 " uint8_list[64] = 1;\n"
1519 " var uint8_list_view =\n"
1520 " new Uint8List.view(uint8_list.buffer, 64, 128);\n"
1521 " var list = [];\n"
1522 " for (var i = 0; i < kArrayLength; i++) {\n"
1523 " list.add(uint8_list_view);\n"
1524 " }\n"
1525 " return list;\n"
1526 "}\n"
1527 "getMixedList() {\n"
1528 " var list = [];\n"
1529 " for (var i = 0; i < kArrayLength; i++) {\n"
1530 " list.add(((i % 2) == 0) ? '.' : 2.72);\n"
1531 " }\n"
1532 " return list;\n"
1533 "}\n"
1534 "getSelfRefList() {\n"
1535 " var list = [];\n"
1536 " for (var i = 0; i < kArrayLength; i++) {\n"
1537 " list.add(list);\n"
1538 " }\n"
1539 " return list;\n"
1540 "}\n";
1541
1543 Thread* thread = Thread::Current();
1544 EXPECT(thread->isolate() != nullptr);
1546
1547 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1548 EXPECT_VALID(lib);
1549
1550 {
1551 CHECK_API_SCOPE(thread);
1552 TransitionNativeToVM transition(thread);
1553 HANDLESCOPE(thread);
1554 StackZone zone(thread);
1555 {
1556 // Generate a list of strings from Dart code.
1557 std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
1558 ApiNativeScope scope;
1559 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1560 EXPECT_NOTNULL(root);
1561 EXPECT_EQ(Dart_CObject_kArray, root->type);
1562 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1563 for (int i = 0; i < kArrayLength; i++) {
1564 Dart_CObject* element = root->value.as_array.values[i];
1565 EXPECT_EQ(root->value.as_array.values[0], element);
1566 EXPECT_EQ(Dart_CObject_kString, element->type);
1567 EXPECT_STREQ("Hello, world!", element->value.as_string);
1568 }
1569 }
1570 {
1571 // Generate a list of medium ints from Dart code.
1572 std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
1573 ApiNativeScope scope;
1574 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1575 EXPECT_NOTNULL(root);
1576 EXPECT_EQ(Dart_CObject_kArray, root->type);
1577 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1578 for (int i = 0; i < kArrayLength; i++) {
1579 Dart_CObject* element = root->value.as_array.values[i];
1580 EXPECT_EQ(root->value.as_array.values[0], element);
1581 EXPECT_EQ(Dart_CObject_kInt64, element->type);
1582 EXPECT_EQ(DART_INT64_C(0x7FFFFFFFFFFFFFFF), element->value.as_int64);
1583 }
1584 }
1585 {
1586 // Generate a list of doubles from Dart code.
1587 std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
1588 ApiNativeScope scope;
1589 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1590 EXPECT_NOTNULL(root);
1591 EXPECT_EQ(Dart_CObject_kArray, root->type);
1592 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1593 Dart_CObject* element = root->value.as_array.values[0];
1594 EXPECT_EQ(Dart_CObject_kDouble, element->type);
1595 EXPECT_EQ(3.14, element->value.as_double);
1596 for (int i = 1; i < kArrayLength; i++) {
1597 element = root->value.as_array.values[i];
1598 EXPECT_EQ(Dart_CObject_kDouble, element->type);
1599 EXPECT_EQ(3.14, element->value.as_double);
1600 }
1601 }
1602 {
1603 // Generate a list of Uint8Lists from Dart code.
1604 std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
1605 ApiNativeScope scope;
1606 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1607 EXPECT_NOTNULL(root);
1608 EXPECT_EQ(Dart_CObject_kArray, root->type);
1609 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1610 for (int i = 0; i < kArrayLength; i++) {
1611 Dart_CObject* element = root->value.as_array.values[i];
1612 EXPECT_EQ(root->value.as_array.values[0], element);
1613 EXPECT_EQ(Dart_CObject_kTypedData, element->type);
1614 EXPECT_EQ(Dart_TypedData_kUint8, element->value.as_typed_data.type);
1615 EXPECT_EQ(256, element->value.as_typed_data.length);
1616 }
1617 }
1618 {
1619 // Generate a list of Uint8List views from Dart code.
1620 std::unique_ptr<Message> message =
1621 GetSerialized(lib, "getTypedDataViewList");
1622 ApiNativeScope scope;
1623 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1624 EXPECT_NOTNULL(root);
1625 EXPECT_EQ(Dart_CObject_kArray, root->type);
1626 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1627 for (int i = 0; i < kArrayLength; i++) {
1628 Dart_CObject* element = root->value.as_array.values[i];
1629 EXPECT_EQ(root->value.as_array.values[0], element);
1630 EXPECT_EQ(Dart_CObject_kTypedData, element->type);
1631 EXPECT_EQ(Dart_TypedData_kUint8, element->value.as_typed_data.type);
1632 EXPECT_EQ(128, element->value.as_typed_data.length);
1633 EXPECT_EQ(1, element->value.as_typed_data.values[0]);
1634 EXPECT_EQ(0, element->value.as_typed_data.values[1]);
1635 }
1636 }
1637 {
1638 // Generate a list of objects of different types from Dart code.
1639 std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
1640 ApiNativeScope scope;
1641 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1642 EXPECT_NOTNULL(root);
1643 EXPECT_EQ(Dart_CObject_kArray, root->type);
1644 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1645 Dart_CObject* element = root->value.as_array.values[0];
1646 EXPECT_EQ(Dart_CObject_kString, element->type);
1647 EXPECT_STREQ(".", element->value.as_string);
1648 element = root->value.as_array.values[1];
1649 EXPECT_EQ(Dart_CObject_kDouble, element->type);
1650 EXPECT_EQ(2.72, element->value.as_double);
1651 for (int i = 2; i < kArrayLength; i++) {
1652 Dart_CObject* element = root->value.as_array.values[i];
1653 if ((i % 2) == 0) {
1654 EXPECT_EQ(root->value.as_array.values[0], element);
1655 EXPECT_EQ(Dart_CObject_kString, element->type);
1656 EXPECT_STREQ(".", element->value.as_string);
1657 } else {
1658 EXPECT_EQ(Dart_CObject_kDouble, element->type);
1659 EXPECT_EQ(2.72, element->value.as_double);
1660 }
1661 }
1662 }
1663 {
1664 // Generate a list of objects of different types from Dart code.
1665 std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
1666 ApiNativeScope scope;
1667 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1668 EXPECT_NOTNULL(root);
1669 EXPECT_EQ(Dart_CObject_kArray, root->type);
1670 EXPECT_EQ(kArrayLength, root->value.as_array.length);
1671 for (int i = 0; i < kArrayLength; i++) {
1672 Dart_CObject* element = root->value.as_array.values[i];
1673 EXPECT_EQ(Dart_CObject_kArray, element->type);
1674 EXPECT_EQ(root, element);
1675 }
1676 }
1677 }
1680}
1681
1682static void CheckTypedData(Dart_CObject* object,
1683 Dart_TypedData_Type typed_data_type,
1684 int len) {
1685 EXPECT_EQ(Dart_CObject_kTypedData, object->type);
1686 EXPECT_EQ(typed_data_type, object->value.as_typed_data.type);
1687 EXPECT_EQ(len, object->value.as_typed_data.length);
1688}
1689
1690VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithTypedData) {
1691 static const char* kScriptChars =
1692 "import 'dart:typed_data';\n"
1693 "getTypedDataList() {\n"
1694 " var list = List<dynamic>.filled(13, null);\n"
1695 " var index = 0;\n"
1696 " list[index++] = Int8List(256);\n"
1697 " list[index++] = Uint8List(256);\n"
1698 " list[index++] = Int16List(256);\n"
1699 " list[index++] = Uint16List(256);\n"
1700 " list[index++] = Int32List(256);\n"
1701 " list[index++] = Uint32List(256);\n"
1702 " list[index++] = Int64List(256);\n"
1703 " list[index++] = Uint64List(256);\n"
1704 " list[index++] = Float32List(256);\n"
1705 " list[index++] = Float64List(256);\n"
1706 " list[index++] = Int32x4List(256);\n"
1707 " list[index++] = Float32x4List(256);\n"
1708 " list[index++] = Float64x2List(256);\n"
1709 " return list;\n"
1710 "}\n"
1711 "getTypedDataViewList() {\n"
1712 " var list = List<dynamic>.filled(45, null);\n"
1713 " var index = 0;\n"
1714 " list[index++] = Int8List.view(Int8List(256).buffer);\n"
1715 " list[index++] = Uint8List.view(Uint8List(256).buffer);\n"
1716 " list[index++] = Int16List.view(new Int16List(256).buffer);\n"
1717 " list[index++] = Uint16List.view(new Uint16List(256).buffer);\n"
1718 " list[index++] = Int32List.view(new Int32List(256).buffer);\n"
1719 " list[index++] = Uint32List.view(new Uint32List(256).buffer);\n"
1720 " list[index++] = Int64List.view(new Int64List(256).buffer);\n"
1721 " list[index++] = Uint64List.view(new Uint64List(256).buffer);\n"
1722 " list[index++] = Float32List.view(new Float32List(256).buffer);\n"
1723 " list[index++] = Float64List.view(new Float64List(256).buffer);\n"
1724 " list[index++] = Int32x4List.view(new Int32x4List(256).buffer);\n"
1725 " list[index++] = Float32x4List.view(new Float32x4List(256).buffer);\n"
1726 " list[index++] = Float64x2List.view(new Float64x2List(256).buffer);\n"
1727
1728 " list[index++] = Int8List.view(new Int16List(256).buffer);\n"
1729 " list[index++] = Uint8List.view(new Uint16List(256).buffer);\n"
1730 " list[index++] = Int8List.view(new Int32List(256).buffer);\n"
1731 " list[index++] = Uint8List.view(new Uint32List(256).buffer);\n"
1732 " list[index++] = Int8List.view(new Int64List(256).buffer);\n"
1733 " list[index++] = Uint8List.view(new Uint64List(256).buffer);\n"
1734 " list[index++] = Int8List.view(new Float32List(256).buffer);\n"
1735 " list[index++] = Uint8List.view(new Float32List(256).buffer);\n"
1736 " list[index++] = Int8List.view(new Float64List(256).buffer);\n"
1737 " list[index++] = Uint8List.view(new Float64List(256).buffer);\n"
1738 " list[index++] = Int8List.view(new Int32x4List(256).buffer);\n"
1739 " list[index++] = Uint8List.view(new Int32x4List(256).buffer);\n"
1740 " list[index++] = Int8List.view(new Float32x4List(256).buffer);\n"
1741 " list[index++] = Uint8List.view(new Float32x4List(256).buffer);\n"
1742 " list[index++] = Int8List.view(new Float64x2List(256).buffer);\n"
1743 " list[index++] = Uint8List.view(new Float64x2List(256).buffer);\n"
1744
1745 " list[index++] = Int16List.view(new Int8List(256).buffer);\n"
1746 " list[index++] = Uint16List.view(new Uint8List(256).buffer);\n"
1747 " list[index++] = Int16List.view(new Int32List(256).buffer);\n"
1748 " list[index++] = Uint16List.view(new Uint32List(256).buffer);\n"
1749 " list[index++] = Int16List.view(new Int64List(256).buffer);\n"
1750 " list[index++] = Uint16List.view(new Uint64List(256).buffer);\n"
1751 " list[index++] = Int16List.view(new Float32List(256).buffer);\n"
1752 " list[index++] = Uint16List.view(new Float32List(256).buffer);\n"
1753 " list[index++] = Int16List.view(new Float64List(256).buffer);\n"
1754 " list[index++] = Uint16List.view(new Float64List(256).buffer);\n"
1755 " list[index++] = Int16List.view(new Int32x4List(256).buffer);\n"
1756 " list[index++] = Uint16List.view(new Int32x4List(256).buffer);\n"
1757 " list[index++] = Int16List.view(new Float32x4List(256).buffer);\n"
1758 " list[index++] = Uint16List.view(new Float32x4List(256).buffer);\n"
1759 " list[index++] = Int16List.view(new Float64x2List(256).buffer);\n"
1760 " list[index++] = Uint16List.view(new Float64x2List(256).buffer);\n"
1761 " return list;\n"
1762 "}\n"
1763 "getMultipleTypedDataViewList() {\n"
1764 " var list = List<dynamic>.filled(13, null);\n"
1765 " var index = 0;\n"
1766 " var data = Uint8List(256).buffer;\n"
1767 " list[index++] = Int8List.view(data);\n"
1768 " list[index++] = Uint8List.view(data);\n"
1769 " list[index++] = Int16List.view(data);\n"
1770 " list[index++] = Uint16List.view(data);\n"
1771 " list[index++] = Int32List.view(data);\n"
1772 " list[index++] = Uint32List.view(data);\n"
1773 " list[index++] = Int64List.view(data);\n"
1774 " list[index++] = Uint64List.view(data);\n"
1775 " list[index++] = Float32List.view(data);\n"
1776 " list[index++] = Float64List.view(data);\n"
1777 " list[index++] = Int32x4List.view(data);\n"
1778 " list[index++] = Float32x4List.view(data);\n"
1779 " list[index++] = Float64x2List.view(data);\n"
1780 " return list;\n"
1781 "}\n";
1782
1784 Thread* thread = Thread::Current();
1785 EXPECT(thread->isolate() != nullptr);
1787
1788 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1789 EXPECT_VALID(lib);
1790
1791 {
1792 CHECK_API_SCOPE(thread);
1793 TransitionNativeToVM transition(thread);
1794 HANDLESCOPE(thread);
1795 StackZone zone(thread);
1796 {
1797 // Generate a list of Uint8Lists from Dart code.
1798 std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
1799 ApiNativeScope scope;
1800 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1801 EXPECT_NOTNULL(root);
1802 EXPECT_EQ(Dart_CObject_kArray, root->type);
1803 struct {
1805 int size;
1806 } expected[] = {
1814
1815 int i = 0;
1816 while (expected[i].type != Dart_TypedData_kInvalid) {
1817 CheckTypedData(root->value.as_array.values[i], expected[i].type,
1818 expected[i].size);
1819 i++;
1820 }
1821 EXPECT_EQ(i, root->value.as_array.length);
1822 }
1823 {
1824 // Generate a list of Uint8List views from Dart code.
1825 std::unique_ptr<Message> message =
1826 GetSerialized(lib, "getTypedDataViewList");
1827 ApiNativeScope scope;
1828 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1829 EXPECT_NOTNULL(root);
1830 EXPECT_EQ(Dart_CObject_kArray, root->type);
1831 struct {
1833 int size;
1834 } expected[] = {
1842
1851
1860
1862
1863 int i = 0;
1864 while (expected[i].type != Dart_TypedData_kInvalid) {
1865 CheckTypedData(root->value.as_array.values[i], expected[i].type,
1866 expected[i].size);
1867 i++;
1868 }
1869 EXPECT_EQ(i, root->value.as_array.length);
1870 }
1871 {
1872 // Generate a list of Uint8Lists from Dart code.
1873 std::unique_ptr<Message> message =
1874 GetSerialized(lib, "getMultipleTypedDataViewList");
1875 ApiNativeScope scope;
1876 Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
1877 EXPECT_NOTNULL(root);
1878 EXPECT_EQ(Dart_CObject_kArray, root->type);
1879 struct {
1881 int size;
1882 } expected[] = {
1890
1891 int i = 0;
1892 while (expected[i].type != Dart_TypedData_kInvalid) {
1893 CheckTypedData(root->value.as_array.values[i], expected[i].type,
1894 expected[i].size);
1895
1896 // All views point to the same data.
1897 EXPECT_EQ(root->value.as_array.values[0]->value.as_typed_data.values,
1898 root->value.as_array.values[i]->value.as_typed_data.values);
1899 i++;
1900 }
1901 EXPECT_EQ(i, root->value.as_array.length);
1902 }
1903 }
1906}
1907
1908static void MallocFinalizer(void* isolate_callback_data, void* peer) {
1909 free(peer);
1910}
1911static void NoopFinalizer(void* isolate_callback_data, void* peer) {}
1912
1913VM_UNIT_TEST_CASE(PostCObject) {
1914 // Create a native port for posting from C to Dart
1915 TestIsolateScope __test_isolate__;
1916 const char* kScriptChars =
1917 "import 'dart:isolate';\n"
1918 "main() {\n"
1919 " var messageCount = 0;\n"
1920 " var exception = '';\n"
1921 " var port = new RawReceivePort();\n"
1922 " var sendPort = port.sendPort;\n"
1923 " port.handler = (message) {\n"
1924 " if (messageCount < 9) {\n"
1925 " exception = '$exception${message}';\n"
1926 " } else {\n"
1927 " exception = '$exception${message.length}';\n"
1928 " for (int i = 0; i < message.length; i++) {\n"
1929 " exception = '$exception${message[i]}';\n"
1930 " }\n"
1931 " }\n"
1932 " messageCount++;\n"
1933 " if (messageCount == 13) throw new Exception(exception);\n"
1934 " };\n"
1935 " return sendPort;\n"
1936 "}\n";
1937 Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
1939
1940 Dart_Handle send_port = Dart_Invoke(lib, NewString("main"), 0, nullptr);
1941 EXPECT_VALID(send_port);
1942 Dart_Port port_id;
1943 Dart_Handle result = Dart_SendPortGetId(send_port, &port_id);
1945
1946 // Setup single object message.
1947 Dart_CObject object;
1948
1949 object.type = Dart_CObject_kNull;
1950 EXPECT(Dart_PostCObject(port_id, &object));
1951
1952 object.type = Dart_CObject_kBool;
1953 object.value.as_bool = true;
1954 EXPECT(Dart_PostCObject(port_id, &object));
1955
1956 object.type = Dart_CObject_kBool;
1957 object.value.as_bool = false;
1958 EXPECT(Dart_PostCObject(port_id, &object));
1959
1960 object.type = Dart_CObject_kInt32;
1961 object.value.as_int32 = 123;
1962 EXPECT(Dart_PostCObject(port_id, &object));
1963
1964 object.type = Dart_CObject_kString;
1965 object.value.as_string = const_cast<char*>("456");
1966 EXPECT(Dart_PostCObject(port_id, &object));
1967
1968 object.type = Dart_CObject_kString;
1969 object.value.as_string = const_cast<char*>("æøå");
1970 EXPECT(Dart_PostCObject(port_id, &object));
1971
1972 object.type = Dart_CObject_kString;
1973 object.value.as_string = const_cast<char*>("");
1974 EXPECT(Dart_PostCObject(port_id, &object));
1975
1976 object.type = Dart_CObject_kDouble;
1977 object.value.as_double = 3.14;
1978 EXPECT(Dart_PostCObject(port_id, &object));
1979
1980 object.type = Dart_CObject_kArray;
1981 object.value.as_array.length = 0;
1982 EXPECT(Dart_PostCObject(port_id, &object));
1983
1984 const int kArrayLength = 10;
1985 Dart_CObject* array = reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(
1986 sizeof(Dart_CObject) + sizeof(Dart_CObject*) * kArrayLength)); // NOLINT
1987 array->type = Dart_CObject_kArray;
1988 array->value.as_array.length = kArrayLength;
1989 array->value.as_array.values = reinterpret_cast<Dart_CObject**>(array + 1);
1990 for (int i = 0; i < kArrayLength; i++) {
1991 Dart_CObject* element = reinterpret_cast<Dart_CObject*>(
1993 element->type = Dart_CObject_kInt32;
1994 element->value.as_int32 = i;
1995 array->value.as_array.values[i] = element;
1996 }
1997 EXPECT(Dart_PostCObject(port_id, array));
1998
1999 object.type = Dart_CObject_kTypedData;
2000 object.value.as_typed_data.type = Dart_TypedData_kUint8;
2001 uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
2002 object.value.as_typed_data.length = ARRAY_SIZE(data);
2003 object.value.as_typed_data.values = data;
2004 EXPECT(Dart_PostCObject(port_id, &object));
2005
2006 object.type = Dart_CObject_kExternalTypedData;
2007 object.value.as_typed_data.type = Dart_TypedData_kUint8;
2008 uint8_t* external_data = reinterpret_cast<uint8_t*>(malloc(sizeof(data)));
2009 memmove(external_data, data, sizeof(data));
2010 object.value.as_external_typed_data.length = ARRAY_SIZE(data);
2011 object.value.as_external_typed_data.data = external_data;
2012 object.value.as_external_typed_data.peer = external_data;
2013 object.value.as_external_typed_data.callback = MallocFinalizer;
2014 EXPECT(Dart_PostCObject(port_id, &object));
2015
2017 object.value.as_typed_data.type = Dart_TypedData_kUint8;
2018 static const uint8_t unmodifiable_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
2019 object.value.as_external_typed_data.length = ARRAY_SIZE(unmodifiable_data);
2020 object.value.as_external_typed_data.data =
2021 const_cast<uint8_t*>(unmodifiable_data);
2022 object.value.as_external_typed_data.peer = nullptr;
2023 object.value.as_external_typed_data.callback = NoopFinalizer;
2024 EXPECT(Dart_PostCObject(port_id, &object));
2025
2026 result = Dart_RunLoop();
2029 EXPECT_SUBSTRING(
2030 "Exception: "
2031 "nulltruefalse123456æøå3.14[]"
2032 "100123456789901234567890123456789012345678\n",
2034
2036}
2037
2038TEST_CASE(IsKernelNegative) {
2039 EXPECT(!Dart_IsKernel(nullptr, 0));
2040
2041 uint8_t buffer[4] = {0, 0, 0, 0};
2043}
2044
2045} // namespace dart
static bool unused
#define EXPECT(type, expectedAlignment, expectedSize)
GLenum type
static ObjectPtr UnwrapHandle(Dart_Handle object)
static Dart_Handle CheckAndFinalizePendingClasses(Thread *thread)
static constexpr intptr_t kMaxElements
Definition: object.h:10924
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
Definition: object.h:10959
virtual bool CanonicalizeEquals(const Instance &other) const
Definition: object.cc:24702
void SetAt(intptr_t index, const Object &value) const
Definition: object.h:10880
static const Bool & False()
Definition: object.h:10799
static const Bool & True()
Definition: object.h:10797
uint64_t Id() const
Definition: object.h:12417
static CapabilityPtr New(uint64_t id, Heap::Space space=Heap::kNew)
Definition: object.cc:25773
static DoublePtr New(double d, Heap::Space space=Heap::kNew)
Definition: object.cc:23402
double value() const
Definition: object.h:10115
static intptr_t MaxElements(intptr_t class_id)
Definition: object.h:11744
void WriteFullSnapshot(GrowableArray< LoadingUnitSerializationData * > *data=nullptr)
static constexpr intptr_t kInitialSize
Definition: app_snapshot.h:110
static IntegerPtr New(const String &str, Heap::Space space=Heap::kNew)
Definition: object.cc:22984
static Isolate * Current()
Definition: isolate.h:986
@ kNormalPriority
Definition: message.h:28
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static ClassPtr pc_descriptors_class()
Definition: object.h:540
static ClassPtr class_class()
Definition: object.h:513
static ClassPtr exception_handlers_class()
Definition: object.h:546
static ClassPtr instructions_class()
Definition: object.h:532
ObjectPtr ptr() const
Definition: object.h:332
static ClassPtr type_arguments_class()
Definition: object.h:517
static ClassPtr context_class()
Definition: object.h:549
static ClassPtr code_class()
Definition: object.h:531
virtual const char * ToCString() const
Definition: object.h:366
static ClassPtr library_class()
Definition: object.h:526
static ClassPtr field_class()
Definition: object.h:524
static ClassPtr script_class()
Definition: object.h:525
bool IsNull() const
Definition: object.h:363
static ClassPtr context_scope_class()
Definition: object.h:550
static Object & Handle()
Definition: object.h:407
static ClassPtr function_class()
Definition: object.h:519
static SmiPtr New(intptr_t value)
Definition: object.h:10006
intptr_t Value() const
Definition: object.h:9990
static constexpr intptr_t kMaxValue
Definition: object.h:9987
static constexpr intptr_t kMinValue
Definition: object.h:9988
Zone * GetZone()
Definition: zone.h:213
bool Equals(const String &str) const
Definition: object.h:13337
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition: object.cc:23698
static Dart_Handle lib()
Definition: unit_test.cc:643
static Dart_Handle LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true, bool allow_compile_errors=false)
Definition: unit_test.cc:436
static Dart_Isolate CreateTestIsolate(const char *name=nullptr, void *isolate_group_data=nullptr, void *isolate_data=nullptr)
Definition: unit_test.cc:140
static Dart_Isolate CreateTestIsolateFromSnapshot(uint8_t *buffer, const char *name=nullptr)
Definition: unit_test.h:381
static Thread * Current()
Definition: thread.h:362
Isolate * isolate() const
Definition: thread.h:534
void Stop()
Definition: timer.h:117
void Start()
Definition: timer.h:111
int64_t TotalElapsedTime() const
Definition: timer.h:123
static TypePtr ObjectType()
static bool IsTypedData(const Instance &obj)
Definition: object.h:11703
static intptr_t MaxElements(intptr_t class_id)
Definition: object.h:11684
static TypedDataPtr New(intptr_t class_id, intptr_t len, Heap::Space space=Heap::kNew)
Definition: object.cc:25587
static bool IsValid(const uint8_t *utf8_array, intptr_t array_len)
Definition: unicode.cc:70
#define ILLEGAL_PORT
Definition: dart_api.h:1535
int64_t Dart_Port
Definition: dart_api.h:1525
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
Dart_TypedData_Type
Definition: dart_api.h:2612
@ Dart_TypedData_kFloat32x4
Definition: dart_api.h:2626
@ Dart_TypedData_kInt32x4
Definition: dart_api.h:2625
@ Dart_TypedData_kUint8
Definition: dart_api.h:2615
@ Dart_TypedData_kUint32
Definition: dart_api.h:2620
@ Dart_TypedData_kInt32
Definition: dart_api.h:2619
@ Dart_TypedData_kUint16
Definition: dart_api.h:2618
@ Dart_TypedData_kFloat64x2
Definition: dart_api.h:2627
@ Dart_TypedData_kUint64
Definition: dart_api.h:2622
@ Dart_TypedData_kFloat32
Definition: dart_api.h:2623
@ Dart_TypedData_kInt16
Definition: dart_api.h:2617
@ Dart_TypedData_kFloat64
Definition: dart_api.h:2624
@ Dart_TypedData_kInt8
Definition: dart_api.h:2614
@ Dart_TypedData_kInt64
Definition: dart_api.h:2621
@ Dart_TypedData_kInvalid
Definition: dart_api.h:2628
#define CHECK_API_SCOPE(thread)
Definition: dart_api_impl.h:64
@ Dart_CObject_kInt64
@ Dart_CObject_kNumberOfTypes
@ Dart_CObject_kDouble
@ Dart_CObject_kUnmodifiableExternalTypedData
@ Dart_CObject_kTypedData
@ Dart_CObject_kString
@ Dart_CObject_kArray
@ Dart_CObject_kUnsupported
@ Dart_CObject_kNull
@ Dart_CObject_kExternalTypedData
@ Dart_CObject_kInt32
@ Dart_CObject_kBool
@ Dart_CObject_kCapability
#define ASSERT(E)
uint8_t value
GAsyncResult * result
#define HANDLESCOPE(thread)
Definition: handles.h:321
Win32Message message
const uint8_t * isolate_snapshot_data
Definition: gen_snapshot.cc:69
Definition: dart_vm.cc:33
constexpr int64_t kMaxInt64
Definition: globals.h:486
static bool Equals(const Object &expected, const Object &actual)
constexpr int64_t kMinInt64
Definition: globals.h:485
ObjectPtr ReadMessage(Thread *thread, Message *message)
DART_EXPORT void Dart_EnterScope()
static std::unique_ptr< Message > GetSerialized(Dart_Handle lib, const char *dart_function)
DART_EXPORT bool Dart_ErrorHasException(Dart_Handle handle)
static void CheckStringInvalid(Dart_Handle dart_string)
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT bool Dart_IsKernel(const uint8_t *buffer, intptr_t buffer_size)
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library, Dart_Handle class_name)
constexpr int32_t kMinInt32
Definition: globals.h:482
void * malloc(size_t size)
Definition: allocation.cc:19
void TestString(BaseTextBuffer *f, LoopInfo *loop, const GrowableArray< BlockEntryInstr * > &preorder)
Definition: loops_test.cc:27
DART_EXPORT const char * Dart_GetError(Dart_Handle handle)
DART_EXPORT uint8_t * Dart_ScopeAllocate(intptr_t size)
Dart_CObject * SerializeAndDeserializeMint(Zone *zone, const Mint &mint)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
void CheckMint(int64_t value)
static void CompareDartCObjects(Dart_CObject *first, Dart_CObject *second)
static void CheckEncodeDecodeMessage(Zone *zone, Dart_CObject *root)
static void CheckString(Dart_Handle dart_string, const char *expected)
Dart_CObject * ReadApiMessage(Zone *zone, Message *message)
static const char * kCustomIsolateScriptChars
ISOLATE_UNIT_TEST_CASE(StackAllocatedDestruction)
TEST_CASE(DirectoryCurrent)
Dart_Handle NewString(const char *str)
DART_EXPORT Dart_Handle Dart_RunLoop()
DART_EXPORT void Dart_ExitScope()
std::unique_ptr< Message > WriteMessage(bool same_group, const Object &obj, Dart_Port dest_port, Message::Priority priority)
static void NoopFinalizer(void *isolate_callback_data, void *peer)
Definition: heap_test.cc:436
constexpr int32_t kMaxInt32
Definition: globals.h:483
std::unique_ptr< Message > WriteApiMessage(Zone *zone, Dart_CObject *obj, Dart_Port dest_port, Message::Priority priority)
DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject *message)
DART_EXPORT bool Dart_IsString(Dart_Handle object)
static int8_t data[kExtLength]
static void MallocFinalizer(void *isolate_callback_data, void *peer)
DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port, Dart_Port *port_id)
DART_EXPORT void Dart_ShutdownIsolate()
static void CheckTypedData(Dart_CObject *object, Dart_TypedData_Type typed_data_type, int len)
VM_UNIT_TEST_CASE(DirectoryCurrentNoScope)
static void ExpectEncodeFail(Zone *zone, Dart_CObject *root)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
string root
Definition: scale_cpu.py:20
#define Pd64
Definition: globals.h:416
#define DART_INT64_C(x)
Definition: globals.h:433
#define TEST_EXTERNAL_TYPED_ARRAY(darttype, ctype)
#define TEST_TYPED_ARRAY(darttype, ctype)
#define TEST_UNMODIFIABLE_EXTERNAL_TYPED_ARRAY(darttype, ctype)
#define TEST_ROUND_TRIP_IDENTICAL(object)
union _Dart_CObject::@86 value
Dart_CObject_Type type
struct _Dart_CObject::@86::@88 as_capability
struct _Dart_CObject::@86::@90 as_typed_data
const char * as_string
struct _Dart_CObject::@86::@89 as_array
struct _Dart_CObject ** values
#define EXPECT_VALID(handle)
Definition: unit_test.h:643
#define ARRAY_SIZE(array)
Definition: globals.h:72