22// License, v. 2.0. If a copy of the MPL was not distributed with this
33// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44
5+ use crate :: RuntimeMacroTask ;
56use andromeda_core:: { Extension , ExtensionOp } ;
7+ use andromeda_core:: { HostData , MacroTask } ;
8+ use nova_vm:: engine:: Global ;
69use nova_vm:: {
710 ecmascript:: {
811 builtins:: ArgumentsList ,
@@ -11,6 +14,7 @@ use nova_vm::{
1114 } ,
1215 engine:: context:: { Bindable , GcScope , NoGcScope } ,
1316} ;
17+
1418use std:: time:: { Instant , SystemTime , UNIX_EPOCH } ;
1519
1620// TODO: Get the time origin from when the runtime starts
@@ -45,6 +49,7 @@ impl WebExt {
4549 Self :: internal_performance_time_origin,
4650 0 ,
4751 ) ,
52+ ExtensionOp :: new( "queueMicrotask" , Self :: queue_microtask, 1 ) ,
4853 ] ,
4954 storage : None ,
5055 files : vec ! [
@@ -420,4 +425,50 @@ impl WebExt {
420425
421426 Ok ( Value :: from_f64 ( agent, origin_ms, gc) . unbind ( ) )
422427 }
428+
429+ /// Implementation of queueMicrotask as per HTML specification:
430+ /// https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-queuemicrotask
431+ pub fn queue_microtask < ' gc > (
432+ agent : & mut Agent ,
433+ _this : Value ,
434+ args : ArgumentsList ,
435+ gc : GcScope < ' gc , ' _ > ,
436+ ) -> JsResult < ' gc , Value < ' gc > > {
437+ let callback = args. get ( 0 ) ;
438+ let _: nova_vm:: ecmascript:: types:: Function = match callback. try_into ( ) {
439+ Ok ( function) => function,
440+ Err ( _) => {
441+ return Err ( agent
442+ . throw_exception (
443+ ExceptionType :: TypeError ,
444+ "The callback provided as an argument to queueMicrotask must be a function." . to_string ( ) ,
445+ gc. nogc ( ) ,
446+ )
447+ . unbind ( ) ) ;
448+ }
449+ } ;
450+
451+ // TODO: Implement proper microtask queueing when Nova APIs become available
452+
453+ // Store the callback globally so it can be called later
454+ let root_callback = Global :: new ( agent, callback. unbind ( ) ) ;
455+
456+ // Get host data to access the macro task system
457+ let host_data = agent. get_host_data ( ) ;
458+ let host_data: & HostData < RuntimeMacroTask > = host_data. downcast_ref ( ) . unwrap ( ) ;
459+ let macro_task_tx = host_data. macro_task_tx ( ) ;
460+
461+ // Schedule an immediate task to call the callback
462+ // Using spawn_macro_task with an immediately resolving future
463+ host_data. spawn_macro_task ( async move {
464+ // Send a macro task to call the callback
465+ macro_task_tx
466+ . send ( MacroTask :: User ( RuntimeMacroTask :: RunMicrotaskCallback (
467+ root_callback,
468+ ) ) )
469+ . unwrap ( ) ;
470+ } ) ;
471+
472+ Ok ( Value :: Undefined )
473+ }
423474}
0 commit comments