Bug 1480236 - Implement queueMicrotask(), r=baku
☠☠ backed out by d451bd35ca1c ☠ ☠
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Thu, 23 May 2019 21:26:05 +0000
changeset 475295 9a5f590f5f7574e186216d510692eab02e242ec8
parent 475294 ebc58c182383d769cc609e6eb17dda547586d5ab
child 475296 e282b9c14e0022d87c4a27190ec0739aeb668171
push id36059
push usercsabou@mozilla.com
push dateFri, 24 May 2019 09:53:37 +0000
treeherdermozilla-central@f58ae8ec64c8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1480236
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1480236 - Implement queueMicrotask(), r=baku Differential Revision: https://phabricator.services.mozilla.com/D32341
dom/base/nsIGlobalObject.cpp
dom/base/nsIGlobalObject.h
dom/webidl/WindowOrWorkerGlobalScope.webidl
testing/web-platform/meta/html/browsers/the-window-object/window-properties.https.html.ini
testing/web-platform/meta/html/dom/interfaces.https.html.ini
testing/web-platform/meta/html/dom/interfaces.worker.js.ini
testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini
testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask.any.js.ini
testing/web-platform/meta/html/webappapis/microtask-queuing/queue-microtask.window.js.ini
--- a/dom/base/nsIGlobalObject.cpp
+++ b/dom/base/nsIGlobalObject.cpp
@@ -1,32 +1,34 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * 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::DOMEventTargetHelper;
 using mozilla::MallocSizeOf;
 using mozilla::Maybe;
 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;
 
 nsIGlobalObject::~nsIGlobalObject() {
   UnlinkHostObjectURIs();
   DisconnectEventTargetObjects();
   MOZ_DIAGNOSTIC_ASSERT(mEventTargetObjects.isEmpty());
 }
 
 nsIPrincipal* nsIGlobalObject::PrincipalOrNull() {
@@ -207,8 +209,33 @@ nsPIDOMWindowInner* nsIGlobalObject::AsI
   }
   return nullptr;
 }
 
 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<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->DispatchToMicroTask(mt.forget());
+  }
+}
--- a/dom/base/nsIGlobalObject.h
+++ b/dom/base/nsIGlobalObject.h
@@ -29,16 +29,17 @@
 
 class nsCycleCollectionTraversalCallback;
 class nsIPrincipal;
 class nsPIDOMWindowInner;
 
 namespace mozilla {
 class DOMEventTargetHelper;
 namespace dom {
+class VoidFunction;
 class ServiceWorker;
 class ServiceWorkerRegistration;
 class ServiceWorkerRegistrationDescriptor;
 }  // namespace dom
 }  // namespace mozilla
 
 class nsIGlobalObject : public nsISupports,
                         public mozilla::dom::DispatcherTrait {
@@ -152,16 +153,18 @@ class nsIGlobalObject : public nsISuppor
   virtual RefPtr<mozilla::dom::ServiceWorkerRegistration>
   GetOrCreateServiceWorkerRegistration(
       const mozilla::dom::ServiceWorkerRegistrationDescriptor& aDescriptor);
 
   // Returns a pointer to this object as an inner window if this is one or
   // nullptr otherwise.
   nsPIDOMWindowInner* AsInnerWindow();
 
+  void QueueMicrotask(mozilla::dom::VoidFunction& aCallback);
+
  protected:
   virtual ~nsIGlobalObject();
 
   void StartDying() { mIsDying = true; }
 
   void DisconnectEventTargetObjects();
 
   size_t ShallowSizeOfExcludingThis(mozilla::MallocSizeOf aSizeOf) const;
--- a/dom/webidl/WindowOrWorkerGlobalScope.webidl
+++ b/dom/webidl/WindowOrWorkerGlobalScope.webidl
@@ -30,16 +30,19 @@ interface WindowOrWorkerGlobalScope {
   long setTimeout(DOMString handler, optional long timeout = 0, any... unused);
   void clearTimeout(optional long handle = 0);
   [Throws]
   long setInterval(Function handler, optional long timeout = 0, any... arguments);
   [Throws]
   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<ImageBitmap> createImageBitmap(ImageBitmapSource aImage);
   [Throws]
   Promise<ImageBitmap> createImageBitmap(ImageBitmapSource aImage, long aSx, long aSy, long aSw, long aSh);
 };
 
 // https://fetch.spec.whatwg.org/#fetch-method
--- 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
@@ -5,19 +5,16 @@
   [Window attribute: onmousewheel]
     expected: FAIL
 
   [Window method: print]
     expected:
       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
     bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1510437
 
   [Window unforgeable attribute: document]
     expected:
       if nightly_build: FAIL
--- a/testing/web-platform/meta/html/dom/interfaces.https.html.ini
+++ b/testing/web-platform/meta/html/dom/interfaces.https.html.ini
@@ -367,26 +367,16 @@ prefs: [dom.security.featurePolicy.enabl
     expected: FAIL
 
   [Document interface: iframe.contentDocument must inherit property "onformdata" with the proper type]
     expected: FAIL
 
   [Document interface: attribute onformdata]
     expected: FAIL
 
-  [Window interface: window must inherit property "queueMicrotask(VoidFunction)" with the proper type]
-    expected: FAIL
-
-  [Window interface: calling queueMicrotask(VoidFunction) on window with too few arguments must throw TypeError]
-    expected: FAIL
-
-  [Window interface: operation queueMicrotask(VoidFunction)]
-    expected: FAIL
-
-
 [interfaces.https.html?include=HTML.*]
   [HTMLAllCollection must be primary interface of document.all]
     expected: FAIL
 
   [Stringification of document.all]
     expected: FAIL
 
   [HTMLAllCollection interface: document.all must inherit property "length" with the proper type]
--- a/testing/web-platform/meta/html/dom/interfaces.worker.js.ini
+++ b/testing/web-platform/meta/html/dom/interfaces.worker.js.ini
@@ -444,37 +444,28 @@
     expected: FAIL
 
   [DedicatedWorkerGlobalScope interface: calling requestAnimationFrame(FrameRequestCallback) on self with too few arguments must throw TypeError]
     expected: FAIL
 
   [TextMetrics interface: attribute ideographicBaseline]
     expected: FAIL
 
-  [WorkerGlobalScope interface: self must inherit property "queueMicrotask(VoidFunction)" with the proper type]
-    expected: FAIL
-
   [OffscreenCanvasRenderingContext2D interface: existence and properties of interface prototype object's @@unscopables property]
     expected: FAIL
 
-  [WorkerGlobalScope interface: operation queueMicrotask(VoidFunction)]
-    expected: FAIL
-
   [TextMetrics interface: attribute actualBoundingBoxAscent]
     expected: FAIL
 
   [CanvasPattern interface: existence and properties of interface prototype object's @@unscopables property]
     expected: FAIL
 
   [TextMetrics interface: existence and properties of interface prototype object's @@unscopables property]
     expected: FAIL
 
-  [WorkerGlobalScope interface: calling queueMicrotask(VoidFunction) on self with too few arguments must throw TypeError]
-    expected: FAIL
-
   [DedicatedWorkerGlobalScope interface: self must inherit property "cancelAnimationFrame(unsigned long)" with the proper type]
     expected: FAIL
 
   [SharedWorker interface: existence and properties of interface prototype object's @@unscopables property]
     expected: FAIL
 
   [TextMetrics interface: attribute emHeightDescent]
     expected: FAIL
deleted file mode 100644
--- 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
-
deleted file mode 100644
--- 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
-
deleted file mode 100644
--- 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
-