Only apply global augmentations before globals are available (#21563) (#21595)

* Only apply global augmentations before globals are available

* Add detailed comment explaining the split of global/nonglobal augmentations

* Remove trailing whitespace
This commit is contained in:
Wesley Wigham
2018-02-05 11:01:05 -08:00
committed by GitHub
parent 3305baf5eb
commit 737fb7f9b5
5 changed files with 222 additions and 1 deletions

View File

@@ -25201,11 +25201,18 @@ namespace ts {
}
}
// We do global augmentations seperately from module augmentations (and before creating global types) because they
// 1. Affect global types. We won't have the correct global types until global augmentations are merged. Also,
// 2. Module augmentation instantiation requires creating the type of a module, which, in turn, can require
// checking for an export or property on the module (if export=) which, in turn, can fall back to the
// apparent type of the module - either globalObjectType or globalFunctionType - which wouldn't exist if we
// did module augmentations prior to finalizing the global types.
if (augmentations) {
// merge module augmentations.
// merge _global_ module augmentations.
// this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed
for (const list of augmentations) {
for (const augmentation of list) {
if (!isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration)) continue;
mergeModuleAugmentation(augmentation);
}
}
@@ -25237,6 +25244,17 @@ namespace ts {
globalReadonlyArrayType = <GenericType>getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1);
anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType;
globalThisType = <GenericType>getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1);
if (augmentations) {
// merge _nonglobal_ module augmentations.
// this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed
for (const list of augmentations) {
for (const augmentation of list) {
if (isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration)) continue;
mergeModuleAugmentation(augmentation);
}
}
}
}
function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) {

View File

@@ -0,0 +1,43 @@
//// [tests/cases/compiler/moduleAugmentationDuringSyntheticDefaultCheck.ts] ////
//// [index.d.ts]
declare function moment(): moment.Moment;
declare namespace moment {
interface Moment extends Object {
valueOf(): number;
}
}
export = moment;
//// [index.d.ts]
import * as moment from 'moment';
export = moment;
declare module "moment" {
interface Moment {
tz(): string;
}
}
//// [idx.ts]
import * as _moment from "moment";
declare module "moment" {
interface Moment {
strftime(pattern: string): string;
}
}
declare module "moment-timezone" {
interface Moment {
strftime(pattern: string): string;
}
}
//// [idx.test.ts]
/// <reference path="./idx" />
import moment = require("moment-timezone");
//// [idx.js]
"use strict";
exports.__esModule = true;
//// [idx.test.js]
"use strict";
/// <reference path="./idx" />
exports.__esModule = true;

View File

@@ -0,0 +1,63 @@
=== tests/cases/compiler/idx.test.ts ===
/// <reference path="./idx" />
import moment = require("moment-timezone");
>moment : Symbol(moment, Decl(idx.test.ts, 0, 0))
=== tests/cases/compiler/node_modules/moment/index.d.ts ===
declare function moment(): moment.Moment;
>moment : Symbol(moment, Decl(index.d.ts, 0, 0), Decl(index.d.ts, 0, 41), Decl(idx.ts, 0, 34), Decl(index.d.ts, 1, 16))
>moment : Symbol(moment, Decl(index.d.ts, 0, 0), Decl(index.d.ts, 0, 41))
>Moment : Symbol(Moment, Decl(index.d.ts, 1, 26))
declare namespace moment {
>moment : Symbol(moment, Decl(index.d.ts, 0, 0), Decl(index.d.ts, 0, 41), Decl(idx.ts, 0, 34), Decl(index.d.ts, 1, 16))
interface Moment extends Object {
>Moment : Symbol(Moment, Decl(index.d.ts, 1, 26), Decl(idx.ts, 1, 25), Decl(idx.ts, 6, 34), Decl(index.d.ts, 2, 25))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
valueOf(): number;
>valueOf : Symbol(Moment.valueOf, Decl(index.d.ts, 2, 35))
}
}
export = moment;
>moment : Symbol(moment, Decl(index.d.ts, 0, 0), Decl(index.d.ts, 0, 41))
=== tests/cases/compiler/node_modules/moment-timezone/index.d.ts ===
import * as moment from 'moment';
>moment : Symbol(moment, Decl(index.d.ts, 0, 6))
export = moment;
>moment : Symbol(moment, Decl(index.d.ts, 0, 6))
declare module "moment" {
interface Moment {
>Moment : Symbol(Moment, Decl(index.d.ts, 1, 26), Decl(idx.ts, 1, 25), Decl(idx.ts, 6, 34), Decl(index.d.ts, 2, 25))
tz(): string;
>tz : Symbol(Moment.tz, Decl(index.d.ts, 3, 22))
}
}
=== tests/cases/compiler/idx.ts ===
import * as _moment from "moment";
>_moment : Symbol(_moment, Decl(idx.ts, 0, 6))
declare module "moment" {
interface Moment {
>Moment : Symbol(Moment, Decl(index.d.ts, 1, 26), Decl(idx.ts, 1, 25), Decl(idx.ts, 6, 34), Decl(index.d.ts, 2, 25))
strftime(pattern: string): string;
>strftime : Symbol(Moment.strftime, Decl(idx.ts, 2, 22), Decl(idx.ts, 7, 22))
>pattern : Symbol(pattern, Decl(idx.ts, 3, 17))
}
}
declare module "moment-timezone" {
interface Moment {
>Moment : Symbol(Moment, Decl(index.d.ts, 1, 26), Decl(idx.ts, 1, 25), Decl(idx.ts, 6, 34), Decl(index.d.ts, 2, 25))
strftime(pattern: string): string;
>strftime : Symbol(Moment.strftime, Decl(idx.ts, 2, 22), Decl(idx.ts, 7, 22))
>pattern : Symbol(pattern, Decl(idx.ts, 8, 17))
}
}

View File

@@ -0,0 +1,63 @@
=== tests/cases/compiler/idx.test.ts ===
/// <reference path="./idx" />
import moment = require("moment-timezone");
>moment : { default: () => moment.Moment; }
=== tests/cases/compiler/node_modules/moment/index.d.ts ===
declare function moment(): moment.Moment;
>moment : () => Moment
>moment : any
>Moment : Moment
declare namespace moment {
>moment : () => Moment
interface Moment extends Object {
>Moment : Moment
>Object : Object
valueOf(): number;
>valueOf : () => number
}
}
export = moment;
>moment : () => Moment
=== tests/cases/compiler/node_modules/moment-timezone/index.d.ts ===
import * as moment from 'moment';
>moment : { default: () => moment.Moment; }
export = moment;
>moment : { default: () => moment.Moment; }
declare module "moment" {
interface Moment {
>Moment : Moment
tz(): string;
>tz : () => string
}
}
=== tests/cases/compiler/idx.ts ===
import * as _moment from "moment";
>_moment : { default: () => _moment.Moment; }
declare module "moment" {
interface Moment {
>Moment : Moment
strftime(pattern: string): string;
>strftime : { (pattern: string): string; (pattern: string): string; }
>pattern : string
}
}
declare module "moment-timezone" {
interface Moment {
>Moment : Moment
strftime(pattern: string): string;
>strftime : { (pattern: string): string; (pattern: string): string; }
>pattern : string
}
}

View File

@@ -0,0 +1,34 @@
// @noImplicitReferences: true
// @esModuleInterop: true
// @filename: node_modules/moment/index.d.ts
declare function moment(): moment.Moment;
declare namespace moment {
interface Moment extends Object {
valueOf(): number;
}
}
export = moment;
// @filename: node_modules/moment-timezone/index.d.ts
import * as moment from 'moment';
export = moment;
declare module "moment" {
interface Moment {
tz(): string;
}
}
// @filename: idx.ts
import * as _moment from "moment";
declare module "moment" {
interface Moment {
strftime(pattern: string): string;
}
}
declare module "moment-timezone" {
interface Moment {
strftime(pattern: string): string;
}
}
// @filename: idx.test.ts
/// <reference path="./idx" />
import moment = require("moment-timezone");