From 15914b25439a1a592b4da61d7c97b392e954b7e3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:45:52 +0000 Subject: [PATCH 1/3] Initial plan From 4adbb1dc8d4db4ccfd5ebf88ee2de98683e051e0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 24 Aug 2026 20:06:12 +0000 Subject: [PATCH 2/3] Fix panic in declaration emit for export default arrow/function expression Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com> --- .../transformers/declarations/transform.go | 8 ++++ ...tExportArrowFunctionPrivateName.errors.txt | 21 +++++++++++ ...itDefaultExportArrowFunctionPrivateName.js | 28 ++++++++++++++ ...aultExportArrowFunctionPrivateName.symbols | 28 ++++++++++++++ ...efaultExportArrowFunctionPrivateName.types | 32 ++++++++++++++++ ...rtFunctionExpressionPrivateName.errors.txt | 25 +++++++++++++ ...aultExportFunctionExpressionPrivateName.js | 30 +++++++++++++++ ...xportFunctionExpressionPrivateName.symbols | 31 ++++++++++++++++ ...tExportFunctionExpressionPrivateName.types | 37 +++++++++++++++++++ ...itDefaultExportArrowFunctionPrivateName.ts | 20 ++++++++++ ...aultExportFunctionExpressionPrivateName.ts | 22 +++++++++++ 11 files changed, 282 insertions(+) create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.errors.txt create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.js create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.types create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.errors.txt create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.js create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.types create mode 100644 tsc/testdata/tests/cases/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.ts create mode 100644 tsc/testdata/tests/cases/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.ts diff --git a/tsc/internal/transformers/declarations/transform.go b/tsc/internal/transformers/declarations/transform.go index 08e26b96a82fd..802fc65231453 100644 --- a/tsc/internal/transformers/declarations/transform.go +++ b/tsc/internal/transformers/declarations/transform.go @@ -1245,8 +1245,16 @@ func (tx *DeclarationTransformer) transformExportAssignment(input *ast.Node, ass if tx.needsDeclare { mods = append(mods, tx.Factory().NewModifier(ast.KindDeclareKeyword)) } + tx.state.getSymbolAccessibilityDiagnostic = func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { + return &SymbolAccessibilityDiagnostic{ + diagnosticMessage: diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, + errorNode: input, + } + } + tx.tracker.PushErrorFallbackNode(assignment) fullSignatureType := assignment.Type() funcDecl := tx.transformFunctionLikeToDeclaration(unwrapped, newId, tx.Factory().NewModifierList(mods), fullSignatureType) + tx.tracker.PopErrorFallbackNode() tx.preserveJsDoc(funcDecl, input) // Reuse the same name node for the export so unique names resolve consistently exportAssignment := tx.Factory().NewExportAssignment(nil, isExportEquals, nil, newId) diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.errors.txt b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.errors.txt new file mode 100644 index 0000000000000..40f6f3ddcae9b --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.errors.txt @@ -0,0 +1,21 @@ +repro.ts(3,1): error TS4082: Default export of the module has or is using private name 'brand'. + + +==== helper.ts (0 errors) ==== + declare const brand: unique symbol; + + class Foo { + [brand]: number = 1; + } + + export function makeFoo() { + return new Foo(); + } + +==== repro.ts (1 errors) ==== + import { makeFoo } from './helper'; + + export default () => makeFoo(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS4082: Default export of the module has or is using private name 'brand'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.js b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.js new file mode 100644 index 0000000000000..fc73dfe930972 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.js @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.ts] //// + +//// [helper.ts] +declare const brand: unique symbol; + +class Foo { + [brand]: number = 1; +} + +export function makeFoo() { + return new Foo(); +} + +//// [repro.ts] +import { makeFoo } from './helper'; + +export default () => makeFoo(); + + + + +//// [helper.d.ts] +declare const brand: unique symbol; +declare class Foo { + [brand]: number; +} +export declare function makeFoo(): Foo; +export {}; diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.symbols b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.symbols new file mode 100644 index 0000000000000..bb52cb85dc346 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.symbols @@ -0,0 +1,28 @@ +//// [tests/cases/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.ts] //// + +=== helper.ts === +declare const brand: unique symbol; +>brand : Symbol(brand, Decl(helper.ts, 0, 13)) + +class Foo { +>Foo : Symbol(Foo, Decl(helper.ts, 0, 35)) + + [brand]: number = 1; +>[brand] : Symbol(Foo[brand], Decl(helper.ts, 2, 11)) +>brand : Symbol(brand, Decl(helper.ts, 0, 13)) +} + +export function makeFoo() { +>makeFoo : Symbol(makeFoo, Decl(helper.ts, 4, 1)) + + return new Foo(); +>Foo : Symbol(Foo, Decl(helper.ts, 0, 35)) +} + +=== repro.ts === +import { makeFoo } from './helper'; +>makeFoo : Symbol(makeFoo, Decl(repro.ts, 0, 8)) + +export default () => makeFoo(); +>makeFoo : Symbol(makeFoo, Decl(repro.ts, 0, 8)) + diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.types b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.types new file mode 100644 index 0000000000000..50de24d6fff21 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.types @@ -0,0 +1,32 @@ +//// [tests/cases/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.ts] //// + +=== helper.ts === +declare const brand: unique symbol; +>brand : unique symbol + +class Foo { +>Foo : Foo + + [brand]: number = 1; +>[brand] : number +>brand : unique symbol +>1 : 1 +} + +export function makeFoo() { +>makeFoo : () => Foo + + return new Foo(); +>new Foo() : Foo +>Foo : typeof Foo +} + +=== repro.ts === +import { makeFoo } from './helper'; +>makeFoo : () => Foo + +export default () => makeFoo(); +>() => makeFoo() : () => Foo +>makeFoo() : Foo +>makeFoo : () => Foo + diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.errors.txt b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.errors.txt new file mode 100644 index 0000000000000..610e62a267335 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.errors.txt @@ -0,0 +1,25 @@ +repro.ts(3,1): error TS4082: Default export of the module has or is using private name 'brand'. + + +==== helper.ts (0 errors) ==== + declare const brand: unique symbol; + + class Foo { + [brand]: number = 1; + } + + export function makeFoo() { + return new Foo(); + } + +==== repro.ts (1 errors) ==== + import { makeFoo } from './helper'; + + export default (function () { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + return makeFoo(); + ~~~~~~~~~~~~~~~~~~~ + }); + ~~~ +!!! error TS4082: Default export of the module has or is using private name 'brand'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.js b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.js new file mode 100644 index 0000000000000..e93913998f14f --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.js @@ -0,0 +1,30 @@ +//// [tests/cases/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.ts] //// + +//// [helper.ts] +declare const brand: unique symbol; + +class Foo { + [brand]: number = 1; +} + +export function makeFoo() { + return new Foo(); +} + +//// [repro.ts] +import { makeFoo } from './helper'; + +export default (function () { + return makeFoo(); +}); + + + + +//// [helper.d.ts] +declare const brand: unique symbol; +declare class Foo { + [brand]: number; +} +export declare function makeFoo(): Foo; +export {}; diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.symbols b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.symbols new file mode 100644 index 0000000000000..7d5de9383d4bb --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.symbols @@ -0,0 +1,31 @@ +//// [tests/cases/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.ts] //// + +=== helper.ts === +declare const brand: unique symbol; +>brand : Symbol(brand, Decl(helper.ts, 0, 13)) + +class Foo { +>Foo : Symbol(Foo, Decl(helper.ts, 0, 35)) + + [brand]: number = 1; +>[brand] : Symbol(Foo[brand], Decl(helper.ts, 2, 11)) +>brand : Symbol(brand, Decl(helper.ts, 0, 13)) +} + +export function makeFoo() { +>makeFoo : Symbol(makeFoo, Decl(helper.ts, 4, 1)) + + return new Foo(); +>Foo : Symbol(Foo, Decl(helper.ts, 0, 35)) +} + +=== repro.ts === +import { makeFoo } from './helper'; +>makeFoo : Symbol(makeFoo, Decl(repro.ts, 0, 8)) + +export default (function () { + return makeFoo(); +>makeFoo : Symbol(makeFoo, Decl(repro.ts, 0, 8)) + +}); + diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.types b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.types new file mode 100644 index 0000000000000..7b9daa304881a --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.types @@ -0,0 +1,37 @@ +//// [tests/cases/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.ts] //// + +=== helper.ts === +declare const brand: unique symbol; +>brand : unique symbol + +class Foo { +>Foo : Foo + + [brand]: number = 1; +>[brand] : number +>brand : unique symbol +>1 : 1 +} + +export function makeFoo() { +>makeFoo : () => Foo + + return new Foo(); +>new Foo() : Foo +>Foo : typeof Foo +} + +=== repro.ts === +import { makeFoo } from './helper'; +>makeFoo : () => Foo + +export default (function () { +>(function () { return makeFoo();}) : () => Foo +>function () { return makeFoo();} : () => Foo + + return makeFoo(); +>makeFoo() : Foo +>makeFoo : () => Foo + +}); + diff --git a/tsc/testdata/tests/cases/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.ts b/tsc/testdata/tests/cases/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.ts new file mode 100644 index 0000000000000..d85edb8d4f9ad --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/declarationEmitDefaultExportArrowFunctionPrivateName.ts @@ -0,0 +1,20 @@ +// @declaration: true +// @emitDeclarationOnly: true +// @outDir: dist +// @strict: true + +// @filename: helper.ts +declare const brand: unique symbol; + +class Foo { + [brand]: number = 1; +} + +export function makeFoo() { + return new Foo(); +} + +// @filename: repro.ts +import { makeFoo } from './helper'; + +export default () => makeFoo(); diff --git a/tsc/testdata/tests/cases/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.ts b/tsc/testdata/tests/cases/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.ts new file mode 100644 index 0000000000000..f639a0997f33b --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/declarationEmitDefaultExportFunctionExpressionPrivateName.ts @@ -0,0 +1,22 @@ +// @declaration: true +// @emitDeclarationOnly: true +// @outDir: dist +// @strict: true + +// @filename: helper.ts +declare const brand: unique symbol; + +class Foo { + [brand]: number = 1; +} + +export function makeFoo() { + return new Foo(); +} + +// @filename: repro.ts +import { makeFoo } from './helper'; + +export default (function () { + return makeFoo(); +}); From 7c402979bf1d0a6462ddbdfce06ec837f7d2b7da Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 24 Aug 2026 20:42:04 +0000 Subject: [PATCH 3/3] Consolidate symbol accessibility diagnostic setup in transformExportAssignment Co-authored-by: weswigham <2932786+weswigham@users.noreply.github.com> --- .../transformers/declarations/transform.go | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/tsc/internal/transformers/declarations/transform.go b/tsc/internal/transformers/declarations/transform.go index 802fc65231453..166d484661a6e 100644 --- a/tsc/internal/transformers/declarations/transform.go +++ b/tsc/internal/transformers/declarations/transform.go @@ -1225,6 +1225,14 @@ func (tx *DeclarationTransformer) transformExportAssignment(input *ast.Node, ass return exportAssignment } + tx.state.getSymbolAccessibilityDiagnostic = func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { + return &SymbolAccessibilityDiagnostic{ + diagnosticMessage: diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, + errorNode: input, + } + } + tx.tracker.PushErrorFallbackNode(assignment) + // Check if the expression is a class expression - emit as a class declaration + export assignment unwrapped := ast.SkipOuterExpressions(expression, ast.OEKExpressionTypePassthrough) newId := tx.getNameOfExportedAssignedExpression(unwrapped, isExportEquals) @@ -1234,6 +1242,7 @@ func (tx *DeclarationTransformer) transformExportAssignment(input *ast.Node, ass mods = append(mods, tx.Factory().NewModifier(ast.KindDeclareKeyword)) } classDecl := tx.transformClassExpressionToDeclaration(unwrapped, newId, tx.Factory().NewModifierList(mods)) + tx.tracker.PopErrorFallbackNode() tx.preserveJsDoc(classDecl, input) // Reuse the same name node for the export so unique names resolve consistently exportAssignment := tx.Factory().NewExportAssignment(nil, isExportEquals, nil, newId) @@ -1245,13 +1254,6 @@ func (tx *DeclarationTransformer) transformExportAssignment(input *ast.Node, ass if tx.needsDeclare { mods = append(mods, tx.Factory().NewModifier(ast.KindDeclareKeyword)) } - tx.state.getSymbolAccessibilityDiagnostic = func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { - return &SymbolAccessibilityDiagnostic{ - diagnosticMessage: diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, - errorNode: input, - } - } - tx.tracker.PushErrorFallbackNode(assignment) fullSignatureType := assignment.Type() funcDecl := tx.transformFunctionLikeToDeclaration(unwrapped, newId, tx.Factory().NewModifierList(mods), fullSignatureType) tx.tracker.PopErrorFallbackNode() @@ -1263,14 +1265,7 @@ func (tx *DeclarationTransformer) transformExportAssignment(input *ast.Node, ass } // expression is non-identifier, create _default typed variable to reference - tx.state.getSymbolAccessibilityDiagnostic = func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { - return &SymbolAccessibilityDiagnostic{ - diagnosticMessage: diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, - errorNode: input, - } - } tx.cjsExportAssignmentName = newId - tx.tracker.PushErrorFallbackNode(assignment) var type_, initializer *ast.Node if ast.IsPrimitiveLiteralValue(unwrapParenthesizedExpression(expression), true) { initializer = tx.resolver.CreateLiteralConstValue(tx.EmitContext(), tx.EmitContext().ParseNode(assignment), tx.tracker)