blob: e14817322d72ace8ab9933e9693800edd01b2def [file] [edit]
import 'dart:_internal' show _AsyncCompleter, patch;
import 'dart:_wasm';
// Modular kernel transformer will make calls to this method be re-directed to
// call dart:core:Error._trySetStackTrace instead.
@patch
external void _trySetStackTrace(Object error, StackTrace stackTrace);
typedef _AsyncResumeFun =
WasmFunction<
void Function(
_AsyncSuspendState,
// Value of the last `await`
Object?,
// If the last `await` threw an error, the error value
Object?,
// If the last `await` threw an error, the stack trace
StackTrace?,
)
>;
@pragma("wasm:entry-point")
class _AsyncSuspendState {
// The inner function.
//
// Note: this function never throws. Any uncaught exceptions are passed to
// `_completer.completeError`.
@pragma("wasm:entry-point")
final _AsyncResumeFun _resume;
// Context containing the local variables of the function.
@pragma("wasm:entry-point")
WasmStructRef? _context;
// CFG target index for the next resumption.
@pragma("wasm:entry-point")
WasmI32 _targetIndex;
// The future that will be completed.
@pragma("wasm:entry-point")
final _Future _future;
// When a called function throws this stores the thrown exception. Used when
// performing type tests in catch blocks.
@pragma("wasm:entry-point")
Object? _currentException;
// When a called function throws this stores the stack trace.
@pragma("wasm:entry-point")
StackTrace? _currentExceptionStackTrace;
// When running finalizers and the continuation is "return", the value to
// return after the last finalizer.
//
// Used in finalizer blocks.
@pragma("wasm:entry-point")
Object? _currentReturnValue;
@pragma("wasm:entry-point")
_AsyncSuspendState(this._resume, this._context, this._future)
: _targetIndex = WasmI32.fromInt(0),
_currentException = null,
_currentExceptionStackTrace = null,
_currentReturnValue = null;
@pragma("wasm:entry-point")
void _complete(FutureOr value) {
_future._asyncComplete(value == null ? value as dynamic : value);
}
@pragma("wasm:entry-point")
void _completeError(Object error, StackTrace stackTrace) {
_future._asyncCompleteError(error, stackTrace);
}
}
// Note: [_AsyncCompleter] is taken as an argument to be able to pass the type
// parameter to [_AsyncCompleter] without having to add a type parameter to
// [_AsyncSuspendState]. Completer type parameter is passed to the completer's
// future, which the outer function returns to the caller.
@pragma("wasm:entry-point")
_AsyncSuspendState _newAsyncSuspendState(
_AsyncResumeFun resume,
WasmStructRef? context,
_Future future,
) => _AsyncSuspendState(resume, context, future);
@pragma("wasm:entry-point")
_Future<T> _makeFuture<T>() => _Future<T>();
@pragma("wasm:entry-point")
void _awaitHelper(_AsyncSuspendState suspendState, Future operand) {
operand.then(
(value) {
suspendState._resume.call(suspendState, value, null, null);
},
onError: (exception, stackTrace) {
suspendState._resume.call(suspendState, null, exception, stackTrace);
},
);
}
@pragma("wasm:entry-point")
void _awaitHelperWithTypeCheck<T>(
_AsyncSuspendState suspendState,
Object? operand,
) {
if (operand is! Future<T>) {
return scheduleMicrotask(
() => suspendState._resume.call(suspendState, operand, null, null),
);
}
operand.then(
(Object? value) {
suspendState._resume.call(suspendState, value, null, null);
},
onError: (exception, stackTrace) {
suspendState._resume.call(suspendState, null, exception, stackTrace);
},
);
}