From 6f8d063b186022997303d33e33c008741c86ca78 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Sun, 6 Feb 2022 13:54:40 +0000 Subject: Issue #1895 - Implement queueMicroTask(callback()) --- dom/base/nsDOMMutationObserver.h | 7 ++---- dom/base/nsGlobalWindow.h | 6 +++++ dom/base/nsIGlobalObject.cpp | 38 +++++++++++++++++++++++++++++ dom/base/nsIGlobalObject.h | 11 +++++++++ dom/webidl/Function.webidl | 8 +++--- dom/webidl/WindowOrWorkerGlobalScope.webidl | 3 +++ xpcom/base/CycleCollectedJSContext.h | 2 +- 7 files changed, 66 insertions(+), 9 deletions(-) diff --git a/dom/base/nsDOMMutationObserver.h b/dom/base/nsDOMMutationObserver.h index 6e17e4f2cc..1e2225d020 100644 --- a/dom/base/nsDOMMutationObserver.h +++ b/dom/base/nsDOMMutationObserver.h @@ -25,6 +25,7 @@ #include "nsIDocument.h" #include "mozilla/dom/Animation.h" #include "nsIAnimationObserver.h" +#include "nsGlobalWindow.h" class nsDOMMutationObserver; using mozilla::dom::MutationObservingInfo; @@ -599,11 +600,7 @@ protected: bool Suppressed() { - if (mOwner) { - nsCOMPtr d = mOwner->GetExtantDoc(); - return d && d->IsInSyncOperation(); - } - return false; + return mOwner && nsGlobalWindow::Cast(mOwner)->IsInSyncOperation(); } static void HandleMutationsInternal(mozilla::AutoSlowOperation& aAso); diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 00ac023fce..e42835a0b2 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -1224,6 +1224,12 @@ public: already_AddRefed GetWindowRoot(mozilla::ErrorResult& aError); mozilla::dom::Performance* GetPerformance(); + + virtual bool IsInSyncOperation() override + { + return GetExtantDoc() && GetExtantDoc()->IsInSyncOperation(); + } + protected: // Web IDL helpers diff --git a/dom/base/nsIGlobalObject.cpp b/dom/base/nsIGlobalObject.cpp index 8923865082..7a6bab8b4b 100644 --- a/dom/base/nsIGlobalObject.cpp +++ b/dom/base/nsIGlobalObject.cpp @@ -4,10 +4,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsIGlobalObject.h" + +#include "mozilla/CycleCollectedJSContext.h" +#include "mozilla/dom/FunctionBinding.h" #include "nsContentUtils.h" #include "nsThreadUtils.h" #include "nsHostObjectProtocolHandler.h" +using mozilla::AutoSlowOperation; +using mozilla::CycleCollectedJSContext; +using mozilla::ErrorResult; +using mozilla::IgnoredErrorResult; +using mozilla::MicroTaskRunnable; +using mozilla::dom::VoidFunction; + nsIGlobalObject::~nsIGlobalObject() { UnlinkHostObjectURIs(); @@ -110,3 +120,31 @@ nsIGlobalObject::TraverseHostObjectURIs(nsCycleCollectionTraversalCallback &aCb) nsHostObjectProtocolHandler::Traverse(mHostObjectURIs[index], aCb); } } + +class QueuedMicrotask : public MicroTaskRunnable { + public: + QueuedMicrotask(nsIGlobalObject* aGlobal, VoidFunction& aCallback) + : mGlobal(aGlobal) + , mCallback(&aCallback) + {} + + /* unsafe */ + void Run(AutoSlowOperation& aAso) final { + IgnoredErrorResult rv; + 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->DispatchMicroTaskRunnable(mt.forget()); + } +} \ No newline at end of file diff --git a/dom/base/nsIGlobalObject.h b/dom/base/nsIGlobalObject.h index 6dfae4fbe4..1438803317 100644 --- a/dom/base/nsIGlobalObject.h +++ b/dom/base/nsIGlobalObject.h @@ -19,6 +19,13 @@ class nsCString; class nsCycleCollectionTraversalCallback; class nsIPrincipal; +namespace mozilla{ +namespace dom{ +class VoidFunction; +} +} + + class nsIGlobalObject : public nsISupports { nsTArray mHostObjectURIs; @@ -72,6 +79,10 @@ public: void UnlinkHostObjectURIs(); void TraverseHostObjectURIs(nsCycleCollectionTraversalCallback &aCb); + virtual bool IsInSyncOperation() { return false; } + + void QueueMicrotask(mozilla::dom::VoidFunction& aCallback); + protected: virtual ~nsIGlobalObject(); diff --git a/dom/webidl/Function.webidl b/dom/webidl/Function.webidl index 55bec0811c..3b44ee111c 100644 --- a/dom/webidl/Function.webidl +++ b/dom/webidl/Function.webidl @@ -6,9 +6,11 @@ * The origin of this IDL file is * http://www.whatwg.org/specs/web-apps/current-work/#functiocn * - * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and - * Opera Software ASA. You are granted a license to use, reproduce - * and create derivative works of this document. + * © Copyright 2004-2022 Apple Computer, Inc., Mozilla Foundation, + * Opera Software ASA and Moonchild Productions. You are granted a license to use, + * reproduce and create derivative works of this document. */ callback Function = any(any... arguments); + +callback VoidFunction = void (); diff --git a/dom/webidl/WindowOrWorkerGlobalScope.webidl b/dom/webidl/WindowOrWorkerGlobalScope.webidl index dddf2d17c4..652a46ffcb 100644 --- a/dom/webidl/WindowOrWorkerGlobalScope.webidl +++ b/dom/webidl/WindowOrWorkerGlobalScope.webidl @@ -36,6 +36,9 @@ interface WindowOrWorkerGlobalScope { long setInterval(DOMString handler, optional long timeout, any... unused); void clearInterval(optional long handle = 0); + // microtask queuing + void queueMicrotask(VoidFunction callback); + // ImageBitmap [Throws] Promise createImageBitmap(ImageBitmapSource aImage); diff --git a/xpcom/base/CycleCollectedJSContext.h b/xpcom/base/CycleCollectedJSContext.h index c39ce62f37..914bb95d30 100644 --- a/xpcom/base/CycleCollectedJSContext.h +++ b/xpcom/base/CycleCollectedJSContext.h @@ -137,7 +137,7 @@ struct CycleCollectorResults class MicroTaskRunnable { public: - MicroTaskRunnable() {} + MicroTaskRunnable() = default; NS_INLINE_DECL_REFCOUNTING(MicroTaskRunnable) virtual void Run(AutoSlowOperation& aAso) = 0; virtual bool Suppressed() { return false; } -- cgit v1.2.3