diff options
11 files changed, 42 insertions, 75 deletions
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 04f8d948a24..e551009b59d 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -4,6 +4,7 @@ use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::EventSourceBinding::EventSourceBinding::EventSourceMethods; +use crate::dom::bindings::codegen::Bindings::VoidFunctionBinding::VoidFunction; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use crate::dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods; use crate::dom::bindings::conversions::{root_from_object, root_from_object_static}; @@ -32,7 +33,7 @@ use crate::dom::performance::Performance; use crate::dom::window::Window; use crate::dom::workerglobalscope::WorkerGlobalScope; use crate::dom::workletglobalscope::WorkletGlobalScope; -use crate::microtask::{Microtask, MicrotaskQueue}; +use crate::microtask::{Microtask, MicrotaskQueue, UserMicrotask}; use crate::script_module::ModuleTree; use crate::script_runtime::{CommonScriptMsg, JSContext as SafeJSContext, ScriptChan, ScriptPort}; use crate::script_thread::{MainThreadScriptChan, ScriptThread}; @@ -1772,6 +1773,13 @@ impl GlobalScope { self.timers.clear_timeout_or_interval(self, handle); } + pub fn queue_function_as_microtask(&self, callback: Rc<VoidFunction>) { + self.enqueue_microtask(Microtask::User(UserMicrotask { + callback: callback, + pipeline: self.pipeline_id(), + })) + } + pub fn fire_timer(&self, handle: TimerEventId) { self.timers.fire_timer(handle, self); } diff --git a/components/script/dom/webidls/WindowOrWorkerGlobalScope.webidl b/components/script/dom/webidls/WindowOrWorkerGlobalScope.webidl index c798b56ab00..61f150f8e81 100644 --- a/components/script/dom/webidls/WindowOrWorkerGlobalScope.webidl +++ b/components/script/dom/webidls/WindowOrWorkerGlobalScope.webidl @@ -20,6 +20,9 @@ interface mixin WindowOrWorkerGlobalScope { long setInterval(TimerHandler handler, optional long timeout = 0, any... arguments); void clearInterval(optional long handle = 0); + // microtask queuing + void queueMicrotask(VoidFunction callback); + // ImageBitmap // Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, optional ImageBitmapOptions options); // Promise<ImageBitmap> createImageBitmap( diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index d48f16ea662..80fa021346c 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -11,6 +11,7 @@ use crate::dom::bindings::codegen::Bindings::HistoryBinding::HistoryBinding::His use crate::dom::bindings::codegen::Bindings::MediaQueryListBinding::MediaQueryListBinding::MediaQueryListMethods; use crate::dom::bindings::codegen::Bindings::PermissionStatusBinding::PermissionState; use crate::dom::bindings::codegen::Bindings::RequestBinding::RequestInit; +use crate::dom::bindings::codegen::Bindings::VoidFunctionBinding::VoidFunction; use crate::dom::bindings::codegen::Bindings::WindowBinding::{ self, FrameRequestCallback, WindowMethods, WindowPostMessageOptions, }; @@ -871,6 +872,12 @@ impl WindowMethods for Window { self.ClearTimeout(handle); } + // https://html.spec.whatwg.org/multipage/#dom-queuemicrotask + fn QueueMicrotask(&self, callback: Rc<VoidFunction>) { + self.upcast::<GlobalScope>() + .queue_function_as_microtask(callback); + } + // https://html.spec.whatwg.org/multipage/#dom-window fn Window(&self) -> DomRoot<WindowProxy> { self.window_proxy() diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index f29fd70f99f..0b8d7e33478 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -5,6 +5,7 @@ use crate::compartments::InCompartment; use crate::dom::bindings::cell::{DomRefCell, Ref}; use crate::dom::bindings::codegen::Bindings::RequestBinding::RequestInit; +use crate::dom::bindings::codegen::Bindings::VoidFunctionBinding::VoidFunction; use crate::dom::bindings::codegen::Bindings::WorkerBinding::WorkerType; use crate::dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods; use crate::dom::bindings::codegen::UnionTypes::{RequestOrUSVString, StringOrFunction}; @@ -341,6 +342,12 @@ impl WorkerGlobalScopeMethods for WorkerGlobalScope { self.ClearTimeout(handle); } + // https://html.spec.whatwg.org/multipage/#dom-queuemicrotask + fn QueueMicrotask(&self, callback: Rc<VoidFunction>) { + self.upcast::<GlobalScope>() + .queue_function_as_microtask(callback); + } + #[allow(unrooted_must_root)] // https://fetch.spec.whatwg.org/#fetch-method fn Fetch( diff --git a/components/script/microtask.rs b/components/script/microtask.rs index 001262c05e1..43628f46331 100644 --- a/components/script/microtask.rs +++ b/components/script/microtask.rs @@ -9,6 +9,7 @@ use crate::dom::bindings::callback::ExceptionHandling; use crate::dom::bindings::cell::DomRefCell; use crate::dom::bindings::codegen::Bindings::PromiseBinding::PromiseJobCallback; +use crate::dom::bindings::codegen::Bindings::VoidFunctionBinding::VoidFunction; use crate::dom::bindings::root::DomRoot; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlimageelement::ImageElementMicrotask; @@ -34,6 +35,7 @@ pub struct MicrotaskQueue { #[derive(JSTraceable, MallocSizeOf)] pub enum Microtask { Promise(EnqueuedPromiseCallback), + User(UserMicrotask), MediaElement(MediaElementMicrotask), ImageElement(ImageElementMicrotask), CustomElementReaction, @@ -52,6 +54,15 @@ pub struct EnqueuedPromiseCallback { pub pipeline: PipelineId, } +/// A microtask that comes from a queueMicrotask() Javascript call, +/// identical to EnqueuedPromiseCallback once it's on the queue +#[derive(JSTraceable, MallocSizeOf)] +pub struct UserMicrotask { + #[ignore_malloc_size_of = "Rc has unclear ownership"] + pub callback: Rc<VoidFunction>, + pub pipeline: PipelineId, +} + impl MicrotaskQueue { /// Add a new microtask to this queue. It will be invoked as part of the next /// microtask checkpoint. @@ -95,6 +106,11 @@ impl MicrotaskQueue { let _ = job.callback.Call_(&*target, ExceptionHandling::Report); } }, + Microtask::User(ref job) => { + if let Some(target) = target_provider(job.pipeline) { + let _ = job.callback.Call_(&*target, ExceptionHandling::Report); + } + }, Microtask::MediaElement(ref task) => { task.handler(); }, diff --git a/tests/wpt/metadata/html/browsers/the-window-object/window-properties.https.html.ini b/tests/wpt/metadata/html/browsers/the-window-object/window-properties.https.html.ini index 4f6538fdff6..d2a0fd7bb38 100644 --- a/tests/wpt/metadata/html/browsers/the-window-object/window-properties.https.html.ini +++ b/tests/wpt/metadata/html/browsers/the-window-object/window-properties.https.html.ini @@ -53,6 +53,3 @@ [Window method: createImageBitmap] expected: FAIL - [Window method: queueMicrotask] - expected: FAIL - diff --git a/tests/wpt/metadata/html/dom/idlharness.https.html.ini b/tests/wpt/metadata/html/dom/idlharness.https.html.ini index d4b393dda49..554531a68b5 100644 --- a/tests/wpt/metadata/html/dom/idlharness.https.html.ini +++ b/tests/wpt/metadata/html/dom/idlharness.https.html.ini @@ -1501,9 +1501,6 @@ [Document interface: attribute all] expected: FAIL - [Window interface: window must inherit property "queueMicrotask(VoidFunction)" with the proper type] - expected: FAIL - [Document interface: calling execCommand(DOMString, boolean, DOMString) on new Document() with too few arguments must throw TypeError] expected: FAIL @@ -1570,9 +1567,6 @@ [Window interface: window must inherit property "scrollbars" with the proper type] expected: FAIL - [Window interface: calling queueMicrotask(VoidFunction) on window with too few arguments must throw TypeError] - expected: FAIL - [Window interface: attribute personalbar] expected: FAIL @@ -1711,9 +1705,6 @@ [Document interface: iframe.contentDocument must inherit property "queryCommandState(DOMString)" with the proper type] expected: FAIL - [Window interface: operation queueMicrotask(VoidFunction)] - expected: FAIL - [Window interface: internal [[SetPrototypeOf\]\] method of interface prototype object - setting to a new value via Object.setPrototypeOf should throw a TypeError] expected: FAIL diff --git a/tests/wpt/metadata/html/dom/idlharness.worker.js.ini b/tests/wpt/metadata/html/dom/idlharness.worker.js.ini index b3939fc4efd..55715d00b01 100644 --- a/tests/wpt/metadata/html/dom/idlharness.worker.js.ini +++ b/tests/wpt/metadata/html/dom/idlharness.worker.js.ini @@ -98,9 +98,6 @@ [OffscreenCanvasRenderingContext2D interface: attribute shadowColor] expected: FAIL - [WorkerGlobalScope interface: self must inherit property "queueMicrotask(VoidFunction)" with the proper type] - expected: FAIL - [DedicatedWorkerGlobalScope interface: attribute name] expected: FAIL @@ -125,9 +122,6 @@ [OffscreenCanvasRenderingContext2D interface: operation translate(unrestricted double, unrestricted double)] expected: FAIL - [WorkerGlobalScope interface: operation queueMicrotask(VoidFunction)] - expected: FAIL - [Path2D interface: operation moveTo(unrestricted double, unrestricted double)] expected: FAIL @@ -158,9 +152,6 @@ [WorkerGlobalScope interface: self must inherit property "createImageBitmap(ImageBitmapSource, ImageBitmapOptions)" with the proper type] 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 diff --git a/tests/wpt/metadata/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini b/tests/wpt/metadata/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini index bc0b6e224ce..f6acbb1bd28 100644 --- a/tests/wpt/metadata/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini +++ b/tests/wpt/metadata/html/webappapis/microtask-queuing/queue-microtask-exceptions.any.js.ini @@ -1,8 +1,3 @@ -[queue-microtask-exceptions.any.html] - [It rethrows exceptions] - expected: FAIL - - [queue-microtask-exceptions.any.serviceworker.html] expected: ERROR [queue-microtask-exceptions] @@ -18,9 +13,3 @@ expected: ERROR [queue-microtask-exceptions] expected: FAIL - - -[queue-microtask-exceptions.any.worker.html] - [It rethrows exceptions] - expected: FAIL - diff --git a/tests/wpt/metadata/html/webappapis/microtask-queuing/queue-microtask.any.js.ini b/tests/wpt/metadata/html/webappapis/microtask-queuing/queue-microtask.any.js.ini index e9a886d8887..a6bd235e24d 100644 --- a/tests/wpt/metadata/html/webappapis/microtask-queuing/queue-microtask.any.js.ini +++ b/tests/wpt/metadata/html/webappapis/microtask-queuing/queue-microtask.any.js.ini @@ -1,20 +1,3 @@ -[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.serviceworker.html] expected: ERROR [queue-microtask] @@ -31,21 +14,3 @@ expected: TIMEOUT [queue-microtask] 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 - diff --git a/tests/wpt/metadata/html/webappapis/microtask-queuing/queue-microtask.window.js.ini b/tests/wpt/metadata/html/webappapis/microtask-queuing/queue-microtask.window.js.ini deleted file mode 100644 index de2c5592973..00000000000 --- a/tests/wpt/metadata/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 - |