Skip to content

Commit b8a7c29

Browse files
committed
fix: flush microtasks in event loop before blocking, add extensive stdin chain logging
1 parent 60c9cd6 commit b8a7c29

5 files changed

Lines changed: 27 additions & 3 deletions

File tree

native/v8-runtime/src/execution.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -930,9 +930,10 @@ pub fn execute_module(
930930
prefetch_module_imports(tc, bridge_ctx, module, resource_name_str);
931931

932932
// Instantiate (calls resolve callback for each import — mostly cache hits now)
933-
if module
934-
.instantiate_module(tc, module_resolve_callback)
935-
.is_none()
933+
eprintln!("[v8-runtime] instantiating module...");
934+
let inst_result = module.instantiate_module(tc, module_resolve_callback);
935+
eprintln!("[v8-runtime] instantiate result: {:?}", inst_result.is_some());
936+
if inst_result.is_none()
936937
{
937938
clear_module_state();
938939
return match tc.exception() {
@@ -945,7 +946,9 @@ pub fn execute_module(
945946
}
946947

947948
// Evaluate
949+
eprintln!("[v8-runtime] evaluating module...");
948950
let eval_result = module.evaluate(tc);
951+
eprintln!("[v8-runtime] evaluate done: result={}", eval_result.is_some());
949952
if eval_result.is_none() {
950953
clear_module_state();
951954
return match tc.exception() {
@@ -1287,6 +1290,7 @@ fn resolve_or_compile_module<'s>(
12871290
};
12881291
let mut compiled = v8::script_compiler::Source::new(v8_source, Some(&origin));
12891292
let module = v8::script_compiler::compile_module(scope, &mut compiled)?;
1293+
eprintln!("[v8-runtime] compiled OK: {}", &resolved_path);
12901294

12911295
MODULE_RESOLVE_STATE.with(|cell| {
12921296
if let Some(state) = cell.borrow_mut().as_mut() {

native/v8-runtime/src/session.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,21 @@ pub(crate) fn run_event_loop(
856856
}
857857
}
858858

859+
// Flush microtasks before blocking. This ensures that Promise
860+
// continuations (e.g., main() returning from async module evaluation)
861+
// run even when no bridge commands are pending.
862+
scope.perform_microtask_checkpoint();
863+
864+
// Re-check exit conditions after microtask flush — the microtask may
865+
// have resolved all pending promises or registered new handles.
866+
if pending.len() == 0
867+
&& !execution::pending_module_evaluation_needs_wait(scope)
868+
&& !execution::pending_script_evaluation_needs_wait(scope)
869+
&& deferred.map(|dq| dq.lock().unwrap().is_empty()).unwrap_or(true)
870+
{
871+
break;
872+
}
873+
859874
// Receive next command, with optional abort monitoring
860875
let cmd = if let Some(abort) = abort_rx {
861876
crossbeam_channel::select! {

packages/nodejs/src/bridge-handlers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3609,10 +3609,13 @@ export function buildKernelStdinDispatchHandlers(
36093609

36103610
handlers[K.kernelStdinRead] = async () => {
36113611
checkBridgeBudget(deps);
3612+
console.error(`[kernelStdinRead] hasLiveSource=${!!deps.liveStdinSource} reading...`);
36123613
if (!deps.liveStdinSource) {
3614+
console.error(`[kernelStdinRead] no source, returning done`);
36133615
return { done: true };
36143616
}
36153617
const chunk = await deps.liveStdinSource.read();
3618+
console.error(`[kernelStdinRead] got chunk: ${chunk ? chunk.length + ' bytes' : 'null'}`);
36163619
if (chunk === null || chunk.length === 0) {
36173620
return { done: true };
36183621
}

packages/nodejs/src/execution-driver.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,7 @@ function buildPostRestoreScript(
15151515
}
15161516

15171517
// Enable streaming stdin for non-TTY processes that need live stdin delivery
1518+
console.error(`[postRestore] streamStdin=${bridgeConfig.streamStdin} mode=${mode}`);
15181519
if (bridgeConfig.streamStdin) {
15191520
parts.push(`globalThis.__runtimeStreamStdin = true;`);
15201521
}

packages/nodejs/src/kernel-runtime.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ class NodeRuntimeDriver implements RuntimeDriver {
506506
let batchStdinResolve: ((data: string | undefined) => void) | null = null;
507507
let batchStdinPromise: Promise<string | undefined> | undefined;
508508

509+
console.error(`[kernel-runtime] pid=${ctx.pid} streamStdin=${ctx.streamStdin} command=${command}`);
509510
if (ctx.streamStdin) {
510511
// Streaming mode: writeStdin delivers data to the running process immediately
511512
const stdinQueue: Uint8Array[] = [];

0 commit comments

Comments
 (0)