[dart2wasm] Avoid using allowInterop in Promise<->Future conversion

The dart closures for the then/onError callbacks we use on a JS promise
will not flow back into dart. There's therefore no reason to use the
very heavyweight `allowInterop` mechanism.

This makes (after [0]) asynchronous calls to JS from Dart more than 2x
as fast.

This also aligns the `promiseToFuture` implementation with the extension on
`JSPromise` (see sdk/lib/_internal/wasm/lib/js_interop_patch.dart)
modulo the fact that the API doesn't work on interop types but Dart
types and needs therefore the full JS<->Dart conversion.

=> Maybe it would make sense to deprecate `promiseToFuture` / not offer it
in dart2wasm and make users use instead the extension on `JSPromise`
instead?

[0] https://dart-review.googlesource.com/c/sdk/+/352520

Change-Id: Ibc80bf083e7ec817f000257d6995108954060277
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352521
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Martin Kustermann 2024-02-14 11:48:15 +00:00 committed by Commit Queue
parent 13532be38c
commit 5d664b4bd4

View file

@ -7,6 +7,12 @@ library dart.js_util;
import "dart:_internal";
import "dart:_js_helper";
import "dart:_js_types";
import "dart:js_interop"
show
JSAnyUtilityExtension,
FunctionToJSExportedDartFunction,
dartify,
JSAny;
import "dart:_wasm";
import "dart:async" show Completer, FutureOr;
import "dart:collection";
@ -151,23 +157,25 @@ typedef _PromiseFailureFunc = void Function(Object? error);
Future<T> promiseToFuture<T>(Object jsPromise) {
Completer<T> completer = Completer<T>();
final success = allowInterop<_PromiseSuccessFunc>((r) {
final success = ((JSAny? jsValue) {
final r = dartifyRaw(jsValue.toExternRef);
return completer.complete(r as FutureOr<T>?);
});
final error = allowInterop<_PromiseFailureFunc>((e) {
}).toJS;
final error = ((JSAny? jsError) {
// Note that `completeError` expects a non-nullable error regardless of
// whether null-safety is enabled, so a `NullRejectionException` is always
// provided if the error is `null` or `undefined`.
// TODO(joshualitt): At this point `undefined` has been replaced with `null`
// so we cannot tell them apart. In the future we should reify `undefined`
// in Dart.
final e = dartifyRaw(jsError.toExternRef);
if (e == null) {
return completer.completeError(NullRejectionException(false));
}
return completer.completeError(e);
});
}).toJS;
promiseThen(jsifyRaw(jsPromise), jsifyRaw(success), jsifyRaw(error));
promiseThen(jsifyRaw(jsPromise), success.toExternRef, error.toExternRef);
return completer.future;
}