Skip to content

fix(register): do not inherit parent execArgv - #18131

Merged
JLHwung merged 6 commits into
babel:mainfrom
JLHwung:fix-18130
Jul 17, 2026
Merged

JLHwung merged 6 commits into
babel:mainfrom
JLHwung:fix-18130

Conversation

@JLHwung

@JLHwung JLHwung commented Jul 13, 2026

Copy link
Copy Markdown
Contributor
Q 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 A
Fixed Issues? Fixes #18130
Patch: Bug Fix? Yes
Major: Breaking Change?
Minor: New Feature?
Tests Added + Pass? Yes
Documentation PR Link
Any Dependency Changes?
License MIT

In this PR we avoid inheriting command line arguments for the babel-register worker, per the best practise mentioned in https://nodejs.org/api/worker_threads.html#launching-worker-threads-from-preload-scripts.

A new Worker threads will inherit command line flags, including -r, but will discard the -e flag, when the --input-type flag is passed down without -e flag, an error is thrown from the module loader, and the signal does not have a chance to change so the Atomics.wait will block event loop indefinitely.

We also add a new feature to the process fixture test: The test will now resolve the special <rootDir> / <rootUrl> token into the root of the monorepo. With the new feature, we can properly test the behaviour of Node.js when @babel/register is preloaded via --require or --import.

Per https://nodejs.org/api/worker_threads.html#launching-worker-threads-from-preload-scripts, new Worker threads will inherit command line flags, including `-e` and `-r`.

When they are combined with the `--input-type`, Node.js somehow hangs and the worker does not start.
@babel-bot

babel-bot commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/61899

@pkg-pr-new

pkg-pr-new Bot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

commit: a7f071a

@JLHwung
JLHwung marked this pull request as ready for review July 14, 2026 01:26
@nicolo-ribaudo

Copy link
Copy Markdown
Member

Is this a Node.js bug or intended behavior on their side?

@liuxingbaoyu

Copy link
Copy Markdown
Member

Node.js somehow hangs and the worker does not start.

Error [ERR_INPUT_TYPE_NOT_ALLOWED]: --input-type can only be used with string input via --eval, --print, or STDIN

In this PR we avoid inheriting command line arguments for the babel-register worker, per the best practise mentioned in nodejs.org/api/worker_threads.html#launching-worker-threads-from-preload-scripts.

Amazing! Thanks to this, we can remove both markInRegisterWorker and isInRegisterWorker.

@liuxingbaoyu liuxingbaoyu added PR: Bug Fix 馃悰 A type of pull request used for our changelog categories pkg: register labels Jul 14, 2026
@JLHwung

JLHwung commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

@nicolo-ribaudo wrote

Is this a Node.js bug or intended behavior on their side?

@liuxingbaoyu wrote

Error [ERR_INPUT_TYPE_NOT_ALLOWED]: --input-type can only be used with string input via --eval, --print, or STDIN

Yes, so what's happening here is that Node.js does not pass --eval to the worker but passed --input-type, an error is thrown when the esm loader is loading the worker and the signal does not have a chance to change so the event loop is blocked indefinitely.

Here is a minimum reproduction case without babel-register:

// server.js
import { parentPort, isMainThread, Worker } from "node:worker_threads";

if (isMainThread) {
  const worker = new Worker(new URL(import.meta.url), { execArgv: process.execArgv });
  const signal = new Int32Array(new SharedArrayBuffer(4), 0, 1);
  worker.postMessage({ signal });
  Atomics.wait(signal, 0, 0, 1000);
  worker.unref();
} else {
  parentPort.addListener("message", ({ signal }) => {
    Atomics.store(signal, 0, 1);
    Atomics.notify(signal, 0, 1);
  });
}
node --import ./server.js --input-type=module -e "console.log(0)"

Though it would be great if the error ERR_INPUT_TYPE_NOT_ALLOWED can somehow be captured, either from a worker event or is populated from new Worker(...). Currently the error is only piped to the stderr of the main thread.

Update: so any uncaught error thrown from the worker will emit the error event, but Atomics.wait blocks the loop so Node.js does not have a chance to handle it. I think this is an essential limit of our current wrap-async-within-sync approach.

What we could do is to add a realistic timeout to the Atomics.wait, e.g. 30 seconds or smaller amount, so at least when there is uncaught error during the loading step, the error will eventually show up.

@JLHwung
JLHwung merged commit 81f752b into babel:main Jul 17, 2026
57 checks passed
@JLHwung
JLHwung deleted the fix-18130 branch July 17, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg: register PR: Bug Fix 馃悰 A type of pull request used for our changelog categories

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@babel/register 8 hangs when the program is piped via stdin with --input-type

4 participants