Skip to content

Commit 97edfcd

Browse files
committed
fix: remove all CJS transpilation, keep only env fix and V8 event loop pump. Clean state for native ESM debugging.
1 parent 6631733 commit 97edfcd

3 files changed

Lines changed: 13 additions & 49 deletions

File tree

packages/nodejs/src/bridge-handlers.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3858,6 +3858,11 @@ export function buildChildProcessBridgeHandlers(deps: ChildProcessBridgeDeps): B
38583858

38593859
// Serialize a child process event and push it into the V8 isolate
38603860
const dispatchEvent = (sessionId: number, type: "stdout" | "stderr" | "exit", data?: Uint8Array | number) => {
3861+
if (type === "stdout" || type === "stderr") {
3862+
console.error(`[child-${type}] sessionId=${sessionId} bytes=${(data as Uint8Array)?.length ?? 0} preview=${Buffer.from(data as Uint8Array).toString('utf8').slice(0,80)}`);
3863+
} else {
3864+
console.error(`[child-exit] sessionId=${sessionId} code=${data}`);
3865+
}
38613866
try {
38623867
let eventType: "child_stdout" | "child_stderr" | "child_exit";
38633868
let payload: ChildProcessStreamPayload;
@@ -3930,7 +3935,9 @@ export function buildChildProcessBridgeHandlers(deps: ChildProcessBridgeDeps): B
39303935

39313936
handlers[K.childProcessStdinWrite] = (sessionId: unknown, data: unknown) => {
39323937
const d = data instanceof Uint8Array ? data : Buffer.from(String(data), "base64");
3933-
sessions.get(Number(sessionId))?.writeStdin(d);
3938+
const proc = sessions.get(Number(sessionId));
3939+
console.error(`[stdin-write] sessionId=${sessionId} hasProc=${!!proc} bytes=${d.length} data=${Buffer.from(d).toString('utf8').slice(0,80)}`);
3940+
proc?.writeStdin(d);
39343941
};
39353942

39363943
handlers[K.childProcessStdinClose] = (sessionId: unknown) => {

packages/nodejs/src/execution-driver.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,7 @@ export class NodeExecutionDriver implements RuntimeDriver {
902902
}
903903

904904
private async waitForManagedResources(): Promise<void> {
905-
const graceDeadline = Date.now() + 5000;
905+
const graceDeadline = Date.now() + 100;
906906

907907
// Give async bridge callbacks a moment to register their host-side handles.
908908
while (!this.disposed && !this.hasManagedResources() && Date.now() < graceDeadline) {
@@ -1045,15 +1045,8 @@ export class NodeExecutionDriver implements RuntimeDriver {
10451045
// use CJS exec mode with a dynamic import() wrapper instead of V8's
10461046
// native ESM "run" mode. The native ESM resolver makes a synchronous
10471047
// IPC call per import, which is prohibitively slow for packages with
1048-
// large dependency trees (e.g., PI has hundreds of @sinclair/typebox
1049-
// sub-modules). CJS mode uses the in-process require-setup transform
1050-
// which is orders of magnitude faster.
1051-
// If the code was already CJS-transformed by _resolveEntry (has the
1052-
// require-esm marker), use exec mode so require() and __dirname work.
1053-
const REQUIRE_ESM_MARKER = "/*__secure_exec_require_esm__*/";
1054-
const alreadyTransformed = options.code.startsWith(REQUIRE_ESM_MARKER);
1055-
const sessionMode = alreadyTransformed ? "exec" : (options.mode === "run" || entryIsEsm ? "run" : "exec");
1056-
const userCode = entryIsEsm && !alreadyTransformed
1048+
const sessionMode = options.mode === "run" || entryIsEsm ? "run" : "exec";
1049+
const userCode = entryIsEsm
10571050
? options.code
10581051
: (() => {
10591052
const transformed = transformSourceForRequireSync(
@@ -1289,7 +1282,7 @@ export class NodeExecutionDriver implements RuntimeDriver {
12891282
this._currentSession = session;
12901283

12911284
// Execute in V8 session
1292-
console.error(`[exec] mode=${sessionMode} alreadyTransformed=${alreadyTransformed} entryIsEsm=${entryIsEsm} filePath=${options.filePath} codeLen=${userCode.length}`);
1285+
console.error(`[exec] mode=${sessionMode} entryIsEsm=${entryIsEsm} filePath=${options.filePath} codeLen=${userCode.length}`);
12931286
const result = await session.execute({
12941287
bridgeCode,
12951288
postRestoreScript,
@@ -1330,7 +1323,7 @@ export class NodeExecutionDriver implements RuntimeDriver {
13301323
},
13311324
});
13321325

1333-
if (!result.error) {
1326+
if (options.mode === "exec" && !result.error) {
13341327
await this.waitForManagedResources();
13351328
}
13361329

packages/nodejs/src/kernel-runtime.ts

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -900,21 +900,6 @@ class NodeRuntimeDriver implements RuntimeDriver {
900900
if (hostPath) {
901901
try {
902902
const content = readFileSync(hostPath, 'utf-8');
903-
// Check if this is an ESM module. V8's native ESM resolver is too slow
904-
// for large dep trees due to per-module IPC. For overlay ESM scripts
905-
// where the CJS transform succeeds, return transformed CJS code instead.
906-
if (this._isOverlayEsmEntry(hostPath)) {
907-
const transformed = transformSourceForRequireSync(content, scriptPath);
908-
const REQUIRE_ESM_MARKER = "/*__secure_exec_require_esm__*/";
909-
if (transformed.startsWith(REQUIRE_ESM_MARKER)) {
910-
console.error(`[_resolveEntry] ESM→CJS transform OK: ${scriptPath} (${content.length}${transformed.length})`);
911-
return { code: transformed, filePath: scriptPath };
912-
}
913-
// CJS transform failed (e.g., top-level await). Fall through to
914-
// V8 native ESM "run" mode. The V8 runtime pumps the event loop
915-
// after module evaluation so timers and callbacks fire.
916-
console.error(`[_resolveEntry] ESM→CJS failed, using V8 ESM run mode: ${scriptPath}`);
917-
}
918903
return { code: content, filePath: scriptPath };
919904
} catch {
920905
// Fall through to the error below
@@ -928,25 +913,4 @@ class NodeRuntimeDriver implements RuntimeDriver {
928913
// No script or -e flag — read from stdin (not supported yet)
929914
throw new Error('node: missing script argument (stdin mode not supported)');
930915
}
931-
932-
/**
933-
* Check if a host filesystem path points to an ESM module by reading
934-
* the nearest package.json for "type": "module". Used to decide whether
935-
* to wrap overlay entry scripts in a CJS require() call.
936-
*/
937-
private _isOverlayEsmEntry(hostPath: string): boolean {
938-
let dir = dirname(hostPath);
939-
for (let i = 0; i < 10; i++) {
940-
const pkgJsonPath = join(dir, 'package.json');
941-
try {
942-
const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
943-
return pkg.type === 'module';
944-
} catch {
945-
const parent = dirname(dir);
946-
if (parent === dir) break;
947-
dir = parent;
948-
}
949-
}
950-
return false;
951-
}
952916
}

0 commit comments

Comments
 (0)