Skip to content

feat(semantic): add enum member value evaluation for const enum support#20602

Merged
graphite-app[bot] merged 1 commit intomainfrom
feat/const-enum-semantic
Apr 7, 2026
Merged

feat(semantic): add enum member value evaluation for const enum support#20602
graphite-app[bot] merged 1 commit intomainfrom
feat/const-enum-semantic

Conversation

@Dunqing
Copy link
Copy Markdown
Member

@Dunqing Dunqing commented Mar 21, 2026

Summary

Part of #6073 and #11844

  • Add ConstantValue type in oxc_syntax for representing enum member values (number/string)
  • Implement enum member value evaluation in oxc_semantic supporting numeric auto-increment, string values, binary/unary expressions, cross-member and cross-enum references, template literals, and merged enum declarations
  • Store evaluated enum member values in Scoping via EnumData struct with getter/setter APIs and enum body scope tracking
  • All enum evaluation code is gated behind the enum_eval Cargo feature (enabled by oxc_transformer)

Feature gate

The enum_eval feature controls:

  • ts_enum module (evaluator + data types)
  • EnumData field and enum-related methods on Scoping
  • oxc_syntax/to_js_string dependency

Consumers that don't need enum values (linter, language server) pay zero cost.

Babel alignment

Unary operators on strings follow Babel's JS-coercion semantics (+"s""s", -"s"NaN, ~"s"-1), which differs from TypeScript (unevaluated). This is documented in the source.

Test plan

  • Integration tests in crates/oxc_semantic/tests/integration/enum_values.rs
  • Semantic TypeScript conformance snapshot updated
  • cargo check -p oxc_semantic passes (without feature)
  • cargo check -p oxc_semantic --features enum_eval passes (with feature)
  • cargo check -p oxc_transformer passes (enables feature transitively)

Copy link
Copy Markdown
Member Author

Dunqing commented Mar 21, 2026


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions github-actions Bot added A-semantic Area - Semantic C-enhancement Category - New feature or request labels Mar 21, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Mar 21, 2026

Merging this PR will not alter performance

✅ 48 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing feat/const-enum-semantic (edbaf84) with main (3cfe8ed)2

Open in CodSpeed

Footnotes

  1. 3 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 (5f6ce21) during the generation of this report, so 3cfe8ed was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@Dunqing Dunqing force-pushed the feat/const-enum-semantic branch 6 times, most recently from d2f596a to 0d3cb2e Compare March 23, 2026 07:17
@Dunqing Dunqing marked this pull request as ready for review March 23, 2026 07:32
@Dunqing Dunqing requested a review from Boshen March 23, 2026 07:35
@Dunqing Dunqing force-pushed the feat/const-enum-semantic branch from 0d3cb2e to 5a62fdc Compare April 3, 2026 01:00
Copy link
Copy Markdown
Member

@Boshen Boshen left a comment

Choose a reason for hiding this comment

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

This should be a runtime flag instead of compile time feature flag.

@graphite-app graphite-app Bot added the 0-merge Merge with Graphite Merge Queue label Apr 7, 2026
@graphite-app
Copy link
Copy Markdown
Contributor

graphite-app Bot commented Apr 7, 2026

Merge activity

…rt (#20602)

## Summary

Part of #6073 and #11844

- Add `ConstantValue` type in `oxc_syntax` for representing enum member values (number/string)
- Implement enum member value evaluation in `oxc_semantic` supporting numeric auto-increment, string values, binary/unary expressions, cross-member and cross-enum references, template literals, and merged enum declarations
- Store evaluated enum member values in `Scoping` via `EnumData` struct with getter/setter APIs and enum body scope tracking
- All enum evaluation code is gated behind the `enum_eval` Cargo feature (enabled by `oxc_transformer`)

### Feature gate

The `enum_eval` feature controls:
- `ts_enum` module (evaluator + data types)
- `EnumData` field and enum-related methods on `Scoping`
- `oxc_syntax/to_js_string` dependency

Consumers that don't need enum values (linter, language server) pay zero cost.

### Babel alignment

Unary operators on strings follow Babel's JS-coercion semantics (`+"s"` → `"s"`, `-"s"` → `NaN`, `~"s"` → `-1`), which differs from TypeScript (unevaluated). This is documented in the source.

## Test plan

- [x] Integration tests in `crates/oxc_semantic/tests/integration/enum_values.rs`
- [x] Semantic TypeScript conformance snapshot updated
- [x] `cargo check -p oxc_semantic` passes (without feature)
- [x] `cargo check -p oxc_semantic --features enum_eval` passes (with feature)
- [x] `cargo check -p oxc_transformer` passes (enables feature transitively)
@graphite-app graphite-app Bot force-pushed the feat/const-enum-semantic branch from edbaf84 to 75663c0 Compare April 7, 2026 08:52
@graphite-app graphite-app Bot merged commit 75663c0 into main Apr 7, 2026
25 of 26 checks passed
@graphite-app graphite-app Bot deleted the feat/const-enum-semantic branch April 7, 2026 08:56
@graphite-app graphite-app Bot removed the 0-merge Merge with Graphite Merge Queue label Apr 7, 2026
graphite-app Bot pushed a commit that referenced this pull request Apr 13, 2026
…ration removal (#20508)

## Summary

Depends on #20602.

Closes: #6073
Closes: #11844

- Inline const enum member accesses (`Foo.Bar` / `Foo["Bar"]`) to literal values when `optimize_const_enums` is enabled
- Remove non-exported const enum declarations when all members are evaluable
- Use `exit_statements` for enum removal so inlining happens before removal
- Delete references when inlining enum member accesses for correct semantic data
- Handle `IdentifierReferenceRename` for sibling enum member references in merged declarations

## Test plan

- [x] Transform conformance tests pass (`cargo run -p oxc_transform_conformance`)
- [x] `cargo test -p oxc_transformer` passes
- [x] Babel conformance snapshot updated
camc314 pushed a commit that referenced this pull request Apr 13, 2026
### 💥 BREAKING CHANGES

- 36cdc31 str: [**BREAKING**] Remove identity `FromIn` impl for `Ident`
(#21251) (overlookmotel)
- 382958a span: [**BREAKING**] Remove re-exports of string types from
`oxc_span` crate (#21246) (overlookmotel)
- c4aedfa str: [**BREAKING**] Add `static_ident!` macro (#21245)
(overlookmotel)

### 🚀 Features

- e7e1aea transformer/typescript: Add `optimize_enums` option for
regular enum inlining (#20539) (Dunqing)
- 679f57f transformer/typescript: Implement const enum inlining and
declaration removal (#20508) (Dunqing)
- 6dd061c semantic: Extend `MemberWriteTarget` to cover all property
modification patterns (#21205) (Dunqing)
- f134e24 minifier: Support `property_write_side_effects` option to drop
unused property assignments (#20773) (Dunqing)
- 75663c0 semantic: Add enum member value evaluation for const enum
support (#20602) (Dunqing)
- 3cfe8ed semantic: Add `MemberWriteTarget` flag to `ReferenceFlags`
(#20772) (Dunqing)

### 🐛 Bug Fixes

- af1a586 transformer/class-properties: Use correct property name when
converting parameter properties (#21268) (Amal Jossy)
- b43250a allocator: Move allocation tracking into `Bump` (#21342)
(overlookmotel)
- 36f505f allocator: `StringBuilder` use `Allocator::alloc_layout`
(#21340) (overlookmotel)
- 7a08a6f allocator: Fix allocation counting in
`Allocator::alloc_concat_strs_array` (#21336) (overlookmotel)
- 2338e28 ecmascript: Treat `this` as potentially having side effects
(#21297) (sapphi-red)
- bd8bd39 allocator: Remove unsafe hacks from `from_raw_parts` methods
(#21283) (overlookmotel)
- 8f4c340 allocator: Remove dangerous pointer const to mut cast (#21279)
(overlookmotel)
- aa9259f parser: Add missing error code for optional param diagnostic
(#21258) (camc314)
- 04b3c2f str: Fix unsound casting const pointers to mut pointers
(#21242) (overlookmotel)
- ceadf6c str: Make `Ident::from_raw` an unsafe function (#21241)
(overlookmotel)
- eab13b3 transformer/decorators: Avoid accessor storage name collisions
(#21106) (Dunqing)
- 07e8a30 transformer/react-refresh: Handle parenthesized variable
initializers (#21047) (camc314)

### ⚡ Performance

- c3ca6f6 allocator: `StringBuilder::from_strs_array_in` check for 0
length earlier (#21338) (overlookmotel)
- c2422bb allocator: `Allocator::alloc_concat_strs_array` check for 0
length earlier (#21337) (overlookmotel)
- 04b0fdc allocator: Mark `Allocator::alloc_layout` as
`#[inline(always)]` (#21335) (overlookmotel)
- 17aee9e allocator: Use `offset_from_unsigned` in
`ChunkFooter::as_raw_parts` (#21280) (overlookmotel)
- 61adedd minifier: Fix O(n²) perf on very many var decls (#21062)
(Gunnlaugur Thor Briem)
- addcd02 napi/parser, linter/plugins: Raw transfer deserializer for
`Vec`s use shift instead of multiply where possible (#21142)
(overlookmotel)
- 3068ded napi/parser, linter/plugins: Shift before add when calculating
positions in raw transfer deserializer (#21141) (overlookmotel)
- eb400b8 napi/parser, linter/plugins: Remove `uint32` buffer view
(#21140) (overlookmotel)
- 2675085 napi/parser: Lazy deserialization use only `Int32Array`
(#21139) (overlookmotel)
- 5b35a53 napi/parser: Deserializing tokens use only `int32` array
(#21138) (overlookmotel)
- f163d10 parser: Tokens raw deserialization use `Int32Array` (#21137)
(overlookmotel)
- 7a86613 linter/plugins: Use `Int32Array`s for tokens and comments
buffers (#21136) (overlookmotel)
- 8c51121 napi/parser, linter/plugins: Raw transfer deserialize `Span`
fields as `i32`s (#21135) (overlookmotel)
- bc1bcdd napi/parser, linter/plugins: Inline trivial raw transfer field
deserializers into node object definitions (#21134) (overlookmotel)
- c0278ab napi/parser, linter/plugins: Use `Int32Array` in raw transfer
deserializer (#21132) (overlookmotel)
- 43482c7 linter/plugins: Use `>>` not `>>>` in binary search loops
(#21129) (overlookmotel)

### 📚 Documentation

- f5e1845 allocator: Upgrade headers in doc comments for `Bump` (#21263)
(overlookmotel)
- 2870174 allocator: Upper case `SAFETY` in comments (#21253)
(overlookmotel)
- 01bc269 str: Reformat `Ident` doc comments (#21240) (overlookmotel)
- dd47359 allocator: Add doc comments for panics and errors (#21230)
(overlookmotel)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-semantic Area - Semantic C-enhancement Category - New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants