Fix crash on umd and module merge, allow umds to be accessed when merged with a non-UMD symbol

This commit is contained in:
Wesley Wigham 2018-11-30 15:55:20 -08:00
parent 3d8668c3d4
commit d92771d61a
6 changed files with 126 additions and 19 deletions

View file

@ -1569,7 +1569,8 @@ namespace ts {
// If we're in an external module, we can't reference value symbols created from UMD export declarations
if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value && !(originalLocation!.flags & NodeFlags.JSDoc)) {
if (some(result.declarations, d => isNamespaceExportDeclaration(d) || isSourceFile(d) && !!d.symbol.globalExports)) {
const merged = getMergedSymbol(result);
if (length(merged.declarations) && every(merged.declarations, d => isNamespaceExportDeclaration(d) || isSourceFile(d) && !!d.symbol.globalExports)) {
error(errorLocation!, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeLeadingUnderscores(name)); // TODO: GH#18217
}
}
@ -5322,12 +5323,11 @@ namespace ts {
return anyType;
}
// Handle export default expressions
if (isSourceFile(declaration)) {
const jsonSourceFile = cast(declaration, isJsonSourceFile);
if (!jsonSourceFile.statements.length) {
if (isSourceFile(declaration) && isJsonSourceFile(declaration)) {
if (!declaration.statements.length) {
return emptyObjectType;
}
const type = getWidenedLiteralType(checkExpression(jsonSourceFile.statements[0].expression));
const type = getWidenedLiteralType(checkExpression(declaration.statements[0].expression));
if (type.flags & TypeFlags.Object) {
return getRegularTypeOfObjectLiteral(type);
}
@ -5352,7 +5352,8 @@ namespace ts {
|| isClassDeclaration(declaration)
|| isFunctionDeclaration(declaration)
|| (isMethodDeclaration(declaration) && !isObjectLiteralMethod(declaration))
|| isMethodSignature(declaration)) {
|| isMethodSignature(declaration)
|| isSourceFile(declaration)) {
// Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty`
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
return getTypeOfFuncClassEnumModule(symbol);

View file

@ -1,10 +1,6 @@
/a.d.ts(3,14): error TS2451: Cannot redeclare block-scoped variable 'conflict'.
/b.ts(6,22): error TS2451: Cannot redeclare block-scoped variable 'conflict'.
/b.ts(12,18): error TS2451: Cannot redeclare block-scoped variable 'conflict'.
/b.ts(15,1): error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
/b.ts(15,7): error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
/b.ts(15,13): error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
/b.ts(15,19): error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
==== /a.d.ts (1 errors) ====
@ -16,7 +12,7 @@
!!! related TS6203 /b.ts:6:22: 'conflict' was also declared here.
!!! related TS6204 /b.ts:12:18: and here.
==== /b.ts (6 errors) ====
==== /b.ts (2 errors) ====
import * as a2 from "./a";
declare global {
@ -38,13 +34,5 @@
}
a.x + a.y + a.z + a.conflict;
~
!!! error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
~
!!! error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
~
!!! error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
~
!!! error TS2686: 'a' refers to a UMD global, but the current file is a module. Consider adding an import instead.
a2.x + a2.y + a2.z + a2.conflict;

View file

@ -0,0 +1,27 @@
//// [tests/cases/compiler/umdGlobalAugmentationNoCrash.ts] ////
//// [global.d.ts]
declare global {
const React: typeof import("./module");
}
export {};
//// [module.d.ts]
export as namespace React;
export function foo(): string;
//// [some_module.ts]
export {}
React.foo;
//// [emits.ts]
console.log("hello");
React.foo;
//// [some_module.js]
React.foo;
//// [emits.js]
"use strict";
console.log("hello");
React.foo;

View file

@ -0,0 +1,34 @@
=== tests/cases/compiler/global.d.ts ===
declare global {
>global : Symbol(global, Decl(global.d.ts, 0, 0))
const React: typeof import("./module");
>React : Symbol("tests/cases/compiler/module", Decl(module.d.ts, 0, 0), Decl(global.d.ts, 1, 9))
}
export {};
=== tests/cases/compiler/module.d.ts ===
export as namespace React;
>React : Symbol(React, Decl(module.d.ts, 0, 0))
export function foo(): string;
>foo : Symbol(foo, Decl(module.d.ts, 0, 26))
=== tests/cases/compiler/some_module.ts ===
export {}
React.foo;
>React.foo : Symbol(foo, Decl(module.d.ts, 0, 26))
>React : Symbol("tests/cases/compiler/module", Decl(module.d.ts, 0, 0), Decl(global.d.ts, 1, 9))
>foo : Symbol(foo, Decl(module.d.ts, 0, 26))
=== tests/cases/compiler/emits.ts ===
console.log("hello");
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
React.foo;
>React.foo : Symbol(foo, Decl(module.d.ts, 0, 26))
>React : Symbol("tests/cases/compiler/module", Decl(module.d.ts, 0, 0), Decl(global.d.ts, 1, 9))
>foo : Symbol(foo, Decl(module.d.ts, 0, 26))

View file

@ -0,0 +1,36 @@
=== tests/cases/compiler/global.d.ts ===
declare global {
>global : typeof global
const React: typeof import("./module");
>React : typeof import("tests/cases/compiler/module")
}
export {};
=== tests/cases/compiler/module.d.ts ===
export as namespace React;
>React : typeof import("tests/cases/compiler/module")
export function foo(): string;
>foo : () => string
=== tests/cases/compiler/some_module.ts ===
export {}
React.foo;
>React.foo : () => string
>React : typeof import("tests/cases/compiler/module")
>foo : () => string
=== tests/cases/compiler/emits.ts ===
console.log("hello");
>console.log("hello") : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>"hello" : "hello"
React.foo;
>React.foo : () => string
>React : typeof import("tests/cases/compiler/module")
>foo : () => string

View file

@ -0,0 +1,21 @@
// @strict: true
// @module: esnext
// @moduleResolution: node
// @target: es2018
// @filename: global.d.ts
declare global {
const React: typeof import("./module");
}
export {};
// @filename: module.d.ts
export as namespace React;
export function foo(): string;
// @filename: some_module.ts
export {}
React.foo;
// @filename: emits.ts
console.log("hello");
React.foo;