From 8e9d3f94ac1cbcefe989115266026f5fd3e0a947 Mon Sep 17 00:00:00 2001 From: kaustubhOG Date: Wed, 1 Jul 2026 09:37:18 +0530 Subject: [PATCH] feat(wintertc): migrate queueMicrotask from boa_runtime --- core/wintertc/src/microtask/mod.rs | 40 ++++++++++++++------- core/wintertc/src/microtask/tests.rs | 52 ++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 core/wintertc/src/microtask/tests.rs diff --git a/core/wintertc/src/microtask/mod.rs b/core/wintertc/src/microtask/mod.rs index bae48303b4e..e1a40c7a226 100644 --- a/core/wintertc/src/microtask/mod.rs +++ b/core/wintertc/src/microtask/mod.rs @@ -5,19 +5,35 @@ //! # TC55 Status //! //! `queueMicrotask` is required in the `WinterTC` TC55 Minimum Common Web API. -//! -//! # TODO -//! -//! - Migrate `queueMicrotask` from `boa_runtime::microtask`. +use boa_engine::realm::Realm; +use boa_engine::{Context, JsResult, boa_module}; + +#[cfg(test)] +mod tests; + +/// JavaScript module containing the `queueMicrotask` function. +#[boa_module] +pub mod js_module { + use boa_engine::job::{Job, PromiseJob}; + use boa_engine::object::builtins::JsFunction; + use boa_engine::{Context, JsValue}; -/// Register `queueMicrotask` into the given context. + /// The [`queueMicrotask()`][mdn] method of the `Window` interface queues a + /// microtask to be executed at a safe time prior to control returning to + /// the browser's event loop. + /// + /// [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/Window/queueMicrotask + pub fn queue_microtask(callback: JsFunction, context: &mut Context) { + context.enqueue_job(Job::from(PromiseJob::new(move |context| { + callback.call(&JsValue::undefined(), &[], context) + }))); + } +} + +/// Register the `queueMicrotask` function to the realm or context. /// /// # Errors -/// -/// Returns a [`boa_engine::JsError`] if registration fails. -pub fn register( - _realm: Option, - _ctx: &mut boa_engine::Context, -) -> boa_engine::JsResult<()> { - Ok(()) +/// Returns an error if the microtask extension cannot be registered. +pub fn register(realm: Option, context: &mut Context) -> JsResult<()> { + js_module::boa_register(realm, context) } diff --git a/core/wintertc/src/microtask/tests.rs b/core/wintertc/src/microtask/tests.rs new file mode 100644 index 00000000000..e8ee935cbda --- /dev/null +++ b/core/wintertc/src/microtask/tests.rs @@ -0,0 +1,52 @@ +use crate::test::{TestAction, run_test_actions_with}; +use boa_engine::Context; +use indoc::indoc; + +#[test] +fn queue_microtask() { + let context = &mut Context::default(); + crate::microtask::register(None, context).unwrap(); + + run_test_actions_with( + [ + // Queue a nested set of microtasks, recording execution order into + // a global array. Microtasks run in FIFO order after the current + // synchronous task completes, and microtasks queued from within a + // microtask are appended to the same queue. + TestAction::run(indoc! {r#" + globalThis.order = []; + order.push(1); + queueMicrotask(() => order.push(2)); + order.push(3); + queueMicrotask(() => { + order.push(4); + queueMicrotask(() => { + order.push(5); + queueMicrotask(() => order.push(6)); + order.push(7); + }); + order.push(8); + }); + order.push(9); + "#}), + // Drain the microtask (job) queue. + TestAction::inspect_context(|context| { + context.run_jobs().unwrap(); + }), + // The synchronous pushes (1, 3, 9) run first, then the microtasks + // in the order they were queued and re-queued. + TestAction::run(indoc! {r#" + var expected = [1, 3, 9, 2, 4, 8, 5, 7, 6]; + if (order.length !== expected.length) { + throw new Error("wrong length: [" + order + "]"); + } + for (var i = 0; i < expected.length; i++) { + if (order[i] !== expected[i]) { + throw new Error("wrong order at " + i + ": [" + order + "]"); + } + } + "#}), + ], + context, + ); +}