Skip to content

Conversation

@liuxingbaoyu
Copy link
Member

@liuxingbaoyu liuxingbaoyu commented Jan 29, 2026

Q                       A
Fixed Issues? Closes #16871
Patch: Bug Fix?
Major: Breaking Change?
Minor: New Feature?
Tests Added + Pass? Yes
Documentation PR Link babel/website#3160
Any Dependency Changes?
License MIT

@babel-bot
Copy link
Collaborator

babel-bot commented Jan 29, 2026

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

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 29, 2026

Open in StackBlitz

commit: 007f7bd

Copy link
Member

@nicolo-ribaudo nicolo-ribaudo left a comment

Choose a reason for hiding this comment

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

Nice

Copy link
Contributor

@JLHwung JLHwung left a comment

Choose a reason for hiding this comment

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

This PR also removes the experimental worker. As far as I know, one thing that blocks the removal of experimental worker is that require(esm) does not support top level await but the worker implementation does support such usage. Is this issue resolved?

OK, it seems that this PR merges experimental-worker with the index. It should be documented in the migration notes then.

@liuxingbaoyu
Copy link
Member Author

require(esm) still doesn't support top-level await, but this usage doesn't seem to exist in our worker.

@JLHwung
Copy link
Contributor

JLHwung commented Jan 29, 2026

require(esm) still doesn't support top-level await, but this usage doesn't seem to exist in our worker.

Users can use top level await in babel.config.mjs, since the eslint-parser could be required from eslint.config, maybe we should add a test case about this scenario.

@JLHwung JLHwung added PR: Breaking Change 💥 A type of pull request used for our changelog categories for next major release PR: Needs Docs labels Jan 29, 2026
@liuxingbaoyu
Copy link
Member Author

liuxingbaoyu commented Jan 29, 2026

By the way, ESLint v10 is about to be released as a stable version. Do we plan to drop ESLint v8?

@nicolo-ribaudo
Copy link
Member

Technically without the worker we don't support top-level await, but I suspect that that's fine. The motivation for the worker was originally to use ESM, I expect that top-level await in Babel configs is very rare and can be replaced with sync operations (since probably the only common I/O might be to read some config file somewhere).

@liuxingbaoyu
Copy link
Member Author

It may be a bit late to drop asynchronous support now, because our core has supported asynchronous operations for a long time, many plugins have already used asynchronous operations, and some third-party packages only provide asynchronous operations.

I will investigate how much time it takes us to execute the entire configuration file in order to obtain the parser options.

Comment on lines +41 to +60
if (
options.babelOptions.babelrc === false &&
options.babelOptions.configFile === false
) {
const parserOpts = {
sourceType: options.sourceType,
sourceFilename: options.filePath,
...(options.sourceType !== "commonjs"
? {
allowReturnOutsideFunction:
options.ecmaFeatures?.globalReturn ?? false,
}
: {}),
...options.babelOptions.parserOpts,
plugins: getParserPlugins(options.babelOptions),
// skip comment attaching for parsing performance
attachComment: false,
ranges: true,
tokens: true,
};
Copy link
Member Author

Choose a reason for hiding this comment

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

The cost of worker threads is low, but I still added a fast path.

Copy link
Member

@nicolo-ribaudo nicolo-ribaudo left a comment

Choose a reason for hiding this comment

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

I think this PR is fine, but if the default performance is worse we might want in the future to add a useSameThread: true option to opt-out from the worker and use sync Babel APIs.

@liuxingbaoyu
Copy link
Member Author

Users can do this with the fast path now. :)

@nicolo-ribaudo
Copy link
Member

nicolo-ribaudo commented Jan 30, 2026

I mean for when they still have a config, since in most cases everything will be fully sync anyway. Or we should at least document that if you have configFile: false then it will run in the same thread.

@liuxingbaoyu
Copy link
Member Author

It seems most users only need to provide a list of parser plugins.
They can be configured using configFile: false + parserOpts: {}.

By the way, I remember we used to want to disable the babelrc search by default in Babel 8.
Because it significantly impacts performance.

@JLHwung
Copy link
Contributor

JLHwung commented Jan 30, 2026

The motivation for the worker was originally to use ESM, I expect that top-level await in Babel configs is very rare and can be replaced with sync operations (since probably the only common I/O might be to read some config file somewhere).

Before require(esm) is implemented, the top level await scenario I can think of is that users might migrate old config from

{
  plugins: [
    require("@babel/plugin-transform-class-properties")
  ]
}

to

{
  plugins: [
    await import("@babel/plugin-transform-class-properties")
  ]
}

because it is easier to find-and-replace and users don't have to name every plugins again in static import. Now that require(esm) is there, they can probably stay with require so top level await should be rare for Babel 8 users.

@nicolo-ribaudo
Copy link
Member

It seems most users only need to provide a list of parser plugins. They can be configured using configFile: false + parserOpts: {}.

Yes, but that requires duplicating your syntax configuration across your Babel config ans ESLint config.

I just tested the performance of using vs not using the worker in our repository (by commenting out the @typescript-eslint usage since it would dominate the linting time, and using Babel to parse everything), and there is zero difference. I am not worried anymore about this PR.

@nicolo-ribaudo
Copy link
Member

To recap, since a couple of things changes since @JLHwung's approval:

  • we still support TLA and export default async function in configs
  • we will now always use the worker
  • the entry point is now @babel/eslint-parser, and @babel/eslint-parser/experimental-worker is gone
  • the worker does not have a noticeable performance overhead

This was referenced Feb 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: eslint PR: Breaking Change 💥 A type of pull request used for our changelog categories for next major release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants