Issue #3063 - Implement queueMicroTask(callback())

This commit is contained in:
Moonchild 2022-02-06 13:54:40 +00:00 • committed by roytam1
commit bf17b1fec3
7 changed files with 66 additions and 9 deletions

View file

@ -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<nsIDocument> d = mOwner->GetExtantDoc();
return d && d->IsInSyncOperation();
}
return false;
return mOwner && nsGlobalWindow::Cast(mOwner)->IsInSyncOperation();
}
static void HandleMutationsInternal(mozilla::AutoSlowOperation& aAso);

View file

@ -1224,6 +1224,12 @@ public:
already_AddRefed<nsWindowRoot> GetWindowRoot(mozilla::ErrorResult& aError);
mozilla::dom::Performance* GetPerformance();
virtual bool IsInSyncOperation() override
{
return GetExtantDoc() && GetExtantDoc()->IsInSyncOperation();
}
protected:
// Web IDL helpers

View file

@ -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<ErrorResult&>(rv));
}
bool Suppressed() final { return mGlobal->IsInSyncOperation(); }
private:
nsCOMPtr<nsIGlobalObject> mGlobal;
RefPtr<VoidFunction> mCallback;
};
void nsIGlobalObject::QueueMicrotask(VoidFunction& aCallback) {
CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
if (context) {
RefPtr<MicroTaskRunnable> mt = new QueuedMicrotask(this, aCallback);
context->DispatchMicroTaskRunnable(mt.forget());
}
}

View file

@ -19,6 +19,13 @@ class nsCString;
class nsCycleCollectionTraversalCallback;
class nsIPrincipal;
namespace mozilla{
namespace dom{
class VoidFunction;
}
}
class nsIGlobalObject : public nsISupports
{
nsTArray<nsCString> 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();

View file

@ -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 ();

View file

@ -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<ImageBitmap> createImageBitmap(ImageBitmapSource aImage);

View file

@ -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; }