diff --git a/internal/bundler_tests/snapshots/snapshots_ts.txt b/internal/bundler_tests/snapshots/snapshots_ts.txt index 69960ee039d..5e2ccbe0870 100644 --- a/internal/bundler_tests/snapshots/snapshots_ts.txt +++ b/internal/bundler_tests/snapshots/snapshots_ts.txt @@ -1739,9 +1739,9 @@ console.log("success"); TestTSPrintNonFiniteNumberInsideWith ---------- /out.js ---------- var Foo = /* @__PURE__ */ ((Foo2) => { - Foo2[Foo2["NAN"] = NaN] = "NAN"; - Foo2[Foo2["POS_INF"] = Infinity] = "POS_INF"; - Foo2[Foo2["NEG_INF"] = -Infinity] = "NEG_INF"; + Foo2["NAN"] = NaN; + Foo2["POS_INF"] = Infinity; + Foo2["NEG_INF"] = -Infinity; return Foo2; })(Foo || {}); //! It's ok to use "NaN" and "Infinity" here diff --git a/internal/js_ast/js_ast.go b/internal/js_ast/js_ast.go index ca37f342a42..66800922909 100644 --- a/internal/js_ast/js_ast.go +++ b/internal/js_ast/js_ast.go @@ -1030,6 +1030,7 @@ type SEnum struct { Values []EnumValue Name ast.LocRef Arg ast.Ref + IsConst bool IsExport bool } diff --git a/internal/js_parser/js_parser.go b/internal/js_parser/js_parser.go index a3e6a913e03..61183408e41 100644 --- a/internal/js_parser/js_parser.go +++ b/internal/js_parser/js_parser.go @@ -7095,7 +7095,7 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt { if !p.options.ts.Parse { p.lexer.Unexpected() } - return p.parseTypeScriptEnumStmt(loc, opts) + return p.parseTypeScriptEnumStmt(loc, opts, false) case js_lexer.TAt: // Parse decorators before class statements, which are potentially exported @@ -7176,7 +7176,7 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt { p.lexer.Next() if p.options.ts.Parse && p.lexer.Token == js_lexer.TEnum { - return p.parseTypeScriptEnumStmt(loc, opts) + return p.parseTypeScriptEnumStmt(loc, opts, true) } decls := p.parseAndDeclareDecls(ast.SymbolConst, opts) @@ -10940,8 +10940,8 @@ func (p *parser) visitAndAppendStmt(stmts []js_ast.Stmt, stmt js_ast.Stmt) []js_ } p.recordUsage(s.Arg) - // String-valued enums do not form a two-way map - if hasStringValue { + // Const-based and string-valued enums do not form a two-way map + if hasStringValue || s.IsConst { valueExprs = append(valueExprs, assignTarget) } else { // "Enum[assignTarget] = 'Name'" @@ -10969,7 +10969,7 @@ func (p *parser) visitAndAppendStmt(stmts []js_ast.Stmt, stmt js_ast.Stmt) []js_ // Wrap this enum definition in a closure stmts = p.generateClosureForTypeScriptEnum( - stmts, stmt.Loc, s.IsExport, s.Name.Loc, s.Name.Ref, s.Arg, valueExprs, allValuesArePure) + stmts, stmt.Loc, s.IsConst, s.IsExport, s.Name.Loc, s.Name.Ref, s.Arg, valueExprs, allValuesArePure) return stmts case *js_ast.SNamespace: diff --git a/internal/js_parser/ts_parser.go b/internal/js_parser/ts_parser.go index 6338fa09a9a..ffa3a558d2c 100644 --- a/internal/js_parser/ts_parser.go +++ b/internal/js_parser/ts_parser.go @@ -1270,7 +1270,7 @@ func (p *parser) skipTypeScriptTypeStmt(opts parseStmtOpts) { p.lexer.ExpectOrInsertSemicolon() } -func (p *parser) parseTypeScriptEnumStmt(loc logger.Loc, opts parseStmtOpts) js_ast.Stmt { +func (p *parser) parseTypeScriptEnumStmt(loc logger.Loc, opts parseStmtOpts, isConst bool) js_ast.Stmt { p.lexer.Expect(js_lexer.TEnum) nameLoc := p.lexer.Loc() nameText := p.lexer.Identifier.String @@ -1445,6 +1445,7 @@ func (p *parser) parseTypeScriptEnumStmt(loc logger.Loc, opts parseStmtOpts) js_ Name: name, Arg: tsNamespace.ArgRef, Values: values, + IsConst: isConst, IsExport: opts.isExport, }} } @@ -1865,7 +1866,7 @@ func (p *parser) generateClosureForTypeScriptNamespaceOrEnum( } func (p *parser) generateClosureForTypeScriptEnum( - stmts []js_ast.Stmt, stmtLoc logger.Loc, isExport bool, nameLoc logger.Loc, + stmts []js_ast.Stmt, stmtLoc logger.Loc, isConst bool, isExport bool, nameLoc logger.Loc, nameRef ast.Ref, argRef ast.Ref, exprsInsideClosure []js_ast.Expr, allValuesArePure bool, ) []js_ast.Stmt { diff --git a/internal/js_parser/ts_parser_test.go b/internal/js_parser/ts_parser_test.go index 41058a352fb..88c70a114c2 100644 --- a/internal/js_parser/ts_parser_test.go +++ b/internal/js_parser/ts_parser_test.go @@ -1640,10 +1640,17 @@ bar = 0 /* FOO */; expectPrintedTS(t, "(() => { const enum Foo { A } () => Foo.A })", `() => { let Foo; ((Foo) => { - Foo[Foo["A"] = 0] = "A"; + Foo["A"] = 0; })(Foo || (Foo = {})); () => 0 /* A */; }; +`) + + expectPrintedTS(t, "const enum Foo { A, B }", `var Foo = /* @__PURE__ */ ((Foo) => { + Foo["A"] = 0; + Foo["B"] = 1; + return Foo; +})(Foo || {}); `) }