@@ -568,7 +568,11 @@ DEFINE_NATIVE_ENTRY(Ffi_fromFunction, 1, 2) {
568568
569569 Class& native_function_class =
570570 Class::Handle (isolate->class_table ()->At (kFfiNativeFunctionCid ));
571- native_function_class.EnsureIsFinalized (Thread::Current ());
571+ const auto & error =
572+ Error::Handle (native_function_class.EnsureIsFinalized (Thread::Current ()));
573+ if (!error.IsNull ()) {
574+ Exceptions::PropagateError (error);
575+ }
572576
573577 Type& native_function_type = Type::Handle (
574578 Type::New (native_function_class, type_args, TokenPosition::kNoSource ));
@@ -608,6 +612,90 @@ DEFINE_NATIVE_ENTRY(Ffi_fromFunction, 1, 2) {
608612#endif
609613}
610614
615+ DEFINE_NATIVE_ENTRY (Ffi_asExternalTypedData, 0 , 2 ) {
616+ GET_NON_NULL_NATIVE_ARGUMENT (Pointer, pointer, arguments->NativeArgAt (0 ));
617+ GET_NON_NULL_NATIVE_ARGUMENT (Integer, count, arguments->NativeArgAt (1 ));
618+ const auto & pointer_type_arg = AbstractType::Handle (pointer.type_argument ());
619+ const classid_t type_cid = pointer_type_arg.type_class_id ();
620+ classid_t cid = 0 ;
621+
622+ switch (type_cid) {
623+ case kFfiInt8Cid :
624+ cid = kExternalTypedDataInt8ArrayCid ;
625+ break ;
626+ case kFfiUint8Cid :
627+ cid = kExternalTypedDataUint8ArrayCid ;
628+ break ;
629+ case kFfiInt16Cid :
630+ cid = kExternalTypedDataInt16ArrayCid ;
631+ break ;
632+ case kFfiUint16Cid :
633+ cid = kExternalTypedDataUint16ArrayCid ;
634+ break ;
635+ case kFfiInt32Cid :
636+ cid = kExternalTypedDataInt32ArrayCid ;
637+ break ;
638+ case kFfiUint32Cid :
639+ cid = kExternalTypedDataUint32ArrayCid ;
640+ break ;
641+ case kFfiInt64Cid :
642+ cid = kExternalTypedDataInt64ArrayCid ;
643+ break ;
644+ case kFfiUint64Cid :
645+ cid = kExternalTypedDataUint64ArrayCid ;
646+ break ;
647+ case kFfiIntPtrCid :
648+ cid = kWordSize == 4 ? kExternalTypedDataInt32ArrayCid
649+ : kExternalTypedDataInt64ArrayCid ;
650+ break ;
651+ case kFfiFloatCid :
652+ cid = kExternalTypedDataFloat32ArrayCid ;
653+ break ;
654+ case kFfiDoubleCid :
655+ cid = kExternalTypedDataFloat64ArrayCid ;
656+ break ;
657+ default : {
658+ const String& error = String::Handle (
659+ String::NewFormatted (" Cannot create a TypedData from a Pointer to %s" ,
660+ pointer_type_arg.ToCString ()));
661+ Exceptions::ThrowArgumentError (error);
662+ UNREACHABLE ();
663+ }
664+ }
665+
666+ const intptr_t element_count = count.AsInt64Value ();
667+
668+ if (element_count < 0 ||
669+ element_count > ExternalTypedData::MaxElements (cid)) {
670+ const String& error = String::Handle (
671+ String::NewFormatted (" Count must be in the range [0, %" Pd " ]." ,
672+ ExternalTypedData::MaxElements (cid)));
673+ Exceptions::ThrowArgumentError (error);
674+ }
675+
676+ // The address must be aligned by the element size.
677+ const intptr_t element_size = ExternalTypedData::ElementSizeFor (cid);
678+ if (!Utils::IsAligned (pointer.NativeAddress (), element_size)) {
679+ const String& error = String::Handle (
680+ String::NewFormatted (" Pointer address must be aligned to a multiple of"
681+ " the element size (%" Pd " )." ,
682+ element_size));
683+ Exceptions::ThrowArgumentError (error);
684+ }
685+
686+ const auto & typed_data_class =
687+ Class::Handle (zone, isolate->class_table ()->At (cid));
688+ const auto & error = Error::Handle (
689+ zone, typed_data_class.EnsureIsFinalized (Thread::Current ()));
690+ if (!error.IsNull ()) {
691+ Exceptions::PropagateError (error);
692+ }
693+
694+ return ExternalTypedData::New (
695+ cid, reinterpret_cast <uint8_t *>(pointer.NativeAddress ()), element_count,
696+ Heap::kNew );
697+ }
698+
611699#if defined(TARGET_ARCH_DBC)
612700
613701void FfiMarshalledArguments::SetFunctionAddress (uint64_t value) const {
0 commit comments