[js_runtime] Modernize and simplify `_AsyncRun._scheduleImmediate`.
Use browser's `queueMicrotask` if available.
Remove `MutationObserver` method, since `queueMicrotask` is available on all supported browsers.
Simplify by removing `internalCallback`. This is no longer needed (it used to do more than just call the callback).
Issue: #20055
Change-Id: Ic866cdd77787fc45456f65a6618fe66afcbcb970
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/444392
Reviewed-by: Mayank Patke <fishythefish@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
diff --git a/sdk/lib/_internal/js_runtime/lib/async_patch.dart b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
index 0d53e6b..1ac1cf8 100644
--- a/sdk/lib/_internal/js_runtime/lib/async_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
@@ -26,6 +26,8 @@
}
}
+typedef _ScheduleImmediateFn = void Function(void Function());
+
@patch
class _AsyncRun {
@patch
@@ -34,78 +36,33 @@
}
// Lazily initialized.
- static final Function _scheduleImmediateClosure =
+ static final _ScheduleImmediateFn _scheduleImmediateClosure =
_initializeScheduleImmediate();
- static Function _initializeScheduleImmediate() {
+ static _ScheduleImmediateFn _initializeScheduleImmediate() {
requiresPreamble();
if (JS('', 'self.scheduleImmediate') != null) {
return _scheduleImmediateJsOverride;
}
- if (JS('', 'self.MutationObserver') != null &&
- JS('', 'self.document') != null) {
- // Use mutationObservers.
- var div = JS('', 'self.document.createElement("div")');
- var span = JS('', 'self.document.createElement("span")');
- void Function()? storedCallback;
- internalCallback(_) {
- var f = storedCallback;
- storedCallback = null;
- f!();
- }
-
- var observer = JS(
- '',
- 'new self.MutationObserver(#)',
- convertDartClosureToJS(internalCallback, 1),
- );
- JS('', '#.observe(#, { childList: true })', observer, div);
-
- return (void callback()) {
- assert(storedCallback == null);
- storedCallback = callback;
- // Because of a broken shadow-dom polyfill we have to change the
- // children instead a cheap property.
- JS(
- '',
- '#.firstChild ? #.removeChild(#): #.appendChild(#)',
- div,
- div,
- span,
- div,
- span,
- );
- };
- } else if (JS('', 'self.setImmediate') != null) {
- return _scheduleImmediateWithSetImmediate;
+ if (JS('', 'typeof self.queueMicrotask == "function"')) {
+ return _scheduleImmediateWithQueueMicrotask;
}
- // TODO(20055): We should use DOM promises when available.
+
+ // The fallback is not quite right as it uses the macro task queue.
return _scheduleImmediateWithTimer;
}
static void _scheduleImmediateJsOverride(void callback()) {
- internalCallback() {
- callback();
- }
-
- JS(
- 'void',
- 'self.scheduleImmediate(#)',
- convertDartClosureToJS(internalCallback, 0),
- );
+ JS('', 'self.scheduleImmediate(#)', convertDartClosureToJS(callback, 0));
}
- static void _scheduleImmediateWithSetImmediate(void callback()) {
- internalCallback() {
- callback();
- }
-
- JS(
- 'void',
- 'self.setImmediate(#)',
- convertDartClosureToJS(internalCallback, 0),
- );
+ /// `queueMicrotask` is available in all supported browsers in
+ /// [windows](https://developer.mozilla.org/en-US/docs/Web/API/Window/queueMicrotask#browser_compatibility)
+ /// and
+ /// [workers](https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/queueMicrotask#browser_compatibility).
+ static void _scheduleImmediateWithQueueMicrotask(void callback()) {
+ JS('', 'self.queueMicrotask(#)', convertDartClosureToJS(callback, 0));
}
static void _scheduleImmediateWithTimer(void callback()) {