@@ -879,23 +879,46 @@ pub(crate) fn run_event_loop(
879879 break ;
880880 }
881881
882- // Receive next command, with optional abort monitoring
883- let cmd = if let Some ( abort) = abort_rx {
884- crossbeam_channel:: select! {
885- recv( rx) -> result => match result {
886- Ok ( cmd) => cmd,
887- Err ( _) => return EventLoopStatus :: Terminated ,
888- } ,
889- recv( abort) -> _ => {
890- // Timeout fired — abort channel closed
891- scope. terminate_execution( ) ;
892- return EventLoopStatus :: Terminated ;
893- } ,
882+ // Receive next command with interleaved microtask processing.
883+ // Instead of blocking indefinitely, use a short timeout so we can
884+ // periodically flush microtasks (like Node.js's libuv + DrainTasks pattern).
885+ let cmd = loop {
886+ let recv_result = if let Some ( abort) = abort_rx {
887+ crossbeam_channel:: select! {
888+ recv( rx) -> result => result. ok( ) ,
889+ recv( abort) -> _ => {
890+ scope. terminate_execution( ) ;
891+ return EventLoopStatus :: Terminated ;
892+ } ,
893+ default ( std:: time:: Duration :: from_millis( 1 ) ) => None ,
894+ }
895+ } else {
896+ rx. recv_timeout ( std:: time:: Duration :: from_millis ( 1 ) ) . ok ( )
897+ } ;
898+ if let Some ( cmd) = recv_result {
899+ break cmd;
894900 }
895- } else {
896- match rx. recv ( ) {
897- Ok ( cmd) => cmd,
898- Err ( _) => return EventLoopStatus :: Terminated ,
901+ // No command received — flush microtasks and check deferred queue
902+ scope. perform_microtask_checkpoint ( ) ;
903+ if let Some ( dq) = deferred {
904+ if !dq. lock ( ) . unwrap ( ) . is_empty ( ) {
905+ // New deferred work appeared — drain it in the outer loop
906+ let frames: Vec < BinaryFrame > = dq. lock ( ) . unwrap ( ) . drain ( ..) . collect ( ) ;
907+ for frame in frames {
908+ let status = dispatch_event_loop_frame ( scope, frame, pending) ;
909+ if !matches ! ( status, EventLoopStatus :: Completed ) {
910+ return status;
911+ }
912+ }
913+ }
914+ }
915+ // Check if we should exit
916+ if pending. len ( ) == 0
917+ && !execution:: pending_module_evaluation_needs_wait ( scope)
918+ && !execution:: pending_script_evaluation_needs_wait ( scope)
919+ && deferred. map ( |dq| dq. lock ( ) . unwrap ( ) . is_empty ( ) ) . unwrap_or ( true )
920+ {
921+ return EventLoopStatus :: Completed ;
899922 }
900923 } ;
901924
0 commit comments