Skip to content

refactor(es/ast)!: split bodyless functions - #12119

Open
magic-akari wants to merge 1 commit into
mainfrom
refactor/ast-split-bodyless-functions
Open

refactor(es/ast)!: split bodyless functions#12119
magic-akari wants to merge 1 commit into
mainfrom
refactor/ast-split-bodyless-functions

Conversation

@magic-akari

@magic-akari magic-akari commented Aug 14, 2026

Copy link
Copy Markdown
Member

Summary

This PR makes the required-body invariant explicit in the SWC ECMAScript AST.

Function now only represents JavaScript function declarations, expressions, and methods with an implementation body. Bodyless TypeScript and Flow declarations, overload signatures, abstract methods, and ambient methods use TsFunction, wrapped by TsFnDecl for declarations and TsMethod for class members.

The parser selects the node kind based on whether an implementation body was parsed. Code generation, traversal, semantic analysis, transforms, bindings, and ESTree compatibility have been updated accordingly.

Motivation

A function-like declaration without a body is not a JavaScript function implementation. It is a TypeScript or Flow declaration, overload signature, abstract method, or ambient method.

Previously, Function combined runtime function implementations with declaration-only signatures through body: Option<FunctionBody>. This allowed combinations that are not semantically meaningful and required every consumer of an implementation-bearing function to handle the bodyless case.

With this change, transforms and minifiers operating on Function can access its body directly without repeated Some / None checks. Declaration-only signatures are represented structurally and are less likely to enter runtime processing accidentally.

The split also makes class semantics structural: ClassMethod and PrivateMethod represent implementations, while TsMethod represents a bodyless signature. Keeping TsFunction nested under TsMethod preserves the function-scope boundary between decorators or computed keys and method parameters.

Additional Fix

The legacy lexer now stops iteration when the remaining input is empty instead of relying on source-map position metadata. This prevents zero-length errors at EOF, such as an unterminated string error, from being yielded indefinitely.

BREAKING CHANGE:

  • Function.body changes from Option<FunctionBody> to FunctionBody.
  • TsFunction, TsFnDecl, and TsMethod are introduced for bodyless TypeScript and Flow function-like syntax.
  • Bodyless declarations may appear as Decl::TsFn or DefaultDecl::TsFn.
  • Bodyless class methods may appear as ClassMember::TsMethod.
  • Serialized AST output for bodyless declarations and methods now uses TsDeclareFunction and TsMethodDefinition.
  • Downstream exhaustive matches, visitors, AST builders, and serialized AST consumers must handle the new variants.

Related issue (if exists):

@changeset-bot

changeset-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 698a192

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codspeed-hq

codspeed-hq Bot commented Aug 14, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 4.36%

❌ 1 regressed benchmark
✅ 199 untouched benchmarks
⏩ 61 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation typescript/fast-strip/graphile-config 1.2 ms 1.3 ms -4.36%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing refactor/ast-split-bodyless-functions (698a192) with main (394c7c9)2

Open in CodSpeed

Footnotes

  1. 61 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (d7d7434) during the generation of this report, so 394c7c9 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@magic-akari
magic-akari force-pushed the refactor/ast-split-bodyless-functions branch 3 times, most recently from 5931283 to b1547b7 Compare August 14, 2026 16:31
@magic-akari
magic-akari marked this pull request as ready for review August 14, 2026 18:33
@magic-akari
magic-akari requested review from a team as code owners August 14, 2026 18:33

@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: b1547b7892

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread crates/swc_ecma_ast/src/decl.rs
@magic-akari
magic-akari force-pushed the refactor/ast-split-bodyless-functions branch from b1547b7 to 6d3788b Compare August 15, 2026 02:30

@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: 6d3788b379

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread crates/swc_ecma_parser/src/parser/class_and_fn.rs
Comment thread crates/swc_ecma_parser/src/parser/class_and_fn.rs
Comment thread crates/swc_ecma_ast/src/decl.rs
Comment thread crates/swc_estree_compat/src/swcify/stmt.rs
Comment thread crates/swc_ecma_transforms_typescript/src/retain.rs
@magic-akari
magic-akari force-pushed the refactor/ast-split-bodyless-functions branch from 6d3788b to b21ffad Compare August 15, 2026 04:26

@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: b21ffad28d

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread crates/swc_ecma_lexer/src/common/parser/output_type.rs
Comment thread crates/swc_estree_compat/src/swcify/class.rs Outdated
Comment thread crates/swc_ecma_transforms_base/src/rename/analyer_and_collector.rs Outdated
Comment thread crates/swc_ecma_utils/src/lib.rs
@magic-akari
magic-akari force-pushed the refactor/ast-split-bodyless-functions branch from b21ffad to 767005a Compare August 15, 2026 04:58

@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: 767005a504

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread crates/swc_ecma_ast/src/decl.rs
Comment thread crates/swc_ecma_ast/src/class.rs
Comment thread crates/swc_ecma_parser/src/parser/class_and_fn.rs
@magic-akari
magic-akari force-pushed the refactor/ast-split-bodyless-functions branch 2 times, most recently from cd903b6 to 9b1b646 Compare August 15, 2026 06:12

@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: 9b1b646f3a

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread crates/swc_bundler/src/bundler/export.rs
Comment thread crates/swc_ecma_parser/src/parser/class_and_fn.rs
@magic-akari
magic-akari force-pushed the refactor/ast-split-bodyless-functions branch from 9b1b646 to f913be6 Compare August 15, 2026 07:01

@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: f913be666d

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread crates/swc_ecma_transforms_base/src/rename/analyer_and_collector.rs
Comment thread crates/swc_ecma_ast/src/function.rs
Comment thread crates/swc_estree_compat/src/swcify/class.rs Outdated
Comment thread crates/swc_ecma_react_compiler/src/convert_ast.rs Outdated
Represent functions with bodies separately from TypeScript declarations and methods that omit bodies.

Also stop legacy lexer iteration at exhausted input so zero-length EOF errors cannot repeat indefinitely.

Closes #12103.
@magic-akari
magic-akari force-pushed the refactor/ast-split-bodyless-functions branch from f913be6 to 698a192 Compare August 15, 2026 07:38
@Austaras

Copy link
Copy Markdown
Member

I don't really see the benefit of this change.

@magic-akari

Copy link
Copy Markdown
Member Author

I don't really see the benefit of this change.

I've updated the PR description to clarify the motivation and breaking changes.

The main benefit is making the implementation-body invariant structural: Function always represents a JavaScript function or method with an implementation body, while bodyless TypeScript and Flow declarations and overload signatures use TsFunction.

This keeps declaration-only nodes out of runtime transforms and removes repeated Option handling from consumers of Function. More importantly, it establishes the structural boundary we need and will serve as a bridge to our next step.

@Austaras

Copy link
Copy Markdown
Member

Most of the passed that works after typescript doesn't need to deal with ts nodes so it would be a brainless unwrap while those few passes needed to deal with typescript would need duplicate method for simliar ast nodes.

Also even under the intention of this PR, Constructor should be splitted too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Unterminated template literals cause endless lexer loop

2 participants