Skip to content

Commit 7895c77

Browse files
committed
fix: microtask loop flush, extensive IPC tracing. PI eval completes but main() stuck - pending bridge promise blocks.
1 parent 644b744 commit 7895c77

4 files changed

Lines changed: 19 additions & 6 deletions

File tree

native/v8-runtime/src/execution.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -946,9 +946,10 @@ pub fn execute_module(
946946
}
947947

948948
// Evaluate
949-
eprintln!("[v8-runtime] evaluating module...");
949+
let eval_start = std::time::Instant::now();
950+
eprintln!("[v8-runtime] evaluating module (resource={})...", resource_name_str);
950951
let eval_result = module.evaluate(tc);
951-
eprintln!("[v8-runtime] evaluate done: result={}", eval_result.is_some());
952+
eprintln!("[v8-runtime] evaluate done: result={} elapsed={}ms", eval_result.is_some(), eval_start.elapsed().as_millis());
952953
if eval_result.is_none() {
953954
clear_module_state();
954955
return match tc.exception() {

native/v8-runtime/src/session.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -856,10 +856,18 @@ 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();
859+
// Flush microtasks before blocking. Run in a loop to drain the full
860+
// microtask queue -- each checkpoint may resolve Promises that schedule
861+
// new microtasks (e.g., async function await chains).
862+
for _ in 0..100 {
863+
scope.perform_microtask_checkpoint();
864+
// Check if new deferred work appeared from microtask processing
865+
if let Some(dq) = deferred {
866+
if !dq.lock().unwrap().is_empty() {
867+
break; // New bridge work to process
868+
}
869+
}
870+
}
863871

864872
// Re-check exit conditions after microtask flush — the microtask may
865873
// have resolved all pending promises or registered new handles.

packages/nodejs/src/bridge-handlers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3443,8 +3443,11 @@ export function buildModuleLoadingBridgeHandlers(
34433443
}
34443444

34453445
// Regular files load differently for CommonJS require() vs V8's ESM loader.
3446+
console.error(`[loadFile-async] falling to async path for: ${p.slice(-60)}`);
34463447
return (async () => {
3448+
console.error(`[loadFile-async] loading from VFS: ${p.slice(-60)}`);
34473449
const source = await loadFile(p, deps.filesystem);
3450+
console.error(`[loadFile-async] VFS result: ${source ? source.length + ' bytes' : 'null'}`);
34483451
if (source === null) return null;
34493452
if (loadMode === "require") {
34503453
return transformSourceForRequire(source, p);

packages/nodejs/src/module-access.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ export class ModuleAccessFileSystem implements VirtualFileSystem {
476476
!this.hostNodeModulesRoot ||
477477
!this.isWithinAllowedOverlayRoots(canonical)
478478
) {
479+
console.error(`[module-access] OUT_OF_SCOPE: virtualPath=${virtualPath} canonical=${canonical} allowedRoots=${this.overlayAllowedRoots.length} first3=${this.overlayAllowedRoots.slice(0,3).join(', ')}`);
479480
throw createModuleAccessError(
480481
MODULE_ACCESS_OUT_OF_SCOPE,
481482
`resolved path for '${virtualPath}' escapes allowed overlay roots`,

0 commit comments

Comments
 (0)