forked from TypeStrong/ts-node
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix ESM node processes being unable to fork into other scripts
Currently, Node processes instantiated through the `--esm` flag result in a child process being created so that the ESM loader can be registered. This works fine and is reasonable. The child process approach to register ESM hooks currently prevents the NodeJS `fork` method from being used because the `execArgv` propagated into forked processes causes `ts-node` (which is also propagated as child exec script -- this is good because it allows nested type resolution to work) to always execute the original entry-point, causing potential infinite loops because the designated fork module script is not executed as expected. This commit fixes this by not encoding the entry-point information into the state that is captured as part of the `execArgv`. Instead the entry-point information is always retrieved from the parsed rest command line arguments in the final stage (`phase4`). Additionally, this PR streamlines the boostrap mechanism to always call into the child script, resulting in reduced complexity, and also improved caching for user-initiated forked processes. i.e. the tsconfig resolution is not repeated multiple-times because forked processes are expected to preserve the existing ts-node project. More details can be found here TypeStrong#1831. Fixes TypeStrong#1812.
- Loading branch information
1 parent
aa5ec36
commit 7c0678f
Showing
36 changed files
with
638 additions
and
129 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { pathToFileURL } from 'url'; | ||
import { brotliCompressSync } from 'zlib'; | ||
import type { BootstrapStateForChild } from '../bin'; | ||
import { versionGteLt } from '../util'; | ||
|
||
const argPrefix = '--brotli-base64-config='; | ||
|
||
export function getChildProcessArguments( | ||
enableEsmLoader: boolean, | ||
state: BootstrapStateForChild | ||
) { | ||
if (enableEsmLoader && !versionGteLt(process.versions.node, '12.17.0')) { | ||
throw new Error( | ||
'`ts-node-esm` and `ts-node --esm` require node version 12.17.0 or newer.' | ||
); | ||
} | ||
|
||
const nodeExecArgs = []; | ||
|
||
if (enableEsmLoader) { | ||
nodeExecArgs.push( | ||
'--require', | ||
require.resolve('./child-require.js'), | ||
'--loader', | ||
// Node on Windows doesn't like `c:\` absolute paths here; must be `file:///c:/` | ||
pathToFileURL(require.resolve('../../child-loader.mjs')).toString() | ||
); | ||
} | ||
|
||
const childScriptArgs = [ | ||
`${argPrefix}${brotliCompressSync( | ||
Buffer.from(JSON.stringify(state), 'utf8') | ||
).toString('base64')}`, | ||
]; | ||
|
||
return { | ||
nodeExecArgs, | ||
childScriptArgs, | ||
childScriptPath: require.resolve('./child-entrypoint.js'), | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
tests/esm-child-process/process-forking-nested-esm-node-next/index.mts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { fork } from 'child_process'; | ||
import { dirname, join } from 'path'; | ||
import { fileURLToPath } from 'url'; | ||
|
||
// Initially set the exit code to non-zero. We only set it to `0` when the | ||
// worker process finishes properly with the expected stdout message. | ||
process.exitCode = 1; | ||
|
||
const projectDir = dirname(fileURLToPath(import.meta.url)); | ||
const workerProcess = fork(join(projectDir, 'worker.mts'), [], { | ||
stdio: 'pipe', | ||
}); | ||
|
||
let stdout = ''; | ||
|
||
workerProcess.stdout.on('data', (chunk) => (stdout += chunk.toString('utf8'))); | ||
workerProcess.on('error', () => (process.exitCode = 1)); | ||
workerProcess.on('close', (status, signal) => { | ||
if (status === 0 && signal === null && stdout.trim() === 'Works') { | ||
console.log('Passing: from main'); | ||
process.exitCode = 0; | ||
} | ||
}); |
5 changes: 5 additions & 0 deletions
5
tests/esm-child-process/process-forking-nested-esm-node-next/tsconfig.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "NodeNext" | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
tests/esm-child-process/process-forking-nested-esm-node-next/worker.mts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const message: string = 'Works'; | ||
|
||
console.log(message); |
20 changes: 20 additions & 0 deletions
20
tests/esm-child-process/process-forking-nested-esm/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { fork } from 'child_process'; | ||
|
||
// Initially set the exit code to non-zero. We only set it to `0` when the | ||
// worker process finishes properly with the expected stdout message. | ||
process.exitCode = 1; | ||
|
||
const workerProcess = fork('./worker.ts', [], { | ||
stdio: 'pipe', | ||
}); | ||
|
||
let stdout = ''; | ||
|
||
workerProcess.stdout.on('data', (chunk) => (stdout += chunk.toString('utf8'))); | ||
workerProcess.on('error', () => (process.exitCode = 1)); | ||
workerProcess.on('close', (status, signal) => { | ||
if (status === 0 && signal === null && stdout.trim() === 'Works') { | ||
console.log('Passing: from main'); | ||
process.exitCode = 0; | ||
} | ||
}); |
3 changes: 3 additions & 0 deletions
3
tests/esm-child-process/process-forking-nested-esm/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"type": "module" | ||
} |
Oops, something went wrong.