From 5047fe54d7880e15fdfea1df229a781488375a26 Mon Sep 17 00:00:00 2001 From: Fedor Date: Mon, 30 Oct 2023 22:46:28 +0200 Subject: [PATCH] Implement queueMicrotask() --- dom/base/nsIGlobalObject.cpp | 34 ++++++++- dom/base/nsIGlobalObject.h | 3 + dom/webidl/WindowOrWorkerGlobalScope.webidl | 3 + .../window-properties.https.html.ini | 3 - .../queue-microtask-exceptions.any.js.ini | 22 ------ .../queue-microtask.any.js.ini | 72 ------------------- .../queue-microtask.window.js.ini | 7 -- 7 files changed, 39 insertions(+), 105 deletions(-) delete mode 100644 testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini delete mode 100644 testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask.any.js.ini delete mode 100644 testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask.window.js.ini diff --git a/dom/base/nsIGlobalObject.cpp b/dom/base/nsIGlobalObject.cpp index 62b07706eb..b830d9d5d1 100644 --- a/dom/base/nsIGlobalObject.cpp +++ b/dom/base/nsIGlobalObject.cpp @@ -3,23 +3,30 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsIGlobalObject.h" - +#include "mozilla/CycleCollectedJSContext.h" #include "mozilla/dom/BlobURLProtocolHandler.h" +#include "mozilla/dom/FunctionBinding.h" #include "mozilla/dom/ServiceWorker.h" #include "mozilla/dom/ServiceWorkerRegistration.h" #include "nsContentUtils.h" #include "nsThreadUtils.h" #include "nsGlobalWindowInner.h" +using mozilla::AutoSlowOperation; +using mozilla::CycleCollectedJSContext; using mozilla::DOMEventTargetHelper; +using mozilla::ErrorResult; +using mozilla::IgnoredErrorResult; using mozilla::MallocSizeOf; using mozilla::Maybe; +using mozilla::MicroTaskRunnable; using mozilla::dom::BlobURLProtocolHandler; using mozilla::dom::ClientInfo; using mozilla::dom::ServiceWorker; using mozilla::dom::ServiceWorkerDescriptor; using mozilla::dom::ServiceWorkerRegistration; using mozilla::dom::ServiceWorkerRegistrationDescriptor; +using mozilla::dom::VoidFunction; bool nsIGlobalObject::IsScriptForbidden(JSObject* aCallback, bool aIsJSImplementedWebIDL) const { @@ -232,3 +239,28 @@ size_t nsIGlobalObject::ShallowSizeOfExcludingThis(MallocSizeOf aSizeOf) const { size_t rtn = mHostObjectURIs.ShallowSizeOfExcludingThis(aSizeOf); return rtn; } + +class QueuedMicrotask : public MicroTaskRunnable { + public: + QueuedMicrotask(nsIGlobalObject* aGlobal, VoidFunction& aCallback) + : mGlobal(aGlobal), mCallback(&aCallback) {} + + MOZ_CAN_RUN_SCRIPT_BOUNDARY void Run(AutoSlowOperation& aAso) final { + IgnoredErrorResult rv; + MOZ_KnownLive(mCallback)->Call(static_cast(rv)); + } + + bool Suppressed() final { return mGlobal->IsInSyncOperation(); } + + private: + nsCOMPtr mGlobal; + RefPtr mCallback; +}; + +void nsIGlobalObject::QueueMicrotask(VoidFunction& aCallback) { + CycleCollectedJSContext* context = CycleCollectedJSContext::Get(); + if (context) { + RefPtr mt = new QueuedMicrotask(this, aCallback); + context->DispatchToMicroTask(mt.forget()); + } +} diff --git a/dom/base/nsIGlobalObject.h b/dom/base/nsIGlobalObject.h index 47111a7d0d..1166445150 100644 --- a/dom/base/nsIGlobalObject.h +++ b/dom/base/nsIGlobalObject.h @@ -32,6 +32,7 @@ class nsPIDOMWindowInner; namespace mozilla { class DOMEventTargetHelper; namespace dom { +class VoidFunction; class DebuggerNotificationManager; class ServiceWorker; class ServiceWorkerRegistration; @@ -176,6 +177,8 @@ class nsIGlobalObject : public nsISupports, // nullptr otherwise. nsPIDOMWindowInner* AsInnerWindow(); + void QueueMicrotask(mozilla::dom::VoidFunction& aCallback); + protected: virtual ~nsIGlobalObject(); diff --git a/dom/webidl/WindowOrWorkerGlobalScope.webidl b/dom/webidl/WindowOrWorkerGlobalScope.webidl index 49384e24cb..16fa2a8429 100644 --- a/dom/webidl/WindowOrWorkerGlobalScope.webidl +++ b/dom/webidl/WindowOrWorkerGlobalScope.webidl @@ -34,6 +34,9 @@ interface mixin WindowOrWorkerGlobalScope { long setInterval(DOMString handler, optional long timeout = 0, any... unused); void clearInterval(optional long handle = 0); + // microtask queuing + void queueMicrotask(VoidFunction callback); + // ImageBitmap [Throws] Promise createImageBitmap(ImageBitmapSource aImage); diff --git a/testing/web-platform/meta/html/browsers/the-window-object/window-properties.https.html.ini b/testing/web-platform/meta/html/browsers/the-window-object/window-properties.https.html.ini index 080b3610ab..588d21f8cb 100644 --- a/testing/web-platform/meta/html/browsers/the-window-object/window-properties.https.html.ini +++ b/testing/web-platform/meta/html/browsers/the-window-object/window-properties.https.html.ini @@ -10,9 +10,6 @@ if (os == "android") and not e10s: FAIL if (os == "android") and e10s: FAIL - [Window method: queueMicrotask] - expected: FAIL - [Window unforgeable attribute: window] expected: if nightly_build: FAIL diff --git a/testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini b/testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini deleted file mode 100644 index 4214bcc35d..0000000000 --- a/testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini +++ /dev/null @@ -1,22 +0,0 @@ -[queue-microtask-exceptions.https.any.serviceworker.html] - expected: TIMEOUT - -[queue-microtask-exceptions.any.worker.html] - [It rethrows exceptions] - expected: FAIL - - -[queue-microtask-exceptions.any.html] - [It rethrows exceptions] - expected: FAIL - - -[queue-microtask-exceptions.any.sharedworker.html] - [It rethrows exceptions] - expected: FAIL - - -[queue-microtask-exceptions.any.serviceworker.html] - [It rethrows exceptions] - expected: FAIL - diff --git a/testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask.any.js.ini b/testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask.any.js.ini deleted file mode 100644 index 2c232e51b8..0000000000 --- a/testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask.any.js.ini +++ /dev/null @@ -1,72 +0,0 @@ -[queue-microtask.https.any.serviceworker.html] - expected: TIMEOUT - -[queue-microtask.any.sharedworker.html] - [It exists and is a function] - expected: FAIL - - [It does not pass any arguments] - expected: FAIL - - [It calls the callback asynchronously] - expected: FAIL - - [It throws when given non-functions] - expected: FAIL - - [It interleaves with promises as expected] - expected: FAIL - - -[queue-microtask.any.html] - [It exists and is a function] - expected: FAIL - - [It does not pass any arguments] - expected: FAIL - - [It calls the callback asynchronously] - expected: FAIL - - [It throws when given non-functions] - expected: FAIL - - [It interleaves with promises as expected] - expected: FAIL - - -[queue-microtask.any.worker.html] - [It exists and is a function] - expected: FAIL - - [It does not pass any arguments] - expected: FAIL - - [It calls the callback asynchronously] - expected: FAIL - - [It throws when given non-functions] - expected: FAIL - - [It interleaves with promises as expected] - expected: FAIL - - -[queue-microtask.any.serviceworker.html] - disabled: - if os == "android" and not e10s: https://bugzilla.mozilla.org/show_bug.cgi?id=1499003 - [It exists and is a function] - expected: FAIL - - [It does not pass any arguments] - expected: FAIL - - [It calls the callback asynchronously] - expected: FAIL - - [It throws when given non-functions] - expected: FAIL - - [It interleaves with promises as expected] - expected: FAIL - diff --git a/testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask.window.js.ini b/testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask.window.js.ini deleted file mode 100644 index de2c559297..0000000000 --- a/testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask.window.js.ini +++ /dev/null @@ -1,7 +0,0 @@ -[queue-microtask.window.html] - [It interleaves with MutationObservers and promises together as expected] - expected: FAIL - - [It interleaves with MutationObservers as expected] - expected: FAIL -