From 57a8ee1507d2e14f3d7efd8bd53ff049e573afbf Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Sat, 27 Apr 2019 16:47:27 -0700 Subject: [PATCH] Fix binder performance regression --- src/compiler/checker.ts | 18 +++++++++++++++--- .../reference/globalThisCollision.errors.txt | 7 +++++++ .../reference/globalThisCollision.symbols | 4 ++++ .../reference/globalThisCollision.types | 4 ++++ .../conformance/es2019/globalThisCollision.ts | 5 +++++ 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/globalThisCollision.errors.txt create mode 100644 tests/baselines/reference/globalThisCollision.symbols create mode 100644 tests/baselines/reference/globalThisCollision.types create mode 100644 tests/cases/conformance/es2019/globalThisCollision.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8ee0a4c051996..33d2dd73876b8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -94,8 +94,6 @@ namespace ts { const globalThisSymbol = createSymbol(SymbolFlags.Module, "globalThis" as __String, CheckFlags.Readonly); globalThisSymbol.exports = globals; - globalThisSymbol.valueDeclaration = createNode(SyntaxKind.Identifier) as Identifier; - (globalThisSymbol.valueDeclaration as Identifier).escapedText = "globalThis" as __String; globals.set(globalThisSymbol.escapedName, globalThisSymbol); const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as __String); @@ -926,7 +924,12 @@ namespace ts { recordMergedSymbol(target, source); } else if (target.flags & SymbolFlags.NamespaceModule) { - error(getNameOfDeclaration(source.declarations[0]), Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); + // Do not report an error when merging `var globalThis` with the built-in `globalThis`, + // as we will already report a "Declaration name conflicts..." error, and this error + // won't make much sense. + if (target !== globalThisSymbol) { + error(getNameOfDeclaration(source.declarations[0]), Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); + } } else { // error const isEitherEnum = !!(target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum); @@ -30456,6 +30459,14 @@ namespace ts { continue; } if (!isExternalOrCommonJsModule(file)) { + // It is an error for a non-external-module (i.e. script) to declare its own `globalThis`. + // We can't use `builtinGlobals` for this due to synthetic expando-namespace generation in JS files. + const fileGlobalThisSymbol = file.locals!.get("globalThis" as __String); + if (fileGlobalThisSymbol) { + for (const declaration of fileGlobalThisSymbol.declarations) { + diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis")); + } + } mergeSymbolTable(globals, file.locals!); } if (file.jsGlobalAugmentations) { @@ -30501,6 +30512,7 @@ namespace ts { getSymbolLinks(undefinedSymbol).type = undefinedWideningType; getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as __String, /*arity*/ 0, /*reportErrors*/ true); getSymbolLinks(unknownSymbol).type = errorType; + getSymbolLinks(globalThisSymbol).type = createObjectType(ObjectFlags.Anonymous, globalThisSymbol); // Initialize special types globalArrayType = getGlobalType("Array" as __String, /*arity*/ 1, /*reportErrors*/ true); diff --git a/tests/baselines/reference/globalThisCollision.errors.txt b/tests/baselines/reference/globalThisCollision.errors.txt new file mode 100644 index 0000000000000..ea0fb9d9f434b --- /dev/null +++ b/tests/baselines/reference/globalThisCollision.errors.txt @@ -0,0 +1,7 @@ +tests/cases/conformance/es2019/globalThisCollision.js(1,5): error TS2397: Declaration name conflicts with built-in global identifier 'globalThis'. + + +==== tests/cases/conformance/es2019/globalThisCollision.js (1 errors) ==== + var globalThis; + ~~~~~~~~~~ +!!! error TS2397: Declaration name conflicts with built-in global identifier 'globalThis'. \ No newline at end of file diff --git a/tests/baselines/reference/globalThisCollision.symbols b/tests/baselines/reference/globalThisCollision.symbols new file mode 100644 index 0000000000000..088357fd537db --- /dev/null +++ b/tests/baselines/reference/globalThisCollision.symbols @@ -0,0 +1,4 @@ +=== tests/cases/conformance/es2019/globalThisCollision.js === +var globalThis; +>globalThis : Symbol(globalThis, Decl(globalThisCollision.js, 0, 3)) + diff --git a/tests/baselines/reference/globalThisCollision.types b/tests/baselines/reference/globalThisCollision.types new file mode 100644 index 0000000000000..476533be18cae --- /dev/null +++ b/tests/baselines/reference/globalThisCollision.types @@ -0,0 +1,4 @@ +=== tests/cases/conformance/es2019/globalThisCollision.js === +var globalThis; +>globalThis : any + diff --git a/tests/cases/conformance/es2019/globalThisCollision.ts b/tests/cases/conformance/es2019/globalThisCollision.ts new file mode 100644 index 0000000000000..d73a7b6217e64 --- /dev/null +++ b/tests/cases/conformance/es2019/globalThisCollision.ts @@ -0,0 +1,5 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @filename: globalThisCollision.js +var globalThis; \ No newline at end of file