Skip to content

Commit

Permalink
fix #3657: empty enum returns {} not undefined
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Feb 19, 2024
1 parent 9f9e4f8 commit 40711af
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 13 deletions.
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Changelog

## Unreleased

* Empty enums should behave like an object literal ([#3657](https://github.com/evanw/esbuild/issues/3657))

TypeScript allows you to create an empty enum and add properties to it at run time. While people usually use an empty object literal for this instead of a TypeScript enum, esbuild's enum transform didn't anticipate this use case and generated `undefined` instead of `{}` for an empty enum. With this release, you can now use an empty enum to generate an empty object literal.

```ts
// Original code
enum Foo {}

// Old output (with --loader=ts)
var Foo = /* @__PURE__ */ ((Foo2) => {
})(Foo || {});

// New output (with --loader=ts)
var Foo = /* @__PURE__ */ ((Foo2) => {
return Foo2;
})(Foo || {});
```

## 0.20.1

* Fix a bug with the CSS nesting transform ([#3648](https://github.com/evanw/esbuild/issues/3648))
Expand Down
22 changes: 10 additions & 12 deletions internal/js_parser/ts_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1930,19 +1930,17 @@ func (p *parser) generateClosureForTypeScriptEnum(

// Generate the body of the closure, including a return statement at the end
stmtsInsideClosure := []js_ast.Stmt{}
if len(exprsInsideClosure) > 0 {
argExpr := js_ast.Expr{Loc: nameLoc, Data: &js_ast.EIdentifier{Ref: argRef}}
if p.options.minifySyntax {
// "a; b; return c;" => "return a, b, c;"
joined := js_ast.JoinAllWithComma(exprsInsideClosure)
joined = js_ast.JoinWithComma(joined, argExpr)
stmtsInsideClosure = append(stmtsInsideClosure, js_ast.Stmt{Loc: joined.Loc, Data: &js_ast.SReturn{ValueOrNil: joined}})
} else {
for _, expr := range exprsInsideClosure {
stmtsInsideClosure = append(stmtsInsideClosure, js_ast.Stmt{Loc: expr.Loc, Data: &js_ast.SExpr{Value: expr}})
}
stmtsInsideClosure = append(stmtsInsideClosure, js_ast.Stmt{Loc: argExpr.Loc, Data: &js_ast.SReturn{ValueOrNil: argExpr}})
argExpr := js_ast.Expr{Loc: nameLoc, Data: &js_ast.EIdentifier{Ref: argRef}}
if p.options.minifySyntax {
// "a; b; return c;" => "return a, b, c;"
joined := js_ast.JoinAllWithComma(exprsInsideClosure)
joined = js_ast.JoinWithComma(joined, argExpr)
stmtsInsideClosure = append(stmtsInsideClosure, js_ast.Stmt{Loc: joined.Loc, Data: &js_ast.SReturn{ValueOrNil: joined}})
} else {
for _, expr := range exprsInsideClosure {
stmtsInsideClosure = append(stmtsInsideClosure, js_ast.Stmt{Loc: expr.Loc, Data: &js_ast.SExpr{Value: expr}})
}
stmtsInsideClosure = append(stmtsInsideClosure, js_ast.Stmt{Loc: argExpr.Loc, Data: &js_ast.SReturn{ValueOrNil: argExpr}})
}

// Try to use an arrow function if possible for compactness
Expand Down
2 changes: 1 addition & 1 deletion internal/js_parser/ts_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1804,7 +1804,7 @@ func TestTSDeclare(t *testing.T) {
expectPrintedTS(t, "declare\nconst foo = 0", "declare;\nconst foo = 0;\n")
expectPrintedTS(t, "declare\nfunction foo() {}", "declare;\nfunction foo() {\n}\n")
expectPrintedTS(t, "declare\nclass Foo {}", "declare;\nclass Foo {\n}\n")
expectPrintedTS(t, "declare\nenum Foo {}", "declare;\nvar Foo = /* @__PURE__ */ ((Foo) => {\n})(Foo || {});\n")
expectPrintedTS(t, "declare\nenum Foo {}", "declare;\nvar Foo = /* @__PURE__ */ ((Foo) => {\n return Foo;\n})(Foo || {});\n")
expectPrintedTS(t, "class Foo { declare \n foo }", "class Foo {\n declare;\n foo;\n}\n")

expectPrintedTS(t, "declare;", "declare;\n")
Expand Down

0 comments on commit 40711af

Please sign in to comment.