Skip to content

Commit 62376dd

Browse files
committed
fix(transformer): inline const enum members through type-cast wrappers
Wrapping a const enum access in `as T`, `satisfies T`, `!`, or `<T>` prevented `optimizeConstEnums` from inlining it: the inliner's `enter_expression` only matched bare `StaticMemberExpression` / `ComputedMemberExpression`, while `annotations.rs` stripped the TS wrapper after this hook returned — by which point the outer node had been replaced and `enter_expression` was never re-invoked on it. Peek through wrappers via `get_inner_expression_mut()` so the inner member access is inlined; the outer replacement then drops the wrapper along with the value. Closes #22444
1 parent c9f506e commit 62376dd

7 files changed

Lines changed: 88 additions & 3 deletions

File tree

crates/oxc_transformer/src/typescript/enum.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ impl<'a> Traverse<'a, TransformState<'a>> for TypeScriptEnum {
102102
return;
103103
}
104104

105-
let inlined = match expr {
105+
// Peek through TS-only wrappers and parens so `E.X as T`, `E.X satisfies T`,
106+
// `E.X!`, `<T>E.X`, `E.X` (with `preserveParens`) all inline. `annotations.rs`
107+
// strips these wrappers, but only after this hook returns — by then the outer
108+
// node has been replaced and `enter_expression` is not re-invoked on it.
109+
let inlined = match expr.get_inner_expression_mut() {
106110
Expression::StaticMemberExpression(member_expr) => {
107111
self.try_inline_enum_member(member_expr, ctx)
108112
}

tasks/transform_conformance/snapshots/oxc.snap.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
commit: 4079bcda
22

3-
Passed: 235/382
3+
Passed: 236/384
44

55
# All Passed:
66
* babel-plugin-transform-class-static-block
@@ -63,7 +63,7 @@ after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(6), R
6363
rebuilt : SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(6), ReferenceId(10)]
6464

6565

66-
# babel-plugin-transform-typescript (22/56)
66+
# babel-plugin-transform-typescript (23/58)
6767
* allow-declare-fields-false/input.ts
6868
Unresolved references mismatch:
6969
after transform: ["dce"]
@@ -526,6 +526,20 @@ Symbol flags mismatch for "B":
526526
after transform: SymbolId(2): SymbolFlags(RegularEnum)
527527
rebuilt : SymbolId(2): SymbolFlags(FunctionScopedVariable)
528528

529+
* optimize-enums/type-cast/input.ts
530+
Bindings mismatch:
531+
after transform: ScopeId(1): ["Direction", "Down", "Up"]
532+
rebuilt : ScopeId(1): ["Direction"]
533+
Scope flags mismatch:
534+
after transform: ScopeId(1): ScopeFlags(0x0)
535+
rebuilt : ScopeId(1): ScopeFlags(Function)
536+
Symbol flags mismatch for "Direction":
537+
after transform: SymbolId(0): SymbolFlags(RegularEnum)
538+
rebuilt : SymbolId(0): SymbolFlags(FunctionScopedVariable)
539+
Symbol reference IDs mismatch for "Direction":
540+
after transform: SymbolId(0): [ReferenceId(5), ReferenceId(1), ReferenceId(7), ReferenceId(3), ReferenceId(14)]
541+
rebuilt : SymbolId(0): [ReferenceId(5)]
542+
529543
* optimize-enums/typeof-kept/input.ts
530544
Bindings mismatch:
531545
after transform: ScopeId(1): ["Bar", "X"]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const enum Phase {
2+
idle,
3+
active,
4+
}
5+
6+
const enum Theme {
7+
Light = "Light",
8+
Dark = "Dark",
9+
}
10+
11+
// `as` type-cast
12+
const a1 = Phase.idle as Phase;
13+
const a2 = Phase["active"] as Phase;
14+
const a3 = Theme.Light as Theme;
15+
16+
// `satisfies` type-cast
17+
const s1 = Phase.idle satisfies Phase;
18+
const s2 = Theme.Dark satisfies Theme;
19+
20+
// `!` non-null assertion
21+
const n1 = Phase.active!;
22+
const n2 = Theme.Light!;
23+
24+
// `<T>` type assertion
25+
const t1 = <Phase>Phase.idle;
26+
27+
// nested / combined
28+
const c1 = (Phase.active as Phase) satisfies Phase;
29+
const c2 = (Phase.idle satisfies Phase)!;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"plugins": [["transform-typescript", { "optimizeConstEnums": true }]]
3+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// `as` type-cast
2+
const a1 = 0;
3+
const a2 = 1;
4+
const a3 = "Light";
5+
// `satisfies` type-cast
6+
const s1 = 0;
7+
const s2 = "Dark";
8+
// `!` non-null assertion
9+
const n1 = 1;
10+
const n2 = "Light";
11+
// `<T>` type assertion
12+
const t1 = 0;
13+
// nested / combined
14+
const c1 = 1;
15+
const c2 = 0;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
enum Direction {
2+
Up,
3+
Down,
4+
}
5+
6+
Direction.Up as Direction;
7+
Direction["Down"] as Direction;
8+
Direction.Up satisfies Direction;
9+
Direction.Down!;
10+
<Direction>Direction.Up;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
var Direction = /* @__PURE__ */ function(Direction) {
2+
Direction[Direction["Up"] = 0] = "Up";
3+
Direction[Direction["Down"] = 1] = "Down";
4+
return Direction;
5+
}(Direction || {});
6+
0;
7+
1;
8+
0;
9+
1;
10+
0;

0 commit comments

Comments
 (0)