Sitelet https://github.com/babel/babel/pull/18106
Skip to content

perf: Remove the use of NodePath#contexts - #18106

Open
liuxingbaoyu wants to merge 1 commit into
babel:mainfrom
liuxingbaoyu:perf-traverse-context
Open

liuxingbaoyu wants to merge 1 commit into
babel:mainfrom
liuxingbaoyu:perf-traverse-context

Conversation

@liuxingbaoyu

@liuxingbaoyu liuxingbaoyu commented Jun 28, 2026 •

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 a breaking change.
I hope to postpone it until Babel 9.
Fortunately, none of our plugins were affected.
Only one test that supported babel-plugin-jest-hoist's edge behavior was impacted.
This resulted in an overall transformation and traversing time reduction of ~20%.

PS F:\babel> node .\benchmark\all\real-case-ts-mjs.mjs
Recommend running with --expose-gc.
all/real-case-ts-mjs.mjs babel-parser-express.ts @ current: 70.6 ops/sec ±3.29% 336 runs (15ms)
all/real-case-ts-mjs.mjs babel-parser-express.ts @ baseline: 56.45 ops/sec ±2.96% 274 runs (18ms)
all/real-case-ts-mjs.mjs ts-parser.ts @ current: 13.09 ops/sec ±2.93% 65 runs (77ms)
all/real-case-ts-mjs.mjs ts-parser.ts @ baseline: 11.32 ops/sec ±2.44% 64 runs (89ms)
PS F:\babel> node .\benchmark\babel-traverse\real-case.mjs          
Recommend running with --expose-gc.
babel-traverse/real-case.mjs babel-parser-express.ts @ current: 174 ops/sec ±2.24% 804 runs (6.219ms)
babel-traverse/real-case.mjs babel-parser-express.ts @ baseline: 139 ops/sec ±2.64% 629 runs (7.953ms)
babel-traverse/real-case.mjs jquery-3.6.js @ current: 43.97 ops/sec ±1.33% 219 runs (23ms)
babel-traverse/real-case.mjs jquery-3.6.js @ baseline: 36.64 ops/sec ±1.61% 182 runs (28ms)
babel-traverse/real-case.mjs ts-checker.mjs @ current: 5.89 ops/sec ±1.27% 64 runs (170ms)
babel-traverse/real-case.mjs ts-checker.mjs @ baseline: 5.03 ops/sec ±1.67% 64 runs (200ms)
babel-traverse/real-case.mjs ts-parser.mjs @ current: 40.48 ops/sec ±1.95% 200 runs (25ms)
babel-traverse/real-case.mjs ts-parser.mjs @ baseline: 33.6 ops/sec ±1.92% 166 runs (30ms)
babel-traverse/real-case.mjs ts-parser.ts @ current: 31.63 ops/sec ±1.53% 157 runs (32ms)
babel-traverse/real-case.mjs ts-parser.ts @ baseline: 25.49 ops/sec ±1.95% 127 runs (40ms)
babel-traverse/real-case.mjs typescript-5.6.2.js @ current: 1.45 ops/sec ±0.74% 64 runs (691ms)
babel-traverse/real-case.mjs typescript-5.6.2.js @ baseline: 1.21 ops/sec ±1.47% 64 runs (829ms)

traverse with noScope: true: 30%-40%

PS F:\babel> node .\benchmark\babel-traverse\real-case.mjs
Recommend running with --expose-gc.
babel-traverse/real-case.mjs babel-parser-express.ts @ current: 470 ops/sec ±0.64% 2308 runs (2.167ms)
babel-traverse/real-case.mjs babel-parser-express.ts @ baseline: 313 ops/sec ±2.2% 1389 runs (3.601ms)
babel-traverse/real-case.mjs jquery-3.6.js @ current: 135 ops/sec ±0.99% 663 runs (7.55ms)
babel-traverse/real-case.mjs jquery-3.6.js @ baseline: 90.28 ops/sec ±1.76% 443 runs (11ms)
babel-traverse/real-case.mjs ts-checker.mjs @ current: 15.54 ops/sec ±2.87% 77 runs (65ms)
babel-traverse/real-case.mjs ts-checker.mjs @ baseline: 11.21 ops/sec ±4.12% 64 runs (91ms)
babel-traverse/real-case.mjs ts-parser.mjs @ current: 125 ops/sec ±0.91% 618 runs (8.094ms)
babel-traverse/real-case.mjs ts-parser.mjs @ baseline: 90.59 ops/sec ±2.05% 442 runs (11ms)
babel-traverse/real-case.mjs ts-parser.ts @ current: 82.34 ops/sec ±0.43% 411 runs (12ms)
babel-traverse/real-case.mjs ts-parser.ts @ baseline: 56.12 ops/sec ±2.41% 273 runs (18ms)
babel-traverse/real-case.mjs typescript-5.6.2.js @ current: 3.94 ops/sec ±1.87% 64 runs (255ms)
babel-traverse/real-case.mjs typescript-5.6.2.js @ baseline: 2.7 ops/sec ±2.82% 64 runs (375ms)

@babel-bot

Copy link
Copy Markdown
Collaborator

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ae02ce6797

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


path._traverseFlags = 0;

if (context && !path.context) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Refresh cached paths for the active traversal

When a cached child NodePath already has any context, this guard skips updating its state/opts for the context passed by the current path.get(...) call. Cached paths survive across traversals, so a plugin that fetched a child in an earlier pass can later get the same child under different state/options (for example after a noScope pass) and observe stale path.state or have setScope run with stale opts, leaving scope unset in a scoped traversal. Please refresh the path for the supplied context even when it already has a context.

Useful? React with 👍 / 👎.

@pkg-pr-new

pkg-pr-new Bot commented Jun 28, 2026

Copy link
Copy Markdown

Open in StackBlitz

commit: ae02ce6

@nicolo-ribaudo

Copy link
Copy Markdown
Member

Does this replace #12634? :)

@liuxingbaoyu

Copy link
Copy Markdown
Member Author

#12634 was originally intended to fix #12631.
#12631 was subsequently fixed in #13813 and #16965.

This PR and #12634 seem to be two different approaches and shouldn't work together.

Technically, I don't think this PR completely avoids the context overriding issue.
However, it avoids the asymmetric pushContext and popContext.

Unfortunately, the PR's baseline was also affected by the outdated baseline.
The actual overall transformation time was reduced by 7%-12%.

PS F:\babel> node .\benchmark\all\real-case-ts-mjs.mjs    
Recommend running with --expose-gc.
all/real-case-ts-mjs.mjs babel-parser-express.ts @ current: 73.9 ops/sec ±2.93% 355 runs (14ms)
all/real-case-ts-mjs.mjs babel-parser-express.ts @ baseline: 68.92 ops/sec ±2.62% 333 runs (15ms)
all/real-case-ts-mjs.mjs ts-parser.ts @ current: 13.43 ops/sec ±3.21% 67 runs (75ms)
all/real-case-ts-mjs.mjs ts-parser.ts @ baseline: 12.84 ops/sec ±2.84% 64 runs (79ms)
PS F:\babel> node .\benchmark\all\real-case-mjs-cjs.mjs   
Recommend running with --expose-gc.
all/real-case-mjs-cjs.mjs ts-checker.mjs @ current: 1.74 ops/sec ±1.14% 64 runs (577ms)
all/real-case-mjs-cjs.mjs ts-checker.mjs @ baseline: 1.55 ops/sec ±1.79% 64 runs (647ms)
all/real-case-mjs-cjs.mjs ts-parser.mjs @ current: 13.42 ops/sec ±1.96% 67 runs (75ms)
all/real-case-mjs-cjs.mjs ts-parser.mjs @ baseline: 11.86 ops/sec ±3.56% 64 runs (85ms)

This branch has not been deployed

No deployments
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.

3 participants