From 0f598db3e51f9ba546102ae6754427e51cf54de9 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 15 Mar 2019 09:45:33 -0700 Subject: [PATCH] Fixes #29524, a merged UMD-global (#30403) This kind of merged symbol causes crashes in two places because it's marked BlockScoped, which makes us assume that it must be something that is inside a SourceFile. However, block-scoped checks don't make sense for this kind of symbol, so I exclude them by looking at the kind of the valueDeclaration, as @mprobst suggested in the original bug. --- src/compiler/checker.ts | 3 +- .../checkMergedGlobalUMDSymbol.errors.txt | 22 +++++++++++++++ .../reference/checkMergedGlobalUMDSymbol.js | 22 +++++++++++++++ .../checkMergedGlobalUMDSymbol.symbols | 28 +++++++++++++++++++ .../checkMergedGlobalUMDSymbol.types | 28 +++++++++++++++++++ .../compiler/checkMergedGlobalUMDSymbol.ts | 16 +++++++++++ 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/checkMergedGlobalUMDSymbol.errors.txt create mode 100644 tests/baselines/reference/checkMergedGlobalUMDSymbol.js create mode 100644 tests/baselines/reference/checkMergedGlobalUMDSymbol.symbols create mode 100644 tests/baselines/reference/checkMergedGlobalUMDSymbol.types create mode 100644 tests/cases/compiler/checkMergedGlobalUMDSymbol.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0b1e11db828..5142d608515 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16936,6 +16936,7 @@ namespace ts { function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void { if (languageVersion >= ScriptTarget.ES2015 || (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 || + isSourceFile(symbol.valueDeclaration) || symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause) { return; } @@ -29594,7 +29595,7 @@ namespace ts { } function isSymbolOfDeclarationWithCollidingName(symbol: Symbol): boolean { - if (symbol.flags & SymbolFlags.BlockScoped) { + if (symbol.flags & SymbolFlags.BlockScoped && !isSourceFile(symbol.valueDeclaration)) { const links = getSymbolLinks(symbol); if (links.isDeclarationWithCollidingName === undefined) { const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); diff --git a/tests/baselines/reference/checkMergedGlobalUMDSymbol.errors.txt b/tests/baselines/reference/checkMergedGlobalUMDSymbol.errors.txt new file mode 100644 index 00000000000..f3d21e26b6e --- /dev/null +++ b/tests/baselines/reference/checkMergedGlobalUMDSymbol.errors.txt @@ -0,0 +1,22 @@ +tests/cases/compiler/global.d.ts(6,16): error TS2403: Subsequent variable declarations must have the same type. Variable 'THREE' must be of type 'typeof import("tests/cases/compiler/global")', but here has type 'typeof import("tests/cases/compiler/three")'. + + +==== tests/cases/compiler/three.d.ts (0 errors) ==== + export namespace THREE { + export class Vector2 {} + } + +==== tests/cases/compiler/global.d.ts (1 errors) ==== + import * as _three from './three'; + + export as namespace THREE; + + declare global { + export const THREE: typeof _three; + ~~~~~ +!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'THREE' must be of type 'typeof import("tests/cases/compiler/global")', but here has type 'typeof import("tests/cases/compiler/three")'. + } + +==== tests/cases/compiler/test.ts (0 errors) ==== + const m = THREE + \ No newline at end of file diff --git a/tests/baselines/reference/checkMergedGlobalUMDSymbol.js b/tests/baselines/reference/checkMergedGlobalUMDSymbol.js new file mode 100644 index 00000000000..c3a3ed6fb8a --- /dev/null +++ b/tests/baselines/reference/checkMergedGlobalUMDSymbol.js @@ -0,0 +1,22 @@ +//// [tests/cases/compiler/checkMergedGlobalUMDSymbol.ts] //// + +//// [three.d.ts] +export namespace THREE { + export class Vector2 {} +} + +//// [global.d.ts] +import * as _three from './three'; + +export as namespace THREE; + +declare global { + export const THREE: typeof _three; +} + +//// [test.ts] +const m = THREE + + +//// [test.js] +var m = THREE; diff --git a/tests/baselines/reference/checkMergedGlobalUMDSymbol.symbols b/tests/baselines/reference/checkMergedGlobalUMDSymbol.symbols new file mode 100644 index 00000000000..72038e964b6 --- /dev/null +++ b/tests/baselines/reference/checkMergedGlobalUMDSymbol.symbols @@ -0,0 +1,28 @@ +=== tests/cases/compiler/three.d.ts === +export namespace THREE { +>THREE : Symbol(THREE, Decl(three.d.ts, 0, 0)) + + export class Vector2 {} +>Vector2 : Symbol(Vector2, Decl(three.d.ts, 0, 24)) +} + +=== tests/cases/compiler/global.d.ts === +import * as _three from './three'; +>_three : Symbol(_three, Decl(global.d.ts, 0, 6)) + +export as namespace THREE; +>THREE : Symbol(THREE, Decl(global.d.ts, 0, 34)) + +declare global { +>global : Symbol(global, Decl(global.d.ts, 2, 26)) + + export const THREE: typeof _three; +>THREE : Symbol("tests/cases/compiler/global", Decl(global.d.ts, 0, 0), Decl(global.d.ts, 5, 14)) +>_three : Symbol(_three, Decl(global.d.ts, 0, 6)) +} + +=== tests/cases/compiler/test.ts === +const m = THREE +>m : Symbol(m, Decl(test.ts, 0, 5)) +>THREE : Symbol("tests/cases/compiler/global", Decl(global.d.ts, 0, 0), Decl(global.d.ts, 5, 14)) + diff --git a/tests/baselines/reference/checkMergedGlobalUMDSymbol.types b/tests/baselines/reference/checkMergedGlobalUMDSymbol.types new file mode 100644 index 00000000000..eeb5ce22501 --- /dev/null +++ b/tests/baselines/reference/checkMergedGlobalUMDSymbol.types @@ -0,0 +1,28 @@ +=== tests/cases/compiler/three.d.ts === +export namespace THREE { +>THREE : typeof THREE + + export class Vector2 {} +>Vector2 : Vector2 +} + +=== tests/cases/compiler/global.d.ts === +import * as _three from './three'; +>_three : typeof _three + +export as namespace THREE; +>THREE : typeof import("tests/cases/compiler/global") + +declare global { +>global : typeof global + + export const THREE: typeof _three; +>THREE : typeof import("tests/cases/compiler/global") +>_three : typeof _three +} + +=== tests/cases/compiler/test.ts === +const m = THREE +>m : typeof import("tests/cases/compiler/global") +>THREE : typeof import("tests/cases/compiler/global") + diff --git a/tests/cases/compiler/checkMergedGlobalUMDSymbol.ts b/tests/cases/compiler/checkMergedGlobalUMDSymbol.ts new file mode 100644 index 00000000000..9edddd7a64b --- /dev/null +++ b/tests/cases/compiler/checkMergedGlobalUMDSymbol.ts @@ -0,0 +1,16 @@ +// @Filename: three.d.ts +export namespace THREE { + export class Vector2 {} +} + +// @Filename: global.d.ts +import * as _three from './three'; + +export as namespace THREE; + +declare global { + export const THREE: typeof _three; +} + +// @Filename: test.ts +const m = THREE