Skip to content

Allow running tests in child processes#17486

Open
liuxingbaoyu wants to merge 4 commits into
babel:mainfrom
liuxingbaoyu:exec-worker
Open

Allow running tests in child processes#17486
liuxingbaoyu wants to merge 4 commits into
babel:mainfrom
liuxingbaoyu:exec-worker

Conversation

@liuxingbaoyu

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

This is in preparation for Babel 8.
After we clean up our Babel 7 code, we still want to test compatibility with older Node.js versions.
This also makes it easier for local development, as we can now quickly test compatibility with older versions.

Usage: cross-env EXEC_TESTS_NODE=16 yarn jest

@babel-bot

babel-bot commented Aug 21, 2025

Copy link
Copy Markdown
Collaborator

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

@pkg-pr-new

pkg-pr-new Bot commented Aug 21, 2025

Copy link
Copy Markdown

Open in StackBlitz

commit: 2db29ec

@liuxingbaoyu liuxingbaoyu force-pushed the exec-worker branch 6 times, most recently from f7a8c25 to 0630f73 Compare September 17, 2025 22:48

@nicolo-ribaudo nicolo-ribaudo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@liuxingbaoyu liuxingbaoyu force-pushed the exec-worker branch 2 times, most recently from 09eb690 to 0f6d4ed Compare September 18, 2025 18:10
return new Promise((resolve, reject) => {
if (!(globalThis as any).worker) {
const workerFile = path.join(dirname, "worker.js");
const worker = ((globalThis as any).worker = spawn("fnm", [

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am on the fence with the introduction of a new node version manager for the test purpose, if the fnm website is down the whole CI pipeline will be blocked, too. And it is not very efficient that every babel-8-exec test pipeline has to install a version manager.

Would it be possible to make EXEC_TESTS_NODE independent of the node version manager? For example let EXEC_TESTS_NODE_BIN be the path to the exec test node binary, then we can directly pass it to spawn. Doing so should reduce the runtime overhead of the version manager since we have thousands of exec tests.

The path to the node binary should be easily obtained from any node version manager. With this approach, we may just use the node 6 installed from the setup-node action, it is likely provided in the CI runner toolchain, too.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing so should reduce the runtime overhead of the version manager since we have thousands of exec tests.

We only initialize one worker for each child process, and the total number of workers in CI should be 2 or 4. :)

Whether EXEC_TESTS_NODE_BIN is supported depends on whether setup-node caches compressed, which is a bit more complicated if they are compressed.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be no good way to get the path to other versions of setup-node.

Initially, I also didn't want to rely on a package manager, but unfortunately, tools like esvu don't provide NodeJS support.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we used n, which can be installed through npm?

@JLHwung JLHwung Sep 19, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be no good way to get the path to other versions of setup-node.

After we checked out the legacy node version via setup-node, could we write the result of which node to the github output? Then we can enable the latest node version and pass that output to the test step.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we used n, which can be installed through npm?

Unfortunately it doesn't support Windows.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really know what are we doing in this PR, but this comment seems talking about execute in different node version. Can this lib be useful https://github.com/ehmicky/nve? Just ignore me if it doesn't.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing! Thank you!
The same author's https://github.com/ehmicky/get-node seems to be what we need.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fyi Yarn just announced v6, which will also support switching Node.js version.

It will take a while to migrate however, because we have to rewrite our plugins.

https://yarn6.netlify.app/blog/2026-01-28-yarn-6-preview/

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yarn is great, but...
I can't run yarn install in Yarn v1, and can't run yarn run in Yarn v3.🤦‍♂️

yarnpkg/yarn#7940
yarnpkg/berry#6999

@liuxingbaoyu liuxingbaoyu force-pushed the exec-worker branch 3 times, most recently from 6095b2b to 3c40069 Compare September 19, 2025 16:07
@liuxingbaoyu

Copy link
Copy Markdown
Member Author

One issue I've noticed is that this PR contains breaking changes (using transform in tests is no longer supported, and runCodeInTestContext no longer includes Babel helpers).
I'm a bit concerned about people relying on this package.

@liuxingbaoyu liuxingbaoyu force-pushed the exec-worker branch 3 times, most recently from ea73f0c to 017fec7 Compare January 27, 2026 21:56
Comment thread .github/workflows/ci.yml
Comment on lines 192 to +195
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
name: babel-7
name: babel-8

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably do this.

Comment thread jest.config.ts
child_process.spawnSync(
`./node_modules/.bin/get-node ${process.env.EXEC_TESTS_NODE}`
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@liuxingbaoyu

Copy link
Copy Markdown
Member Author

#12728 (comment)
I've encountered this issue again.🤦‍♀️

@liuxingbaoyu liuxingbaoyu force-pushed the exec-worker branch 2 times, most recently from 505d00e to 55482db Compare May 26, 2026 12:05
@JLHwung JLHwung requested a review from Copilot May 26, 2026 13:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Babel’s test infrastructure to optionally run exec.js fixture tests in a separate Node.js process/version (via EXEC_TESTS_NODE), enabling compatibility testing with older Node releases while keeping the main Jest runtime on a modern Node.

Changes:

  • Add a worker-based execution path for fixture exec.js tests, with optional spawning via get-node when EXEC_TESTS_NODE is set.
  • Update/relocate a number of fixture exec tests into Jest suites and add new source map coverage tests.
  • Adjust build/CI configuration to bundle the new worker entrypoint and add a CI job that runs exec tests using Node v6.

Reviewed changes

Copilot reviewed 40 out of 42 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
yarn.lock Lockfile updates for newly introduced dependencies (e.g. get-node/get-node-cli, expect@24 alias, etc.).
scripts/pack-script.ts Expand Rollup node-resolve export conditions used during packing.
packages/babel-plugin-transform-regenerator/test/fixtures/regression/17425/output.js Update async rejection assertion form in fixture output.
packages/babel-plugin-transform-regenerator/test/fixtures/regression/17425/input.js Update async rejection assertion form in fixture input.
packages/babel-plugin-transform-regenerator/test/fixtures/regression/17425/exec.js Update async rejection assertion form in fixture exec.
packages/babel-plugin-transform-modules-commonjs/test/source-map.js Add Jest test asserting source map mappings are produced.
packages/babel-plugin-transform-modules-commonjs/test/fixtures/source-map/options.json Remove fixture options file (exec coverage migrated to Jest test).
packages/babel-plugin-transform-modules-commonjs/test/fixtures/source-map/exec.js Remove fixture exec file (coverage migrated to Jest test).
packages/babel-plugin-transform-block-scoping/test/index.js Add Jest tests that previously lived as exec fixtures (scope/bindings regressions).
packages/babel-plugin-transform-block-scoping/test/fixtures/general/issue-10339/exec.js Remove fixture exec (migrated to Jest test).
packages/babel-plugin-transform-block-scoping/test/fixtures/exec/scope-bindings.js Remove fixture exec (migrated to Jest test).
packages/babel-plugin-transform-async-generator-functions/test/fixtures/async-generators/await-in-finally/options.json Add minNodeVersion constraint to fixture options.
packages/babel-plugin-proposal-partial-application/test/fixtures/2018-07/member-expression-super/options.json Add fixture options including minNodeVersion.
packages/babel-plugin-proposal-partial-application/test/fixtures/2018-07/member-expression-private-name/options.json Add fixture options including minNodeVersion.
packages/babel-plugin-proposal-decorators/test/fixtures/legacy-object-properties/options.json Move targets.node: current to top-level targets (instead of nested plugin config).
packages/babel-plugin-proposal-decorators/test/fixtures/legacy-object-methods/options.json Same targets restructuring as above.
packages/babel-plugin-proposal-decorators/test/fixtures/legacy-class-static-properties/options.json Same targets restructuring as above.
packages/babel-plugin-proposal-decorators/test/fixtures/legacy-class-static-methods/options.json Same targets restructuring as above.
packages/babel-plugin-proposal-decorators/test/fixtures/legacy-class-prototype-properties/options.json Same targets restructuring as above.
packages/babel-plugin-proposal-decorators/test/fixtures/legacy-class-prototype-methods/options.json Same targets restructuring as above.
packages/babel-helpers/test/define-helper.skip-bundled.js Add dummy test to ensure Jest suite is non-empty when bundled tests are skipped.
packages/babel-helper-transform-fixture-test-runner/test/index.js Update tests to use the new exported APIs and shared context behavior.
packages/babel-helper-transform-fixture-test-runner/src/worker.cts Add CommonJS worker implementation used for executing exec tests in isolated context/process.
packages/babel-helper-transform-fixture-test-runner/src/process.ts Extract/house process-based test runner utilities (previously embedded).
packages/babel-helper-transform-fixture-test-runner/src/index.ts Switch exec execution to the new worker-backed runner; re-export worker/process helpers.
packages/babel-helper-transform-fixture-test-runner/src/exec.ts Add logic to run exec tests either in-process or via spawned Node worker (EXEC_TESTS_NODE).
packages/babel-helper-transform-fixture-test-runner/package.json Add deps needed by the worker path (expect@24 alias, get-node, lru-cache v5 types).
packages/babel-helper-fixtures/src/index.ts Make fixture minNodeVersion logic consider the configured exec-test node version too.
packages/babel-helper-compilation-targets/package.json Remove unused devDependencies.
packages/babel-core/test/plugins.js Migrate various fixture exec tests into explicit Jest tests.
packages/babel-core/test/fixtures/plugins/transform-error/options.json Remove fixture options file (exec migrated to Jest test).
packages/babel-core/test/fixtures/plugins/transform-error/exec.js Remove fixture exec file (migrated to Jest test).
packages/babel-core/test/fixtures/plugins/regression-2772/exec.js Remove fixture exec file (migrated to Jest test).
packages/babel-core/test/fixtures/plugins/nested-if-alternate/exec.js Remove fixture exec file (migrated to Jest test).
packages/babel-core/test/fixtures/plugins/multiple-definition-evaluation/exec.js Remove fixture exec file (migrated to Jest test).
packages/babel-core/test/fixtures/plugins/inference-recursion/exec.js Remove fixture exec file (migrated to Jest test).
packages/babel-core/test/fixtures/plugins/build-code-frame-error/exec.js Remove fixture exec file (migrated to Jest test).
package.json Add get-node-cli to support prefetching node versions in test setup.
lib/globals.d.ts Update environment variable typing for breaking-change toggle.
jest.config.ts Prefetch requested Node version when EXEC_TESTS_NODE is set.
Gulpfile.ts Bundle/build support for the new .cts worker entrypoint and adjust CommonJS bundling settings.
.github/workflows/ci.yml Rename codecov upload label and add a job to run exec tests using Node v6.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/babel-helper-transform-fixture-test-runner/src/exec.ts Outdated
Comment thread packages/babel-helper-transform-fixture-test-runner/src/worker.cts Outdated
Comment thread packages/babel-helper-transform-fixture-test-runner/src/exec.ts
Comment thread packages/babel-helper-transform-fixture-test-runner/src/exec.ts Outdated
Comment thread jest.config.ts
@liuxingbaoyu

liuxingbaoyu commented May 28, 2026

Copy link
Copy Markdown
Member Author

The suggestions provided by copilot were very helpful, and I refactored and fixed it.

Comment thread Gulpfile.ts Outdated
include: [
"packages/babel-helper-transform-fixture-test-runner/src/*.cts",
],
}),

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we shouldn't bundle it?
The output is also terrible, including files containing regenerate.
Image

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, importing CJS in ESM is cumbersome, so let's stop bundling it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bundled lib/index.js on the current main (I am aware that worker.cts is split from index.js in this PR) looks good to me. So this is a new thing specifically in this PR. Could you investigate why regenerate was imported here? Does the new source contain any regexp features that are not widely supported? Or is our build config too conservative on the node.js targets?

@liuxingbaoyu liuxingbaoyu May 28, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

babel/Gulpfile.ts

Lines 473 to 485 in 2c05534

dynamicRequireTargets: [
// https://github.com/mathiasbynens/regexpu-core/blob/ffd8fff2e31f4597f6fdfee75d5ac1c5c8111ec3/rewrite-pattern.js#L48
path
.relative(
monorepoRoot,
resolveChain(
import.meta.url,
"./packages/babel-helper-create-regexp-features-plugin",
"regexpu-core",
"regenerate-unicode-properties"
)
)
.replace(/\\/g, "/") + "/**/*.js", // Must be posix path in rollup 3

Because I used dynamic reqiure before, this issue no longer exists.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I thought this one should only be applied to the standalone build task. I am surprised to hear that it will affect the helper-transform-fixture-test-runner as well.

import vm = require("vm");
import LruCache = require("lru-cache");
import path = require("path");
import fs = require("fs");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

node: prefix should be required here, maybe we should check the linter config.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We did not include .cts in our configuration. :)

@liuxingbaoyu liuxingbaoyu force-pushed the exec-worker branch 2 times, most recently from 82b3b30 to fd7110c Compare June 23, 2026 08:29
@liuxingbaoyu liuxingbaoyu requested a review from JLHwung June 24, 2026 00:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants