Skip ambient modules in globalThis (#48938)

* Skip ambient modules in globalThis

Previously, globalThis mistakenly included ambient modules, even though
these are not values:

```ts
declare module "ambientModule" {
  export type typ = 1
  export var val: typ
}
type Oops = (typeof globalThis)[\"ambientModule\"]
```

This PR adds ambient modules to the kinds of things that are skipped
when constructing `globalThis`' properties, along with block-scoped
variables.

* Skip only modules with every declaration ambient

The modules are required to have at least one declaration so that our
treatment of `globalThis` stays the same, and
`globalThis.globalThis.globalThis` remains legal.
This commit is contained in:
Nathan Shively-Sanders 2022-05-05 09:33:32 -07:00 committed by GitHub
parent 7d60dc1f5d
commit 46e8306050
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 1 deletions

View File

@ -11504,7 +11504,7 @@ namespace ts {
if (symbol === globalThisSymbol) {
const varsOnly = new Map<string, Symbol>() as SymbolTable;
members.forEach(p => {
if (!(p.flags & SymbolFlags.BlockScoped)) {
if (!(p.flags & SymbolFlags.BlockScoped) && !(p.flags & SymbolFlags.ValueModule && p.declarations?.length && every(p.declarations, isAmbientModule))) {
varsOnly.set(p.escapedName, p);
}
});

View File

@ -0,0 +1,21 @@
tests/cases/conformance/es2019/globalThisAmbientModules.ts(8,39): error TS2339: Property '"ambientModule"' does not exist on type 'typeof globalThis'.
tests/cases/conformance/es2019/globalThisAmbientModules.ts(11,33): error TS2339: Property '"ambientModule"' does not exist on type 'typeof globalThis'.
==== tests/cases/conformance/es2019/globalThisAmbientModules.ts (2 errors) ====
declare module "ambientModule" {
export type typ = 1
export var val: typ
}
namespace valueModule { export var val = 1 }
namespace namespaceModule { export type typ = 1 }
// should error
type GlobalBad1 = (typeof globalThis)["\"ambientModule\""]
~~~~~~~~~~~~~~~~~~~
!!! error TS2339: Property '"ambientModule"' does not exist on type 'typeof globalThis'.
type GlobalOk1 = (typeof globalThis)["valueModule"]
type GlobalOk2 = globalThis.namespaceModule.typ
const bad1: (typeof globalThis)["\"ambientModule\""] = 'ambientModule'
~~~~~~~~~~~~~~~~~~~
!!! error TS2339: Property '"ambientModule"' does not exist on type 'typeof globalThis'.

View File

@ -0,0 +1,20 @@
//// [globalThisAmbientModules.ts]
declare module "ambientModule" {
export type typ = 1
export var val: typ
}
namespace valueModule { export var val = 1 }
namespace namespaceModule { export type typ = 1 }
// should error
type GlobalBad1 = (typeof globalThis)["\"ambientModule\""]
type GlobalOk1 = (typeof globalThis)["valueModule"]
type GlobalOk2 = globalThis.namespaceModule.typ
const bad1: (typeof globalThis)["\"ambientModule\""] = 'ambientModule'
//// [globalThisAmbientModules.js]
var valueModule;
(function (valueModule) {
valueModule.val = 1;
})(valueModule || (valueModule = {}));
var bad1 = 'ambientModule';

View File

@ -0,0 +1,38 @@
=== tests/cases/conformance/es2019/globalThisAmbientModules.ts ===
declare module "ambientModule" {
>"ambientModule" : Symbol("ambientModule", Decl(globalThisAmbientModules.ts, 0, 0))
export type typ = 1
>typ : Symbol(typ, Decl(globalThisAmbientModules.ts, 0, 32))
export var val: typ
>val : Symbol(val, Decl(globalThisAmbientModules.ts, 2, 14))
>typ : Symbol(typ, Decl(globalThisAmbientModules.ts, 0, 32))
}
namespace valueModule { export var val = 1 }
>valueModule : Symbol(valueModule, Decl(globalThisAmbientModules.ts, 3, 1))
>val : Symbol(val, Decl(globalThisAmbientModules.ts, 4, 34))
namespace namespaceModule { export type typ = 1 }
>namespaceModule : Symbol(namespaceModule, Decl(globalThisAmbientModules.ts, 4, 44))
>typ : Symbol(typ, Decl(globalThisAmbientModules.ts, 5, 27))
// should error
type GlobalBad1 = (typeof globalThis)["\"ambientModule\""]
>GlobalBad1 : Symbol(GlobalBad1, Decl(globalThisAmbientModules.ts, 5, 49))
>globalThis : Symbol(globalThis)
type GlobalOk1 = (typeof globalThis)["valueModule"]
>GlobalOk1 : Symbol(GlobalOk1, Decl(globalThisAmbientModules.ts, 7, 58))
>globalThis : Symbol(globalThis)
type GlobalOk2 = globalThis.namespaceModule.typ
>GlobalOk2 : Symbol(GlobalOk2, Decl(globalThisAmbientModules.ts, 8, 51))
>globalThis : Symbol(globalThis)
>namespaceModule : Symbol(namespaceModule, Decl(globalThisAmbientModules.ts, 4, 44))
>typ : Symbol(namespaceModule.typ, Decl(globalThisAmbientModules.ts, 5, 27))
const bad1: (typeof globalThis)["\"ambientModule\""] = 'ambientModule'
>bad1 : Symbol(bad1, Decl(globalThisAmbientModules.ts, 10, 5))
>globalThis : Symbol(globalThis)

View File

@ -0,0 +1,37 @@
=== tests/cases/conformance/es2019/globalThisAmbientModules.ts ===
declare module "ambientModule" {
>"ambientModule" : typeof import("ambientModule")
export type typ = 1
>typ : 1
export var val: typ
>val : 1
}
namespace valueModule { export var val = 1 }
>valueModule : typeof valueModule
>val : number
>1 : 1
namespace namespaceModule { export type typ = 1 }
>typ : 1
// should error
type GlobalBad1 = (typeof globalThis)["\"ambientModule\""]
>GlobalBad1 : any
>globalThis : typeof globalThis
type GlobalOk1 = (typeof globalThis)["valueModule"]
>GlobalOk1 : typeof valueModule
>globalThis : typeof globalThis
type GlobalOk2 = globalThis.namespaceModule.typ
>GlobalOk2 : 1
>globalThis : any
>namespaceModule : any
const bad1: (typeof globalThis)["\"ambientModule\""] = 'ambientModule'
>bad1 : any
>globalThis : typeof globalThis
>'ambientModule' : "ambientModule"

View File

@ -0,0 +1,11 @@
declare module "ambientModule" {
export type typ = 1
export var val: typ
}
namespace valueModule { export var val = 1 }
namespace namespaceModule { export type typ = 1 }
// should error
type GlobalBad1 = (typeof globalThis)["\"ambientModule\""]
type GlobalOk1 = (typeof globalThis)["valueModule"]
type GlobalOk2 = globalThis.namespaceModule.typ
const bad1: (typeof globalThis)["\"ambientModule\""] = 'ambientModule'