From ceef7b585fab3790795f6f33017504680bf760d0 Mon Sep 17 00:00:00 2001 From: Sumit Date: Mon, 12 Oct 2026 10:24:54 +0530 Subject: [PATCH 1/2] Fix enum crash when namespace and enum share a name Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- tsc/internal/ast/ast.go | 2 ++ tsc/internal/checker/checker.go | 3 +++ .../enumMemberListModuleBlock.errors.txt | 9 +++++++++ .../compiler/enumMemberListModuleBlock.js | 18 ++++++++++++++++++ .../compiler/enumMemberListModuleBlock.symbols | 13 +++++++++++++ .../compiler/enumMemberListModuleBlock.types | 14 ++++++++++++++ .../compiler/enumMemberListModuleBlock.ts | 2 ++ 7 files changed, 61 insertions(+) create mode 100644 tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.errors.txt create mode 100644 tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.js create mode 100644 tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.types create mode 100644 tsc/testdata/tests/cases/compiler/enumMemberListModuleBlock.ts diff --git a/tsc/internal/ast/ast.go b/tsc/internal/ast/ast.go index 9b08428dd9d4a..05aa91bdd4aab 100644 --- a/tsc/internal/ast/ast.go +++ b/tsc/internal/ast/ast.go @@ -563,6 +563,8 @@ func (n *Node) MemberList() *NodeList { return n.AsInterfaceDeclaration().Members case KindEnumDeclaration: return n.AsEnumDeclaration().Members + case KindModuleBlock: + return n.AsModuleBlock().Statements case KindTypeLiteral: return n.AsTypeLiteralNode().Members case KindMappedType: diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 345ea00ce1437..f484f3f2c5918 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -24475,6 +24475,9 @@ func (c *Checker) getDeclaredTypeOfEnumMember(symbol *ast.Symbol) *Type { } func (c *Checker) computeEnumMemberValues(node *ast.Node) { + if node == nil || node.Kind != ast.KindEnumDeclaration { + return + } nodeLinks := c.nodeLinks.Get(node) if !(nodeLinks.flags&NodeCheckFlagsEnumValuesComputed != 0) { nodeLinks.flags |= NodeCheckFlagsEnumValuesComputed diff --git a/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.errors.txt b/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.errors.txt new file mode 100644 index 0000000000000..6c78957f26d6a --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.errors.txt @@ -0,0 +1,9 @@ +enumMemberListModuleBlock.ts(2,14): error TS18033: Type 'typeof C' is not assignable to type 'number' as required for computed enum member values. + + +==== enumMemberListModuleBlock.ts (1 errors) ==== + namespace E { export class C {} } + enum E { D = E["C"] } + ~~~~~~ +!!! error TS18033: Type 'typeof C' is not assignable to type 'number' as required for computed enum member values. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.js b/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.js new file mode 100644 index 0000000000000..f460dd78318e1 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.js @@ -0,0 +1,18 @@ +//// [tests/cases/compiler/enumMemberListModuleBlock.ts] //// + +//// [enumMemberListModuleBlock.ts] +namespace E { export class C {} } +enum E { D = E["C"] } + + +//// [enumMemberListModuleBlock.js] +"use strict"; +var E; +(function (E) { + class C { + } + E.C = C; +})(E || (E = {})); +(function (E) { + E[E["D"] = E["C"]] = "D"; +})(E || (E = {})); diff --git a/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.symbols b/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.symbols new file mode 100644 index 0000000000000..9c9b7b73ac09a --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.symbols @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/enumMemberListModuleBlock.ts] //// + +=== enumMemberListModuleBlock.ts === +namespace E { export class C {} } +>E : Symbol(E, Decl(enumMemberListModuleBlock.ts, 0, 0), Decl(enumMemberListModuleBlock.ts, 0, 33)) +>C : Symbol(C, Decl(enumMemberListModuleBlock.ts, 0, 13)) + +enum E { D = E["C"] } +>E : Symbol(E, Decl(enumMemberListModuleBlock.ts, 0, 0), Decl(enumMemberListModuleBlock.ts, 0, 33)) +>D : Symbol(E.D, Decl(enumMemberListModuleBlock.ts, 1, 8)) +>E : Symbol(E, Decl(enumMemberListModuleBlock.ts, 0, 0), Decl(enumMemberListModuleBlock.ts, 0, 33)) +>"C" : Symbol(E.C, Decl(enumMemberListModuleBlock.ts, 0, 13)) + diff --git a/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.types b/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.types new file mode 100644 index 0000000000000..3ddf454b67f80 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/enumMemberListModuleBlock.types @@ -0,0 +1,14 @@ +//// [tests/cases/compiler/enumMemberListModuleBlock.ts] //// + +=== enumMemberListModuleBlock.ts === +namespace E { export class C {} } +>E : typeof E +>C : C + +enum E { D = E["C"] } +>E : E +>D : E.D +>E["C"] : typeof E.C +>E : typeof E +>"C" : "C" + diff --git a/tsc/testdata/tests/cases/compiler/enumMemberListModuleBlock.ts b/tsc/testdata/tests/cases/compiler/enumMemberListModuleBlock.ts new file mode 100644 index 0000000000000..3decb5909737b --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/enumMemberListModuleBlock.ts @@ -0,0 +1,2 @@ +namespace E { export class C {} } +enum E { D = E["C"] } From d064a4c4f764c05165f5d29e8f6bdf21056838ba Mon Sep 17 00:00:00 2001 From: Sumit Date: Tue, 13 Oct 2026 12:49:17 +0530 Subject: [PATCH 2/2] fix: preserve AST member list invariants for module blocks --- tsc/internal/ast/ast.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/tsc/internal/ast/ast.go b/tsc/internal/ast/ast.go index 05aa91bdd4aab..9b08428dd9d4a 100644 --- a/tsc/internal/ast/ast.go +++ b/tsc/internal/ast/ast.go @@ -563,8 +563,6 @@ func (n *Node) MemberList() *NodeList { return n.AsInterfaceDeclaration().Members case KindEnumDeclaration: return n.AsEnumDeclaration().Members - case KindModuleBlock: - return n.AsModuleBlock().Statements case KindTypeLiteral: return n.AsTypeLiteralNode().Members case KindMappedType: