diff --git a/internal/js_parser/js_parser.go b/internal/js_parser/js_parser.go index 5461ac0cfeb..61ee0c9865e 100644 --- a/internal/js_parser/js_parser.go +++ b/internal/js_parser/js_parser.go @@ -9335,7 +9335,6 @@ func (p *parser) visitAndAppendStmt(stmts []js_ast.Stmt, stmt js_ast.Stmt) []js_ case *js_ast.SEnum: p.recordDeclaredSymbol(s.Name.Ref) p.pushScopeForVisitPass(js_ast.ScopeEntry, stmt.Loc) - defer p.popScope() p.recordDeclaredSymbol(s.Arg) // Scan ahead for any variables inside this namespace. This must be done @@ -9439,6 +9438,7 @@ func (p *parser) visitAndAppendStmt(stmts []js_ast.Stmt, stmt js_ast.Stmt) []js_ p.recordUsage(s.Arg) } + p.popScope() p.shouldFoldNumericConstants = oldShouldFoldNumericConstants // Generate statements from expressions diff --git a/internal/js_parser/ts_parser.go b/internal/js_parser/ts_parser.go index ea44fe2dee2..f415c262135 100644 --- a/internal/js_parser/ts_parser.go +++ b/internal/js_parser/ts_parser.go @@ -1353,7 +1353,7 @@ func (p *parser) generateClosureForTypeScriptNamespaceOrEnum( // can be multiple namespace blocks for the same namespace if (symbol.Kind == js_ast.SymbolTSNamespace || symbol.Kind == js_ast.SymbolTSEnum) && !p.emittedNamespaceVars[nameRef] { p.emittedNamespaceVars[nameRef] = true - if p.enclosingNamespaceArgRef == nil { + if p.currentScope == p.moduleScope { // Top-level namespace stmts = append(stmts, js_ast.Stmt{Loc: stmtLoc, Data: &js_ast.SLocal{ Kind: js_ast.LocalVar, diff --git a/internal/js_parser/ts_parser_test.go b/internal/js_parser/ts_parser_test.go index 228e0096d4b..bdb4aca5133 100644 --- a/internal/js_parser/ts_parser_test.go +++ b/internal/js_parser/ts_parser_test.go @@ -1099,6 +1099,10 @@ y = [0, Foo?.["A"], Foo?.["A"]()]; })(Foo || (Foo = {})); `) + // Check top-level "var" and nested "let" + expectPrintedTS(t, "enum a { b = 1 }", "var a;\n(function(a) {\n a[a[\"b\"] = 1] = \"b\";\n})(a || (a = {}));\n") + expectPrintedTS(t, "{ enum a { b = 1 } }", "{\n let a;\n (function(a) {\n a[a[\"b\"] = 1] = \"b\";\n })(a || (a = {}));\n}\n") + // Check "await" and "yield" expectPrintedTS(t, "enum x { await = 1, y = await }", `var x; (function(x) { diff --git a/scripts/end-to-end-tests.js b/scripts/end-to-end-tests.js index f08be85207e..e2bd9d27d83 100644 --- a/scripts/end-to-end-tests.js +++ b/scripts/end-to-end-tests.js @@ -81,6 +81,28 @@ }), ) + // Test TypeScript enum scope merging + tests.push( + test(['entry.ts', '--bundle', '--outfile=node.js'], { + 'entry.ts': ` + enum a { b = 1 } + enum a { c = 2 } + if (a.c !== 2 || a[2] !== 'c' || a.b !== 1 || a[1] !== 'b') throw 'fail' + `, + }), + test(['entry.ts', '--bundle', '--outfile=node.js'], { + 'entry.ts': ` + { + enum a { b = 1 } + } + { + enum a { c = 2 } + if (a.c !== 2 || a[2] !== 'c' || a.b !== void 0 || a[1] !== void 0) throw 'fail' + } + `, + }), + ) + // Test coverage for a special JSX error message tests.push( test(['example.jsx', '--outfile=node.js'], {