From 269b0cc63a61b0d2455c4afa4e21a29ef3a28ce2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 4 Sep 2026 00:33:39 +0000 Subject: [PATCH 1/3] Initial plan From 67aea51334b096e79f69589a19cd3ed2c61a0671 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 4 Sep 2026 00:55:36 +0000 Subject: [PATCH 2/3] Reject exports from global augmentations Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com> --- tsc/internal/checker/checker.go | 2 +- ...exportSpecifierForAGlobalAugmentation.errors.txt | 12 ++++++++++++ .../exportSpecifierForAGlobalAugmentation.js | 12 ++++++++++++ .../exportSpecifierForAGlobalAugmentation.symbols | 13 +++++++++++++ .../exportSpecifierForAGlobalAugmentation.types | 13 +++++++++++++ .../exportSpecifierForAGlobalAugmentation.ts | 5 +++++ 6 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.errors.txt create mode 100644 tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.js create mode 100644 tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.types create mode 100644 tsc/testdata/tests/cases/compiler/exportSpecifierForAGlobalAugmentation.ts diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index ca77e97af8547..a5da4adf3ed55 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -5726,7 +5726,7 @@ func (c *Checker) checkExportSpecifier(node *ast.ExportSpecifierNode) { } // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases) symbol := c.resolveName(exportedName, exportedName.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, true /*isUse*/, false) - if symbol != nil && (symbol == c.undefinedSymbol || symbol == c.globalThisSymbol || symbol.Declarations != nil && ast.IsGlobalSourceFile(ast.GetDeclarationContainer(symbol.Declarations[0]))) { + if symbol != nil && (symbol == c.undefinedSymbol || symbol == c.globalThisSymbol || symbol.Declarations != nil && (ast.IsGlobalSourceFile(ast.GetDeclarationContainer(symbol.Declarations[0])) || ast.IsModuleBlock(ast.GetDeclarationContainer(symbol.Declarations[0])) && ast.IsGlobalScopeAugmentation(ast.GetDeclarationContainer(symbol.Declarations[0]).Parent))) { c.error(exportedName, diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, exportedName.Text()) } else { c.markLinkedReferences(node, ReferenceHintExportSpecifier, nil /*propSymbol*/, nil /*parentType*/) diff --git a/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.errors.txt b/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.errors.txt new file mode 100644 index 0000000000000..49d9d266fe726 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.errors.txt @@ -0,0 +1,12 @@ +exportSpecifierForAGlobalAugmentation.ts(5,10): error TS2661: Cannot export 'XYZ'. Only local declarations can be exported from a module. + + +==== exportSpecifierForAGlobalAugmentation.ts (1 errors) ==== + declare global { + var XYZ: number; + } + + export { XYZ }; + ~~~ +!!! error TS2661: Cannot export 'XYZ'. Only local declarations can be exported from a module. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.js b/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.js new file mode 100644 index 0000000000000..7b6f79f3f0458 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.js @@ -0,0 +1,12 @@ +//// [tests/cases/compiler/exportSpecifierForAGlobalAugmentation.ts] //// + +//// [exportSpecifierForAGlobalAugmentation.ts] +declare global { + var XYZ: number; +} + +export { XYZ }; + + +//// [exportSpecifierForAGlobalAugmentation.js] +export { XYZ }; diff --git a/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.symbols b/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.symbols new file mode 100644 index 0000000000000..2245ce2750bdd --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.symbols @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/exportSpecifierForAGlobalAugmentation.ts] //// + +=== exportSpecifierForAGlobalAugmentation.ts === +declare global { +>global : Symbol(global, Decl(exportSpecifierForAGlobalAugmentation.ts, 0, 0)) + + var XYZ: number; +>XYZ : Symbol(XYZ, Decl(exportSpecifierForAGlobalAugmentation.ts, 1, 7)) +} + +export { XYZ }; +>XYZ : Symbol(XYZ, Decl(exportSpecifierForAGlobalAugmentation.ts, 4, 8)) + diff --git a/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.types b/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.types new file mode 100644 index 0000000000000..935ee469dcf03 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/exportSpecifierForAGlobalAugmentation.types @@ -0,0 +1,13 @@ +//// [tests/cases/compiler/exportSpecifierForAGlobalAugmentation.ts] //// + +=== exportSpecifierForAGlobalAugmentation.ts === +declare global { +>global : typeof global + + var XYZ: number; +>XYZ : number +} + +export { XYZ }; +>XYZ : number + diff --git a/tsc/testdata/tests/cases/compiler/exportSpecifierForAGlobalAugmentation.ts b/tsc/testdata/tests/cases/compiler/exportSpecifierForAGlobalAugmentation.ts new file mode 100644 index 0000000000000..1ded55694d9b1 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/exportSpecifierForAGlobalAugmentation.ts @@ -0,0 +1,5 @@ +declare global { + var XYZ: number; +} + +export { XYZ }; From d6c2b0fa22f7931a0fd8706f7424bcde0fb17f9d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 4 Sep 2026 00:58:47 +0000 Subject: [PATCH 3/3] Simplify global export validation Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com> --- tsc/internal/checker/checker.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index a5da4adf3ed55..0f1a8886990cc 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -5726,7 +5726,12 @@ func (c *Checker) checkExportSpecifier(node *ast.ExportSpecifierNode) { } // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases) symbol := c.resolveName(exportedName, exportedName.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, true /*isUse*/, false) - if symbol != nil && (symbol == c.undefinedSymbol || symbol == c.globalThisSymbol || symbol.Declarations != nil && (ast.IsGlobalSourceFile(ast.GetDeclarationContainer(symbol.Declarations[0])) || ast.IsModuleBlock(ast.GetDeclarationContainer(symbol.Declarations[0])) && ast.IsGlobalScopeAugmentation(ast.GetDeclarationContainer(symbol.Declarations[0]).Parent))) { + isGlobalDeclaration := false + if symbol != nil && symbol.Declarations != nil { + declarationContainer := ast.GetDeclarationContainer(symbol.Declarations[0]) + isGlobalDeclaration = ast.IsGlobalSourceFile(declarationContainer) || ast.IsModuleBlock(declarationContainer) && ast.IsGlobalScopeAugmentation(declarationContainer.Parent) + } + if symbol != nil && (symbol == c.undefinedSymbol || symbol == c.globalThisSymbol || isGlobalDeclaration) { c.error(exportedName, diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, exportedName.Text()) } else { c.markLinkedReferences(node, ReferenceHintExportSpecifier, nil /*propSymbol*/, nil /*parentType*/)