From 682fd6d432cd52d0d4e622f4f496b110673f7ff9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 16 May 2026 19:41:43 +0000 Subject: [PATCH 1/5] Initial plan From 1da664f0db1b01b06e3ec33588becd3c366bf0df Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 16 May 2026 19:55:55 +0000 Subject: [PATCH 2/5] fix: handle numeric literal in emitModuleExportName to prevent panic Add KindNumericLiteral case to emitModuleExportName in the printer, which was causing a panic when emitting declarations for CommonJS files with numeric export names like `exports[1] = 2`. Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/9f3fe2c6-afe3-4d4b-9709-13e88c7271b6 Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- internal/printer/printer.go | 2 + .../compiler/numericExportNameDeclaration.js | 59 +++++++++++++++++++ .../numericExportNameDeclaration.symbols | 19 ++++++ .../numericExportNameDeclaration.types | 28 +++++++++ .../compiler/numericExportNameDeclaration.ts | 8 +++ 5 files changed, 116 insertions(+) create mode 100644 testdata/baselines/reference/compiler/numericExportNameDeclaration.js create mode 100644 testdata/baselines/reference/compiler/numericExportNameDeclaration.symbols create mode 100644 testdata/baselines/reference/compiler/numericExportNameDeclaration.types create mode 100644 testdata/tests/cases/compiler/numericExportNameDeclaration.ts diff --git a/internal/printer/printer.go b/internal/printer/printer.go index cab32e2589..0a9be47857 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -1297,6 +1297,8 @@ func (p *Printer) emitModuleExportName(node *ast.ModuleExportName) { p.emitIdentifierName(node.AsIdentifier()) case ast.KindStringLiteral: p.emitStringLiteral(node.AsStringLiteral()) + case ast.KindNumericLiteral: + p.emitNumericLiteral(node.AsNumericLiteral()) default: panic(fmt.Sprintf("unexpected ModuleExportName: %v", node.Kind)) } diff --git a/testdata/baselines/reference/compiler/numericExportNameDeclaration.js b/testdata/baselines/reference/compiler/numericExportNameDeclaration.js new file mode 100644 index 0000000000..85f4b55cdc --- /dev/null +++ b/testdata/baselines/reference/compiler/numericExportNameDeclaration.js @@ -0,0 +1,59 @@ +//// [tests/cases/compiler/numericExportNameDeclaration.ts] //// + +//// [bug.js] +exports[1] = 2; +module.exports[1] = 2; +Object.defineProperty(exports, 1, {}); + + + + +//// [bug.d.ts] +declare const _exported: any; +export { _exported as 1 }; +declare const _exported_1: any; +export { _exported_1 as 1 }; +declare const _exported_2: any; +export { _exported_2 as 1 }; + + +//// [DtsFileErrors] + + +bug.d.ts(2,22): error TS2300: Duplicate identifier '(Missing)'. +bug.d.ts(2,23): error TS1003: Identifier expected. +bug.d.ts(2,25): error TS1128: Declaration or statement expected. +bug.d.ts(4,24): error TS2300: Duplicate identifier '(Missing)'. +bug.d.ts(4,25): error TS1003: Identifier expected. +bug.d.ts(4,27): error TS1128: Declaration or statement expected. +bug.d.ts(6,24): error TS2300: Duplicate identifier '(Missing)'. +bug.d.ts(6,25): error TS1003: Identifier expected. +bug.d.ts(6,27): error TS1128: Declaration or statement expected. + + +==== bug.d.ts (9 errors) ==== + declare const _exported: any; + export { _exported as 1 }; + +!!! error TS2300: Duplicate identifier '(Missing)'. + ~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1128: Declaration or statement expected. + declare const _exported_1: any; + export { _exported_1 as 1 }; + +!!! error TS2300: Duplicate identifier '(Missing)'. + ~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1128: Declaration or statement expected. + declare const _exported_2: any; + export { _exported_2 as 1 }; + +!!! error TS2300: Duplicate identifier '(Missing)'. + ~ +!!! error TS1003: Identifier expected. + ~ +!!! error TS1128: Declaration or statement expected. + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/numericExportNameDeclaration.symbols b/testdata/baselines/reference/compiler/numericExportNameDeclaration.symbols new file mode 100644 index 0000000000..4d1b3998f1 --- /dev/null +++ b/testdata/baselines/reference/compiler/numericExportNameDeclaration.symbols @@ -0,0 +1,19 @@ +//// [tests/cases/compiler/numericExportNameDeclaration.ts] //// + +=== bug.js === +exports[1] = 2; +>exports : Symbol(exports, Decl(bug.js, 0, 0)) +>1 : Symbol(1, Decl(bug.js, 0, 0), Decl(bug.js, 0, 15), Decl(bug.js, 1, 22)) + +module.exports[1] = 2; +>module.exports : Symbol(exports, Decl(bug.js, 0, 0)) +>module : Symbol(module, Decl(bug.js, 0, 0)) +>exports : Symbol(exports, Decl(bug.js, 0, 0)) +>1 : Symbol(1, Decl(bug.js, 0, 0), Decl(bug.js, 0, 15), Decl(bug.js, 1, 22)) + +Object.defineProperty(exports, 1, {}); +>Object.defineProperty : Symbol(ObjectConstructor.defineProperty, Decl(lib.es5.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>defineProperty : Symbol(ObjectConstructor.defineProperty, Decl(lib.es5.d.ts, --, --)) +>exports : Symbol(exports, Decl(bug.js, 0, 0)) + diff --git a/testdata/baselines/reference/compiler/numericExportNameDeclaration.types b/testdata/baselines/reference/compiler/numericExportNameDeclaration.types new file mode 100644 index 0000000000..00507e0eb4 --- /dev/null +++ b/testdata/baselines/reference/compiler/numericExportNameDeclaration.types @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/numericExportNameDeclaration.ts] //// + +=== bug.js === +exports[1] = 2; +>exports[1] = 2 : 2 +>exports[1] : any +>exports : typeof import("./bug") +>1 : 1 +>2 : 2 + +module.exports[1] = 2; +>module.exports[1] = 2 : 2 +>module.exports[1] : error +>module.exports : typeof import("./bug") +>module : { exports: typeof import("./bug"); } +>exports : typeof import("./bug") +>1 : 1 +>2 : 2 + +Object.defineProperty(exports, 1, {}); +>Object.defineProperty(exports, 1, {}) : typeof import("./bug") +>Object.defineProperty : (o: T, p: PropertyKey, attributes: PropertyDescriptor & ThisType) => T +>Object : ObjectConstructor +>defineProperty : (o: T, p: PropertyKey, attributes: PropertyDescriptor & ThisType) => T +>exports : typeof import("./bug") +>1 : 1 +>{} : {} + diff --git a/testdata/tests/cases/compiler/numericExportNameDeclaration.ts b/testdata/tests/cases/compiler/numericExportNameDeclaration.ts new file mode 100644 index 0000000000..8255adf5d8 --- /dev/null +++ b/testdata/tests/cases/compiler/numericExportNameDeclaration.ts @@ -0,0 +1,8 @@ +// @declaration: true +// @emitDeclarationOnly: true +// @allowJs: true + +// @filename: bug.js +exports[1] = 2; +module.exports[1] = 2; +Object.defineProperty(exports, 1, {}); From 0019d09013b756a9c446136a838e213b261a865b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 16 May 2026 20:44:17 +0000 Subject: [PATCH 3/5] fix: convert numeric literal export names to string literals in declaration emit Numeric property names in JS are string properties; convert NumericLiteral to StringLiteral in getNameExpressionPreferringIdentifier so declarations emit valid syntax like `export { _exported as "1" }` instead of the invalid `export { _exported as 1 }`. Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/0d9fa6e3-1d16-42fa-824c-c7baf31e67ee Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- .../transformers/declarations/transform.go | 4 ++ .../compiler/numericExportNameDeclaration.js | 50 ++++++------------- 2 files changed, 20 insertions(+), 34 deletions(-) diff --git a/internal/transformers/declarations/transform.go b/internal/transformers/declarations/transform.go index c16b75baef..7d36b95780 100644 --- a/internal/transformers/declarations/transform.go +++ b/internal/transformers/declarations/transform.go @@ -2173,6 +2173,10 @@ func (tx *DeclarationTransformer) transformJSDocOptionalType(input *ast.JSDocOpt } func (tx *DeclarationTransformer) getNameExpressionPreferringIdentifier(nameExpr *ast.Node) *ast.Node { + if ast.IsNumericLiteral(nameExpr) { + // Numeric property names are string properties in JS; convert to string literal + nameExpr = tx.Factory().NewStringLiteral(nameExpr.Text(), ast.TokenFlagsNone) + } if ast.IsStringLiteralLike(nameExpr) && scanner.IsIdentifierText(nameExpr.Text(), core.LanguageVariantStandard) { result := tx.Factory().NewIdentifier(nameExpr.Text()) // prefer non-string literal names where possible kwKind := scanner.IdentifierToKeywordKind(result.AsIdentifier()) diff --git a/testdata/baselines/reference/compiler/numericExportNameDeclaration.js b/testdata/baselines/reference/compiler/numericExportNameDeclaration.js index 85f4b55cdc..c8f94b58bc 100644 --- a/testdata/baselines/reference/compiler/numericExportNameDeclaration.js +++ b/testdata/baselines/reference/compiler/numericExportNameDeclaration.js @@ -10,50 +10,32 @@ Object.defineProperty(exports, 1, {}); //// [bug.d.ts] declare const _exported: any; -export { _exported as 1 }; +export { _exported as "1" }; declare const _exported_1: any; -export { _exported_1 as 1 }; +export { _exported_1 as "1" }; declare const _exported_2: any; -export { _exported_2 as 1 }; +export { _exported_2 as "1" }; //// [DtsFileErrors] -bug.d.ts(2,22): error TS2300: Duplicate identifier '(Missing)'. -bug.d.ts(2,23): error TS1003: Identifier expected. -bug.d.ts(2,25): error TS1128: Declaration or statement expected. -bug.d.ts(4,24): error TS2300: Duplicate identifier '(Missing)'. -bug.d.ts(4,25): error TS1003: Identifier expected. -bug.d.ts(4,27): error TS1128: Declaration or statement expected. -bug.d.ts(6,24): error TS2300: Duplicate identifier '(Missing)'. -bug.d.ts(6,25): error TS1003: Identifier expected. -bug.d.ts(6,27): error TS1128: Declaration or statement expected. +bug.d.ts(2,23): error TS2300: Duplicate identifier '"1"'. +bug.d.ts(4,25): error TS2300: Duplicate identifier '"1"'. +bug.d.ts(6,25): error TS2300: Duplicate identifier '"1"'. -==== bug.d.ts (9 errors) ==== +==== bug.d.ts (3 errors) ==== declare const _exported: any; - export { _exported as 1 }; - -!!! error TS2300: Duplicate identifier '(Missing)'. - ~ -!!! error TS1003: Identifier expected. - ~ -!!! error TS1128: Declaration or statement expected. + export { _exported as "1" }; + ~~~ +!!! error TS2300: Duplicate identifier '"1"'. declare const _exported_1: any; - export { _exported_1 as 1 }; - -!!! error TS2300: Duplicate identifier '(Missing)'. - ~ -!!! error TS1003: Identifier expected. - ~ -!!! error TS1128: Declaration or statement expected. + export { _exported_1 as "1" }; + ~~~ +!!! error TS2300: Duplicate identifier '"1"'. declare const _exported_2: any; - export { _exported_2 as 1 }; - -!!! error TS2300: Duplicate identifier '(Missing)'. - ~ -!!! error TS1003: Identifier expected. - ~ -!!! error TS1128: Declaration or statement expected. + export { _exported_2 as "1" }; + ~~~ +!!! error TS2300: Duplicate identifier '"1"'. \ No newline at end of file From 4304c9f0a30ab6c9d2a43d803d9e87ec2315f537 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 14:51:37 +0000 Subject: [PATCH 4/5] fix: emit numeric literals as string literals in emitModuleExportName printer Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/1ec9206d-7bdc-4410-a06d-8ea7247652c9 Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- internal/printer/printer.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/printer/printer.go b/internal/printer/printer.go index 0a9be47857..f51b070776 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -1298,7 +1298,11 @@ func (p *Printer) emitModuleExportName(node *ast.ModuleExportName) { case ast.KindStringLiteral: p.emitStringLiteral(node.AsStringLiteral()) case ast.KindNumericLiteral: - p.emitNumericLiteral(node.AsNumericLiteral()) + // ModuleExportName only accepts identifiers or string literals; + // numeric property names are string properties, so emit as a string literal. + p.writePunctuation("\"") + p.writeLiteral(node.AsNumericLiteral().Text) + p.writePunctuation("\"") default: panic(fmt.Sprintf("unexpected ModuleExportName: %v", node.Kind)) } From 95b66ccbe5a7969a0968cceaa78dcec189dd7377 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 17 May 2026 15:19:49 +0000 Subject: [PATCH 5/5] Remove dead KindNumericLiteral case from emitModuleExportName Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/4efd5625-7022-4615-84fe-f09fae670b06 Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- internal/printer/printer.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/internal/printer/printer.go b/internal/printer/printer.go index f51b070776..cab32e2589 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -1297,12 +1297,6 @@ func (p *Printer) emitModuleExportName(node *ast.ModuleExportName) { p.emitIdentifierName(node.AsIdentifier()) case ast.KindStringLiteral: p.emitStringLiteral(node.AsStringLiteral()) - case ast.KindNumericLiteral: - // ModuleExportName only accepts identifiers or string literals; - // numeric property names are string properties, so emit as a string literal. - p.writePunctuation("\"") - p.writeLiteral(node.AsNumericLiteral().Text) - p.writePunctuation("\"") default: panic(fmt.Sprintf("unexpected ModuleExportName: %v", node.Kind)) }