Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
directory.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 <cstdlib>
6#include <memory>
7
8#include "bin/directory.h"
9
10#include "bin/dartutils.h"
11#include "bin/io_buffer.h"
12#include "bin/namespace.h"
14#include "bin/utils.h"
15#include "include/dart_api.h"
16#include "platform/assert.h"
17#include "platform/syslog.h"
18
19namespace dart {
20namespace bin {
21
22char* Directory::system_temp_path_override_ = nullptr;
23
26 const char* current = Directory::Current(namespc);
27 if (current != nullptr) {
30 } else {
32 }
33}
34
45
47 const int kExists = 1;
48 const int kDoesNotExist = 0;
54 } else if (result == Directory::DOES_NOT_EXIST) {
55 Dart_SetIntegerReturnValue(args, kDoesNotExist);
56 } else {
58 }
59}
60
71
78
90
102
114
118 // The list that we should fill.
121 Dart_Handle dart_error;
122 const char* name;
123 {
124 TypedDataScope data(path);
126 // We need to release our typed data before creating SyncDirectoryListing
127 // since it allocates objects which require us to not be holding typed data
128 // that has been acquired.
129 name = data.GetScopedCString();
130 }
131 {
132 // Pass the list that should hold the directory listing to the
133 // SyncDirectoryListing object, which adds elements to it.
134 SyncDirectoryListing sync_listing(
135 results, namespc, name, DartUtils::GetNativeBooleanArgument(args, 3),
137 Directory::List(&sync_listing);
138 dart_error = sync_listing.dart_error();
139 }
140 if (Dart_IsError(dart_error)) {
141 Dart_PropagateError(dart_error);
142 } else if (!Dart_IsNull(dart_error)) {
143 Dart_ThrowException(dart_error);
144 }
145}
146
147static constexpr int kAsyncDirectoryListerFieldIndex = 0;
148
151 AsyncDirectoryListing* listing;
153 ASSERT(Dart_IsInstance(dart_this));
156 reinterpret_cast<intptr_t*>(&listing)));
157 if (listing != nullptr) {
158 intptr_t listing_pointer = reinterpret_cast<intptr_t>(listing);
159 // Increment the listing's reference count. This native should only be
160 // be called when we are about to send the AsyncDirectoryListing* to the
161 // IO service.
162 listing->Retain();
163 Dart_SetReturnValue(args, Dart_NewInteger(listing_pointer));
164 }
165}
166
167static void ReleaseListing(void* isolate_callback_data, void* peer) {
168 AsyncDirectoryListing* listing =
169 reinterpret_cast<AsyncDirectoryListing*>(peer);
170 listing->Release();
171}
172
176 intptr_t listing_pointer =
178 AsyncDirectoryListing* listing =
179 reinterpret_cast<AsyncDirectoryListing*>(listing_pointer);
180 Dart_NewFinalizableHandle(dart_this, reinterpret_cast<void*>(listing),
181 sizeof(*listing), ReleaseListing);
183 dart_this, kAsyncDirectoryListerFieldIndex, listing_pointer);
185}
186
187void Directory::SetSystemTemp(const char* path) {
188 if (system_temp_path_override_ != nullptr) {
189 free(system_temp_path_override_);
190 system_temp_path_override_ = nullptr;
191 }
192 if (path != nullptr) {
193 system_temp_path_override_ = Utils::StrDup(path);
194 }
195}
196
198 CObjectIntptr value(cobject);
199 return reinterpret_cast<Namespace*>(value.Value());
200}
201
203 if ((request.Length() < 1) || !request[0]->IsIntptr()) {
205 }
206 Namespace* namespc = CObjectToNamespacePointer(request[0]);
208 if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
210 }
211 CObjectUint8Array path(request[1]);
212 return Directory::Create(namespc,
213 reinterpret_cast<const char*>(path.Buffer()))
214 ? CObject::True()
216}
217
219 if ((request.Length() < 1) || !request[0]->IsIntptr()) {
221 }
222 Namespace* namespc = CObjectToNamespacePointer(request[0]);
224 if ((request.Length() != 3) || !request[1]->IsUint8Array() ||
225 !request[2]->IsBool()) {
227 }
228 CObjectUint8Array path(request[1]);
229 CObjectBool recursive(request[2]);
230 return Directory::Delete(namespc,
231 reinterpret_cast<const char*>(path.Buffer()),
232 recursive.Value())
233 ? CObject::True()
235}
236
238 const int kExists = 1;
239 const int kDoesNotExist = 0;
240 if ((request.Length() < 1) || !request[0]->IsIntptr()) {
242 }
243 Namespace* namespc = CObjectToNamespacePointer(request[0]);
245 if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
247 }
248 CObjectUint8Array path(request[1]);
250 Directory::Exists(namespc, reinterpret_cast<const char*>(path.Buffer()));
251 if (result == Directory::EXISTS) {
252 return new CObjectInt32(CObject::NewInt32(kExists));
253 } else if (result == Directory::DOES_NOT_EXIST) {
254 return new CObjectInt32(CObject::NewInt32(kDoesNotExist));
255 } else {
256 return CObject::NewOSError();
257 }
258}
259
261 if ((request.Length() < 1) || !request[0]->IsIntptr()) {
263 }
264 Namespace* namespc = CObjectToNamespacePointer(request[0]);
266 if ((request.Length() != 2) || !request[1]->IsUint8Array()) {
268 }
269 CObjectUint8Array path(request[1]);
270 const char* result = Directory::CreateTemp(
271 namespc, reinterpret_cast<const char*>(path.Buffer()));
272 if (result == nullptr) {
273 return CObject::NewOSError();
274 }
276}
277
279 // Respond with an illegal argument list error message.
281 error->SetAt(0, new CObjectInt32(
283 error->SetAt(1, CObject::Null());
285 return error;
286}
287
289 if ((request.Length() < 1) || !request[0]->IsIntptr()) {
291 }
292 Namespace* namespc = CObjectToNamespacePointer(request[0]);
294 if ((request.Length() != 4) || !request[1]->IsUint8Array() ||
295 !request[2]->IsBool() || !request[3]->IsBool()) {
297 }
298 CObjectUint8Array path(request[1]);
299 CObjectBool recursive(request[2]);
300 CObjectBool follow_links(request[3]);
302 namespc, reinterpret_cast<const char*>(path.Buffer()), recursive.Value(),
303 follow_links.Value());
304 if (dir_listing->error()) {
305 // Report error now, so we capture the correct OSError.
307 dir_listing->Release();
309 error->SetAt(0, new CObjectInt32(
311 error->SetAt(1, request[1]);
312 error->SetAt(2, err);
313 return error;
314 }
315 // TODO(ajohnsen): Consider returning the first few results.
316 return new CObjectIntptr(
317 CObject::NewIntptr(reinterpret_cast<intptr_t>(dir_listing)));
318}
319
321 if ((request.Length() != 1) || !request[0]->IsIntptr()) {
323 }
324 CObjectIntptr ptr(request[0]);
325 AsyncDirectoryListing* dir_listing =
326 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
328 if (dir_listing->IsEmpty()) {
329 return new CObjectArray(CObject::NewArray(0));
330 }
331 const int kArraySize = 128;
333 dir_listing->SetArray(response, kArraySize);
334 Directory::List(dir_listing);
335 // In case the listing ended before it hit the buffer length, we need to
336 // override the array length.
337 response->AsApiCObject()->value.as_array.length = dir_listing->index();
338 return response;
339}
340
342 if ((request.Length() != 1) || !request[0]->IsIntptr()) {
344 }
345 CObjectIntptr ptr(request[0]);
346 AsyncDirectoryListing* dir_listing =
347 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
349
350 // We have retained a reference to the listing here. Therefore the listing's
351 // destructor can't be running. Since no further requests are dispatched by
352 // the Dart code after an async stop call, this PopAll() can't be racing
353 // with any other call on the listing. We don't do an extra Release(), and
354 // we don't delete the weak persistent handle. The file is closed here, but
355 // the memory for the listing will be cleaned up when the finalizer runs.
356 dir_listing->PopAll();
357 return new CObjectBool(CObject::Bool(true));
358}
359
361 if ((request.Length() < 1) || !request[0]->IsIntptr()) {
363 }
364 Namespace* namespc = CObjectToNamespacePointer(request[0]);
366 if ((request.Length() != 3) || !request[1]->IsUint8Array() ||
367 !request[2]->IsString()) {
369 }
370 CObjectUint8Array path(request[1]);
371 CObjectString new_path(request[2]);
372 return Directory::Rename(namespc,
373 reinterpret_cast<const char*>(path.Buffer()),
374 new_path.CString())
375 ? CObject::True()
377}
378
379bool AsyncDirectoryListing::AddFileSystemEntityToResponse(Response type,
380 const char* arg) {
381 array_->SetAt(index_++, new CObjectInt32(CObject::NewInt32(type)));
382 if (arg != nullptr) {
383 size_t len = strlen(arg);
384 Dart_CObject* io_buffer = CObject::NewIOBuffer(len);
385 uint8_t* data = io_buffer->value.as_external_typed_data.data;
386 memmove(reinterpret_cast<char*>(data), arg, len);
387
388 CObjectExternalUint8Array* external_array =
389 new CObjectExternalUint8Array(io_buffer);
390 array_->SetAt(index_++, external_array);
391 } else {
392 array_->SetAt(index_++, CObject::Null());
393 }
394 return index_ < length_;
395}
396
397bool AsyncDirectoryListing::HandleDirectory(const char* dir_name) {
398 return AddFileSystemEntityToResponse(kListDirectory, dir_name);
399}
400
401bool AsyncDirectoryListing::HandleFile(const char* file_name) {
402 return AddFileSystemEntityToResponse(kListFile, file_name);
403}
404
405bool AsyncDirectoryListing::HandleLink(const char* link_name) {
406 return AddFileSystemEntityToResponse(kListLink, link_name);
407}
408
410 AddFileSystemEntityToResponse(kListDone, nullptr);
411}
412
415 array_->SetAt(index_++, new CObjectInt32(CObject::NewInt32(kListError)));
416 CObjectArray* response = new CObjectArray(CObject::NewArray(3));
418 // Delay calling CurrentPath() until after CObject::NewOSError() in case
419 // CurrentPath() pollutes the OS error code.
420 response->SetAt(1, new CObjectString(CObject::NewString(
421 error() ? "Invalid path" : CurrentPath())));
422 response->SetAt(2, err);
423 array_->SetAt(index_++, response);
424 return index_ < length_;
425}
426
427bool SyncDirectoryListing::HandleDirectory(const char* dir_name) {
428 // Allocates a Uint8List for dir_name, and invokes the Directory.fromRawPath
429 // constructor. This avoids/delays interpreting the UTF-8 bytes in dir_name.
430 // Later, client code may either choose to access FileSystemEntity.path.
431 // FileSystemEntity.path will trigger UTF-8 decoding and return a path with
432 // non-UTF-8 characters replaced with U+FFFD.
433
434 size_t dir_name_length = strlen(dir_name);
435 uint8_t* buffer = nullptr;
436 Dart_Handle dir_name_dart = IOBuffer::Allocate(dir_name_length, &buffer);
437 if (Dart_IsNull(dir_name_dart)) {
438 dart_error_ = DartUtils::NewDartOSError();
439 return false;
440 }
441 memmove(buffer, dir_name, dir_name_length);
442 Dart_Handle constructor_name = from_raw_path_string_;
443 Dart_Handle dir =
444 Dart_New(directory_type_, constructor_name, 1, &dir_name_dart);
445 Dart_Handle result = Dart_Invoke(results_, add_string_, 1, &dir);
446 if (Dart_IsError(result)) {
447 dart_error_ = result;
448 return false;
449 }
450 return true;
451}
452
453bool SyncDirectoryListing::HandleLink(const char* link_name) {
454 // Allocates a Uint8List for dir_name, and invokes the Directory.fromRawPath
455 // constructor. This avoids/delays interpreting the UTF-8 bytes in dir_name.
456 // Later, client code may either choose to access FileSystemEntity.path.
457 // FileSystemEntity.path will trigger UTF-8 decoding and return a path with
458 // non-UTF-8 characters replaced with U+FFFD.
459
460 size_t link_name_length = strlen(link_name);
461 uint8_t* buffer = nullptr;
462 Dart_Handle link_name_dart = IOBuffer::Allocate(link_name_length, &buffer);
463 if (Dart_IsNull(link_name_dart)) {
464 dart_error_ = DartUtils::NewDartOSError();
465 return false;
466 }
467 memmove(buffer, link_name, link_name_length);
468 Dart_Handle constructor_name = from_raw_path_string_;
469 Dart_Handle link = Dart_New(link_type_, constructor_name, 1, &link_name_dart);
470 Dart_Handle result = Dart_Invoke(results_, add_string_, 1, &link);
471 if (Dart_IsError(result)) {
472 dart_error_ = result;
473 return false;
474 }
475 return true;
476}
477
478bool SyncDirectoryListing::HandleFile(const char* file_name) {
479 // Allocates a Uint8List for dir_name, and invokes the Directory.fromRawPath
480 // constructor. This avoids/delays interpreting the UTF-8 bytes in dir_name.
481 // Later, client code may either choose to access FileSystemEntity.path.
482 // FileSystemEntity.path will trigger UTF-8 decoding and return a path with
483 // non-UTF-8 characters replaced with U+FFFD.
484
485 size_t file_name_length = strlen(file_name);
486 uint8_t* buffer = nullptr;
487 Dart_Handle file_name_dart = IOBuffer::Allocate(file_name_length, &buffer);
488 if (Dart_IsNull(file_name_dart)) {
489 dart_error_ = DartUtils::NewDartOSError();
490 return false;
491 }
492 memmove(buffer, file_name, file_name_length);
493 Dart_Handle constructor_name = from_raw_path_string_;
494 Dart_Handle file = Dart_New(file_type_, constructor_name, 1, &file_name_dart);
495 Dart_Handle result = Dart_Invoke(results_, add_string_, 1, &file);
496 if (Dart_IsError(result)) {
497 dart_error_ = result;
498 return false;
499 }
500 return true;
501}
502
504 Dart_Handle dart_os_error = DartUtils::NewDartOSError();
505 Dart_Handle args[3];
506 args[0] = dart_os_error;
507 args[1] = DartUtils::NewString("Directory listing failed");
508 args[2] = DartUtils::NewString(error() ? "Invalid path" : CurrentPath());
509
510 dart_error_ = Dart_New(
511 DartUtils::GetDartType(DartUtils::kIOLibURL, "FileSystemException"),
512 DartUtils::NewString("_fromOSError"), 3, args);
513 return false;
514}
515
516static bool ListNext(DirectoryListing* listing) {
517 switch (listing->top()->Next(listing)) {
518 case kListFile:
519 return listing->HandleFile(listing->CurrentPath());
520
521 case kListLink:
522 return listing->HandleLink(listing->CurrentPath());
523
524 case kListDirectory:
525 if (listing->recursive()) {
526 listing->Push(new DirectoryListingEntry(listing->top()));
527 }
528 return listing->HandleDirectory(listing->CurrentPath());
529
530 case kListError:
531 return listing->HandleError();
532
533 case kListDone:
534 listing->Pop();
535 if (listing->IsEmpty()) {
536 listing->HandleDone();
537 return false;
538 } else {
539 return true;
540 }
541
542 default:
543 UNREACHABLE();
544 }
545 return false;
546}
547
549 if (listing->error()) {
550 listing->HandleError();
551 listing->HandleDone();
552 } else {
553 while (ListNext(listing)) {
554 }
555 }
556}
557
558const char* Directory::Current(Namespace* namespc) {
559 return Namespace::GetCurrent(namespc);
560}
561
562bool Directory::SetCurrent(Namespace* namespc, const char* name) {
563 return Namespace::SetCurrent(namespc, name);
564}
565
566} // namespace bin
567} // namespace dart
static const uint32_t kArraySize
#define UNREACHABLE()
Definition assert.h:248
#define FUNCTION_NAME(name)
Definition builtin.h:19
static char * StrDup(const char *s)
void SetArray(CObjectArray *array, intptr_t length)
Definition directory.h:183
virtual bool HandleDirectory(const char *dir_name)
Definition directory.cc:397
virtual bool HandleLink(const char *file_name)
Definition directory.cc:405
virtual bool HandleFile(const char *file_name)
Definition directory.cc:401
void SetAt(intptr_t index, CObject *value)
Definition dartutils.h:548
intptr_t Length() const
Definition dartutils.h:544
const char * CString() const
Definition dartutils.h:534
static Dart_CObject * NewString(const char *str)
Definition dartutils.cc:933
static CObject * IllegalArgumentError()
static Dart_CObject * NewIntptr(intptr_t value)
Definition dartutils.cc:920
static Dart_CObject * NewIOBuffer(int64_t length)
Definition dartutils.cc:984
static CObject * Bool(bool value)
Definition dartutils.cc:897
Dart_CObject * AsApiCObject()
Definition dartutils.h:394
static Dart_CObject * NewArray(intptr_t length)
Definition dartutils.cc:942
static CObject * True()
Definition dartutils.cc:889
static Dart_CObject * NewInt32(int32_t value)
Definition dartutils.cc:908
static CObject * NewOSError()
static CObject * Null()
Definition dartutils.cc:885
static constexpr const char * kIOLibURL
Definition dartutils.h:297
static const char * GetNativeTypedDataArgument(Dart_NativeArguments args, intptr_t index)
Definition dartutils.cc:199
static Dart_Handle NewDartOSError()
Definition dartutils.cc:706
static Dart_Handle NewString(const char *str)
Definition dartutils.h:214
static Dart_Handle GetDartType(const char *library_url, const char *class_name)
Definition dartutils.cc:700
static intptr_t GetIntptrValue(Dart_Handle value_obj)
Definition dartutils.cc:104
static const char * GetNativeStringArgument(Dart_NativeArguments args, intptr_t index)
Definition dartutils.cc:179
static bool GetNativeBooleanArgument(Dart_NativeArguments args, intptr_t index)
Definition dartutils.cc:150
ListType Next(DirectoryListing *listing)
const char * CurrentPath()
Definition directory.h:141
DirectoryListingEntry * top() const
Definition directory.h:135
void Push(DirectoryListingEntry *directory)
Definition directory.h:116
virtual bool HandleFile(const char *file_name)=0
virtual void HandleDone()
Definition directory.h:114
virtual bool HandleDirectory(const char *dir_name)=0
virtual bool HandleLink(const char *link_name)=0
virtual bool HandleError()=0
static bool SetCurrent(Namespace *namespc, const char *path)
Definition directory.cc:562
static bool Create(Namespace *namespc, const char *path)
static ExistsResult Exists(Namespace *namespc, const char *path)
static bool Rename(Namespace *namespc, const char *path, const char *new_path)
static bool Delete(Namespace *namespc, const char *path, bool recursive)
static void List(DirectoryListing *listing)
Definition directory.cc:548
static CObject * DeleteRequest(const CObjectArray &request)
Definition directory.cc:218
static CObject * CreateTempRequest(const CObjectArray &request)
Definition directory.cc:260
static const char * CreateTemp(Namespace *namespc, const char *path)
static const char * Current(Namespace *namespc)
Definition directory.cc:558
static CObject * ListStartRequest(const CObjectArray &request)
Definition directory.cc:288
static CObject * RenameRequest(const CObjectArray &request)
Definition directory.cc:360
static const char * SystemTemp(Namespace *namespc)
static CObject * CreateRequest(const CObjectArray &request)
Definition directory.cc:202
static CObject * ListStopRequest(const CObjectArray &request)
Definition directory.cc:341
static CObject * ExistsRequest(const CObjectArray &request)
Definition directory.cc:237
static CObject * ListNextRequest(const CObjectArray &request)
Definition directory.cc:320
static void SetSystemTemp(const char *path)
Definition directory.cc:187
static Dart_Handle Allocate(intptr_t size, uint8_t **buffer)
Definition io_buffer.cc:12
static Namespace * GetNamespace(Dart_NativeArguments args, intptr_t index)
Definition namespace.cc:101
static const char * GetCurrent(Namespace *namespc)
static bool SetCurrent(Namespace *namespc, const char *path)
virtual bool HandleFile(const char *file_name)
Definition directory.cc:478
virtual bool HandleLink(const char *file_name)
Definition directory.cc:453
virtual bool HandleDirectory(const char *dir_name)
Definition directory.cc:427
struct _Dart_Handle * Dart_Handle
Definition dart_api.h:258
struct _Dart_NativeArguments * Dart_NativeArguments
Definition dart_api.h:3010
@ Dart_TypedData_kUint8
Definition dart_api.h:2606
#define ASSERT(E)
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
void FUNCTION_NAME() Directory_CreateTemp(Dart_NativeArguments args)
Definition directory.cc:79
void FUNCTION_NAME() Directory_Delete(Dart_NativeArguments args)
Definition directory.cc:91
static constexpr int kAsyncDirectoryListerFieldIndex
Definition directory.cc:147
static Dart_Handle ThrowIfError(Dart_Handle handle)
Definition dartutils.h:31
void FUNCTION_NAME() Directory_SetCurrent(Dart_NativeArguments args)
Definition directory.cc:35
void FUNCTION_NAME() Directory_SetAsyncDirectoryListerPointer(Dart_NativeArguments args)
Definition directory.cc:173
static void ReleaseListing(void *isolate_callback_data, void *peer)
Definition directory.cc:167
void FUNCTION_NAME() Directory_Rename(Dart_NativeArguments args)
Definition directory.cc:103
static bool ListNext(DirectoryListing *listing)
Definition directory.cc:516
void FUNCTION_NAME() Directory_SystemTemp(Dart_NativeArguments args)
Definition directory.cc:72
@ kListDirectory
Definition directory.h:20
void FUNCTION_NAME() Directory_FillWithDirectoryListing(Dart_NativeArguments args)
Definition directory.cc:115
void FUNCTION_NAME() Directory_Exists(Dart_NativeArguments args)
Definition directory.cc:46
void FUNCTION_NAME() Directory_GetAsyncDirectoryListerPointer(Dart_NativeArguments args)
Definition directory.cc:149
static Namespace * CObjectToNamespacePointer(CObject *cobject)
Definition directory.cc:197
static CObject * CreateIllegalArgumentError()
Definition directory.cc:278
void FUNCTION_NAME() Directory_Current(Dart_NativeArguments args)
Definition directory.cc:24
void FUNCTION_NAME() Directory_Create(Dart_NativeArguments args)
Definition directory.cc:61
DART_EXPORT bool Dart_IsInstance(Dart_Handle object)
const char *const name
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, int index, intptr_t *value)
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args, bool retval)
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value)
DART_EXPORT void Dart_PropagateError(Dart_Handle handle)
DART_EXPORT Dart_FinalizableHandle Dart_NewFinalizableHandle(Dart_Handle object, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback)
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, Dart_Handle retval)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
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 Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception)
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_New(Dart_Handle type, Dart_Handle constructor_name, int number_of_arguments, Dart_Handle *arguments)
static int8_t data[kExtLength]
union _Dart_CObject::@86 value
struct _Dart_CObject::@86::@91 as_external_typed_data
struct _Dart_CObject::@86::@89 as_array