build: support building with TypeScript 4.1 (#39571)

TypeScript 4.1 is now used to build and test within the repository.

PR Close #39571
This commit is contained in:
Charles Lyding 2020-11-04 19:58:29 -05:00 committed by Jessica Janiuk
parent a7e7c211b5
commit 318255a5f8
32 changed files with 93 additions and 69 deletions

View File

@ -49,6 +49,6 @@
"supertest": "^4.0.2", "supertest": "^4.0.2",
"tslint": "^6.1.3", "tslint": "^6.1.3",
"tslint-jasmine-noSkipOrFocus": "^1.0.9", "tslint-jasmine-noSkipOrFocus": "^1.0.9",
"typescript": "^4.0.2" "typescript": "^4.1.2"
} }
} }

View File

@ -2563,10 +2563,10 @@ typedarray-to-buffer@^3.1.5:
dependencies: dependencies:
is-typedarray "^1.0.0" is-typedarray "^1.0.0"
typescript@^4.0.2: typescript@^4.1.2:
version "4.0.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9"
integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ== integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==
undefsafe@^2.0.2: undefsafe@^2.0.2:
version "2.0.2" version "2.0.2"

View File

@ -304,6 +304,6 @@ class FakeModuleFactory extends NgModuleFactory<any> {
function returnPromisesFromSpy(spy: jasmine.Spy): Deferred[] { function returnPromisesFromSpy(spy: jasmine.Spy): Deferred[] {
const deferreds: Deferred[] = []; const deferreds: Deferred[] = [];
spy.and.callFake(() => new Promise((resolve, reject) => deferreds.push({resolve, reject}))); spy.and.callFake(() => new Promise<void>((resolve, reject) => deferreds.push({resolve, reject})));
return deferreds; return deferreds;
} }

View File

@ -13658,7 +13658,7 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript@4.0.5: typescript@4.0.5, typescript@~4.0.2:
version "4.0.5" version "4.0.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389"
integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ== integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==
@ -13668,11 +13668,6 @@ typescript@^3.2.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae"
integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==
typescript@~4.0.2:
version "4.0.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5"
integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==
ua-parser-js@0.7.21: ua-parser-js@0.7.21:
version "0.7.21" version "0.7.21"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777"

View File

@ -18,8 +18,8 @@ export abstract class BaseModule<Data> {
protected git: GitClient, protected config: NgDevConfig<{caretaker: CaretakerConfig}>) {} protected git: GitClient, protected config: NgDevConfig<{caretaker: CaretakerConfig}>) {}
/** Asyncronously retrieve data for the module. */ /** Asyncronously retrieve data for the module. */
protected abstract async retrieveData(): Promise<Data>; protected abstract retrieveData(): Promise<Data>;
/** Print the information discovered for the module to the terminal. */ /** Print the information discovered for the module to the terminal. */
abstract async printToTerminal(): Promise<void>; abstract printToTerminal(): Promise<void>;
} }

View File

@ -83,7 +83,7 @@ export async function execTimed(description: string, func: () => Promise<void>)
} }
export async function nextTick(delay = 1) { export async function nextTick(delay = 1) {
return new Promise((res, rej) => { return new Promise<void>((res, rej) => {
setTimeout(() => { setTimeout(() => {
res(); res();
}, delay); }, delay);

View File

@ -150,7 +150,7 @@
"tsickle": "0.38.1", "tsickle": "0.38.1",
"tslib": "^2.0.0", "tslib": "^2.0.0",
"tslint": "6.1.3", "tslint": "6.1.3",
"typescript": "~4.0.2", "typescript": "~4.1.2",
"xhr2": "0.2.0", "xhr2": "0.2.0",
"yaml": "^1.10.0", "yaml": "^1.10.0",
"yargs": "^16.1.1" "yargs": "^16.1.1"

View File

@ -810,7 +810,7 @@ export class TransitionAnimationEngine {
} }
whenRenderingDone(): Promise<any> { whenRenderingDone(): Promise<any> {
return new Promise(resolve => { return new Promise<void>(resolve => {
if (this.players.length) { if (this.players.length) {
return optimizeGroupPlayer(this.players).onDone(() => resolve()); return optimizeGroupPlayer(this.players).onDone(() => resolve());
} else { } else {

View File

@ -28,7 +28,7 @@
"@angular/compiler-cli": "0.0.0-PLACEHOLDER", "@angular/compiler-cli": "0.0.0-PLACEHOLDER",
"@bazel/typescript": ">=1.0.0", "@bazel/typescript": ">=1.0.0",
"terser": "^4.3.1", "terser": "^4.3.1",
"typescript": ">=4.0 <4.1", "typescript": ">=4.0 <4.2",
"rollup": ">=1.20.0", "rollup": ">=1.20.0",
"rollup-plugin-commonjs": ">=9.0.0", "rollup-plugin-commonjs": ">=9.0.0",
"rollup-plugin-node-resolve": ">=4.2.0", "rollup-plugin-node-resolve": ">=4.2.0",

View File

@ -43,7 +43,7 @@ export class Options {
} }
function writeFile(filename: string, content: string): Promise<any> { function writeFile(filename: string, content: string): Promise<any> {
return new Promise(function(resolve, reject) { return new Promise<void>(function(resolve, reject) {
fs.writeFile(filename, content, (error) => { fs.writeFile(filename, content, (error) => {
if (error) { if (error) {
reject(error); reject(error);

View File

@ -78,7 +78,7 @@ export function findNamespaceOfIdentifier(id: ts.Identifier): ts.Identifier|null
export function findRequireCallReference(id: ts.Identifier, checker: ts.TypeChecker): RequireCall| export function findRequireCallReference(id: ts.Identifier, checker: ts.TypeChecker): RequireCall|
null { null {
const symbol = checker.getSymbolAtLocation(id) || null; const symbol = checker.getSymbolAtLocation(id) || null;
const declaration = symbol && symbol.valueDeclaration; const declaration = symbol?.valueDeclaration ?? symbol?.declarations?.[0];
const initializer = const initializer =
declaration && ts.isVariableDeclaration(declaration) && declaration.initializer || null; declaration && ts.isVariableDeclaration(declaration) && declaration.initializer || null;
return initializer && isRequireCall(initializer) ? initializer : null; return initializer && isRequireCall(initializer) ? initializer : null;

View File

@ -29,7 +29,7 @@
}, },
"peerDependencies": { "peerDependencies": {
"@angular/compiler": "0.0.0-PLACEHOLDER", "@angular/compiler": "0.0.0-PLACEHOLDER",
"typescript": ">=4.0 <4.1" "typescript": ">=4.0 <4.2"
}, },
"engines": { "engines": {
"node": ">=10.0" "node": ">=10.0"

View File

@ -126,9 +126,9 @@ enum TsStructureIsReused {
Completely = 2, Completely = 2,
} }
export function expectCompleteReuse(oldProgram: ts.Program): void { export function expectCompleteReuse(program: ts.Program): void {
// Assert complete reuse using TypeScript's private API. // Assert complete reuse using TypeScript's private API.
expect((oldProgram as any).structureIsReused) expect((program as any).structureIsReused)
.toBe(TsStructureIsReused.Completely, COMPLETE_REUSE_FAILURE_MESSAGE); .toBe(TsStructureIsReused.Completely, COMPLETE_REUSE_FAILURE_MESSAGE);
} }

View File

@ -44,7 +44,7 @@ runInEachFileSystem(() => {
programStrategy.updateFiles( programStrategy.updateFiles(
new Map([[typecheckPath, 'export const VERSION = 2;']]), UpdateMode.Complete); new Map([[typecheckPath, 'export const VERSION = 2;']]), UpdateMode.Complete);
expectCompleteReuse(program); expectCompleteReuse(programStrategy.getProgram());
}); });
it('should have complete reuse if no structural changes are made to input files', () => { it('should have complete reuse if no structural changes are made to input files', () => {
@ -56,7 +56,7 @@ runInEachFileSystem(() => {
programStrategy.updateFiles( programStrategy.updateFiles(
new Map([[mainPath, 'export const STILL_NOT_A_COMPONENT = true;']]), UpdateMode.Complete); new Map([[mainPath, 'export const STILL_NOT_A_COMPONENT = true;']]), UpdateMode.Complete);
expectCompleteReuse(program); expectCompleteReuse(programStrategy.getProgram());
}); });
}); });
}); });

View File

@ -127,7 +127,7 @@ export function performWatchCompilation(host: PerformWatchHost):
// Watch basePath, ignoring .dotfiles // Watch basePath, ignoring .dotfiles
let resolveReadyPromise: () => void; let resolveReadyPromise: () => void;
const readyPromise = new Promise(resolve => resolveReadyPromise = resolve); const readyPromise = new Promise<void>(resolve => resolveReadyPromise = resolve);
// Note: ! is ok as options are filled after the first compilation // Note: ! is ok as options are filled after the first compilation
// Note: ! is ok as resolvedReadyPromise is filled by the previous call // Note: ! is ok as resolvedReadyPromise is filled by the previous call
const fileWatcher = const fileWatcher =

View File

@ -48,6 +48,17 @@ const LOWER_FIELDS = ['useValue', 'useFactory', 'data', 'id', 'loadChildren'];
*/ */
const R3_LOWER_FIELDS = [...LOWER_FIELDS, 'providers', 'imports', 'exports']; const R3_LOWER_FIELDS = [...LOWER_FIELDS, 'providers', 'imports', 'exports'];
/**
* Installs a handler for testing purposes to allow inspection of the temporary program.
*/
let tempProgramHandlerForTest: ((program: ts.Program) => void)|null = null;
export function setTempProgramHandlerForTest(handler: (program: ts.Program) => void): void {
tempProgramHandlerForTest = handler;
}
export function resetTempProgramHandlerForTest(): void {
tempProgramHandlerForTest = null;
}
const emptyModules: NgAnalyzedModules = { const emptyModules: NgAnalyzedModules = {
ngModules: [], ngModules: [],
ngModuleByPipeOrDirective: new Map(), ngModuleByPipeOrDirective: new Map(),
@ -618,6 +629,9 @@ class AngularCompilerProgram implements Program {
} }
const tmpProgram = ts.createProgram(rootNames, this.options, this.hostAdapter, oldTsProgram); const tmpProgram = ts.createProgram(rootNames, this.options, this.hostAdapter, oldTsProgram);
if (tempProgramHandlerForTest !== null) {
tempProgramHandlerForTest(tmpProgram);
}
const sourceFiles: string[] = []; const sourceFiles: string[] = [];
const tsFiles: string[] = []; const tsFiles: string[] = [];
tmpProgram.getSourceFiles().forEach(sf => { tmpProgram.getSourceFiles().forEach(sf => {

View File

@ -1671,7 +1671,7 @@ describe('ngc transformer command-line', () => {
const config = readCommandLineAndConfiguration(['-p', basePath]); const config = readCommandLineAndConfiguration(['-p', basePath]);
const compile = watchMode(config.project, config.options, errorSpy); const compile = watchMode(config.project, config.options, errorSpy);
return new Promise(resolve => { return new Promise<void>(resolve => {
compile.ready(() => { compile.ready(() => {
cb(); cb();

View File

@ -358,7 +358,7 @@ export declare class AnimationEvent {
@Component({ @Component({
selector: 'test', selector: 'test',
template: '<div dir [foo]="invalid && 1"></div>', template: '<div dir [foo]="!!invalid"></div>',
}) })
class TestCmp {} class TestCmp {}
@ -379,7 +379,7 @@ export declare class AnimationEvent {
const diags = env.driveDiagnostics(); const diags = env.driveDiagnostics();
expect(diags.length).toBe(2); expect(diags.length).toBe(2);
expect(diags[0].messageText).toEqual(`Type 'number' is not assignable to type 'string'.`); expect(diags[0].messageText).toEqual(`Type 'boolean' is not assignable to type 'string'.`);
expect(diags[1].messageText) expect(diags[1].messageText)
.toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`); .toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`);
}); });
@ -389,7 +389,7 @@ export declare class AnimationEvent {
const diags = env.driveDiagnostics(); const diags = env.driveDiagnostics();
expect(diags.length).toBe(2); expect(diags.length).toBe(2);
expect(diags[0].messageText).toEqual(`Type 'number' is not assignable to type 'string'.`); expect(diags[0].messageText).toEqual(`Type 'boolean' is not assignable to type 'string'.`);
expect(diags[1].messageText) expect(diags[1].messageText)
.toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`); .toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`);
}); });
@ -411,15 +411,15 @@ export declare class AnimationEvent {
@Component({ @Component({
selector: 'test', selector: 'test',
template: '<div dir [foo]="invalid && nullable"></div>', template: '<div dir [foo]="!!invalid && nullable"></div>',
}) })
class TestCmp { class TestCmp {
nullable: string | null | undefined; nullable: boolean | null | undefined;
} }
@Directive({selector: '[dir]'}) @Directive({selector: '[dir]'})
class TestDir { class TestDir {
@Input() foo: string; @Input() foo: boolean;
} }
@NgModule({ @NgModule({
@ -436,7 +436,7 @@ export declare class AnimationEvent {
const diags = env.driveDiagnostics(); const diags = env.driveDiagnostics();
expect(diags.length).toBe(2); expect(diags.length).toBe(2);
expect((diags[0].messageText as ts.DiagnosticMessageChain).messageText) expect((diags[0].messageText as ts.DiagnosticMessageChain).messageText)
.toEqual(`Type 'string | null | undefined' is not assignable to type 'string'.`); .toEqual(`Type 'boolean | null | undefined' is not assignable to type 'boolean'.`);
expect(diags[1].messageText) expect(diags[1].messageText)
.toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`); .toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`);
}); });
@ -448,7 +448,7 @@ export declare class AnimationEvent {
const diags = env.driveDiagnostics(); const diags = env.driveDiagnostics();
expect(diags.length).toBe(2); expect(diags.length).toBe(2);
expect((diags[0].messageText as ts.DiagnosticMessageChain).messageText) expect((diags[0].messageText as ts.DiagnosticMessageChain).messageText)
.toEqual(`Type 'string | null | undefined' is not assignable to type 'string'.`); .toEqual(`Type 'boolean | null | undefined' is not assignable to type 'boolean'.`);
expect(diags[1].messageText) expect(diags[1].messageText)
.toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`); .toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`);
}); });
@ -470,15 +470,15 @@ export declare class AnimationEvent {
@Component({ @Component({
selector: 'test', selector: 'test',
template: '<div dir [foo]="invalid && user?.name"></div>', template: '<div dir [foo]="!!invalid && user?.isMember"></div>',
}) })
class TestCmp { class TestCmp {
user?: {name: string}; user?: {isMember: boolean};
} }
@Directive({selector: '[dir]'}) @Directive({selector: '[dir]'})
class TestDir { class TestDir {
@Input() foo: string; @Input() foo: boolean;
} }
@NgModule({ @NgModule({
@ -499,7 +499,7 @@ export declare class AnimationEvent {
const diags = env.driveDiagnostics(); const diags = env.driveDiagnostics();
expect(diags.length).toBe(2); expect(diags.length).toBe(2);
expect((diags[0].messageText as ts.DiagnosticMessageChain).messageText) expect((diags[0].messageText as ts.DiagnosticMessageChain).messageText)
.toEqual(`Type 'string | undefined' is not assignable to type 'string'.`); .toEqual(`Type 'boolean | undefined' is not assignable to type 'boolean'.`);
expect(diags[1].messageText) expect(diags[1].messageText)
.toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`); .toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`);
}); });
@ -511,7 +511,7 @@ export declare class AnimationEvent {
const diags = env.driveDiagnostics(); const diags = env.driveDiagnostics();
expect(diags.length).toBe(2); expect(diags.length).toBe(2);
expect((diags[0].messageText as ts.DiagnosticMessageChain).messageText) expect((diags[0].messageText as ts.DiagnosticMessageChain).messageText)
.toEqual(`Type 'string | undefined' is not assignable to type 'string'.`); .toEqual(`Type 'boolean | undefined' is not assignable to type 'boolean'.`);
expect(diags[1].messageText) expect(diags[1].messageText)
.toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`); .toEqual(`Property 'invalid' does not exist on type 'TestCmp'.`);
}); });
@ -2325,7 +2325,8 @@ export declare class AnimationEvent {
env.write('other.ts', `export const VERSION = 2;`); env.write('other.ts', `export const VERSION = 2;`);
env.driveMain(); env.driveMain();
expectCompleteReuse(firstProgram); expectCompleteReuse(env.getTsProgram());
expectCompleteReuse(env.getReuseTsProgram());
}); });
}); });
}); });

View File

@ -13,7 +13,7 @@ import * as ts from 'typescript';
import {formatDiagnostics} from '../../src/perform_compile'; import {formatDiagnostics} from '../../src/perform_compile';
import {CompilerHost, EmitFlags, LazyRoute} from '../../src/transformers/api'; import {CompilerHost, EmitFlags, LazyRoute} from '../../src/transformers/api';
import {createSrcToOutPathMapper} from '../../src/transformers/program'; import {createSrcToOutPathMapper, resetTempProgramHandlerForTest, setTempProgramHandlerForTest} from '../../src/transformers/program';
import {StructureIsReused, tsStructureIsReused} from '../../src/transformers/util'; import {StructureIsReused, tsStructureIsReused} from '../../src/transformers/util';
import {expectNoDiagnosticsInProgram, setup, stripAnsi, TestSupport} from '../test_support'; import {expectNoDiagnosticsInProgram, setup, stripAnsi, TestSupport} from '../test_support';
@ -297,6 +297,17 @@ describe('ng program', () => {
describe( describe(
'verify that program structure is reused within tsc in order to speed up incremental compilation', 'verify that program structure is reused within tsc in order to speed up incremental compilation',
() => { () => {
afterEach(resetTempProgramHandlerForTest);
function captureStructureReuse(compile: () => void): StructureIsReused|null {
let structureReuse: StructureIsReused|null = null;
setTempProgramHandlerForTest(program => {
structureReuse = tsStructureIsReused(program);
});
compile();
return structureReuse;
}
it('should reuse the old ts program completely if nothing changed', () => { it('should reuse the old ts program completely if nothing changed', () => {
testSupport.writeFiles({'src/index.ts': createModuleAndCompSource('main')}); testSupport.writeFiles({'src/index.ts': createModuleAndCompSource('main')});
const host = createWatchModeHost(); const host = createWatchModeHost();
@ -304,8 +315,9 @@ describe('ng program', () => {
// and therefore changes the structure again // and therefore changes the structure again
const p1 = compile(undefined, undefined, undefined, host).program; const p1 = compile(undefined, undefined, undefined, host).program;
const p2 = compile(p1, undefined, undefined, host).program; const p2 = compile(p1, undefined, undefined, host).program;
compile(p2, undefined, undefined, host); const structureReuse =
expect(tsStructureIsReused(p2.getTsProgram())).toBe(StructureIsReused.Completely); captureStructureReuse(() => compile(p2, undefined, undefined, host));
expect(structureReuse).toBe(StructureIsReused.Completely);
}); });
it('should reuse the old ts program completely if a template or a ts file changed', it('should reuse the old ts program completely if a template or a ts file changed',
@ -328,8 +340,9 @@ describe('ng program', () => {
'src/main.html': `Another template`, 'src/main.html': `Another template`,
'src/util.ts': `export const x = 2`, 'src/util.ts': `export const x = 2`,
}); });
compile(p2, undefined, undefined, host); const structureReuse =
expect(tsStructureIsReused(p2.getTsProgram())).toBe(StructureIsReused.Completely); captureStructureReuse(() => compile(p2, undefined, undefined, host));
expect(structureReuse).toBe(StructureIsReused.Completely);
}); });
it('should not reuse the old ts program if an import changed', () => { it('should not reuse the old ts program if an import changed', () => {
@ -348,8 +361,9 @@ describe('ng program', () => {
const p2 = compile(p1, undefined, undefined, host).program; const p2 = compile(p1, undefined, undefined, host).program;
testSupport.writeFiles( testSupport.writeFiles(
{'src/util.ts': `import {Injectable} from '@angular/core'; export const x = 1;`}); {'src/util.ts': `import {Injectable} from '@angular/core'; export const x = 1;`});
compile(p2, undefined, undefined, host); const structureReuse =
expect(tsStructureIsReused(p2.getTsProgram())).toBe(StructureIsReused.SafeModules); captureStructureReuse(() => compile(p2, undefined, undefined, host));
expect(structureReuse).toBe(StructureIsReused.SafeModules);
}); });
}); });
}); });

View File

@ -1048,7 +1048,7 @@ function expectParseTemplateBindingsError(attribute: string, error: string) {
function _parseTemplateBindings(attribute: string, templateUrl: string) { function _parseTemplateBindings(attribute: string, templateUrl: string) {
const match = attribute.match(/^\*(.+)="(.*)"$/); const match = attribute.match(/^\*(.+)="(.*)"$/);
expect(match).toBeTruthy(`failed to extract key and value from ${attribute}`); expect(match).toBeTruthy(`failed to extract key and value from ${attribute}`);
const [_, key, value] = match; const [_, key, value] = match!;
const absKeyOffset = 1; // skip the * prefix const absKeyOffset = 1; // skip the * prefix
const absValueOffset = attribute.indexOf('=') + '="'.length; const absValueOffset = attribute.indexOf('=') + '="'.length;
const parser = createParser(); const parser = createParser();

View File

@ -53,7 +53,7 @@ function getMetaRenderHook(doc: any) {
function getAsyncTitleRenderHook(doc: any) { function getAsyncTitleRenderHook(doc: any) {
return () => { return () => {
// Async set the title as part of the render hook. // Async set the title as part of the render hook.
return new Promise(resolve => { return new Promise<void>(resolve => {
setTimeout(() => { setTimeout(() => {
doc.title = 'AsyncRenderHook'; doc.title = 'AsyncRenderHook';
resolve(); resolve();
@ -64,7 +64,7 @@ function getAsyncTitleRenderHook(doc: any) {
function asyncRejectRenderHook() { function asyncRejectRenderHook() {
return () => { return () => {
return new Promise((_resolve, reject) => { return new Promise<void>((_resolve, reject) => {
setTimeout(() => { setTimeout(() => {
reject('reject'); reject('reject');
}); });

View File

@ -97,7 +97,7 @@ export function validateInjectionKey(
export class Deferred<R> { export class Deferred<R> {
promise: Promise<R>; promise: Promise<R>;
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
resolve!: (value?: R|PromiseLike<R>) => void; resolve!: (value: R|PromiseLike<R>) => void;
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
reject!: (error?: any) => void; reject!: (error?: any) => void;

View File

@ -396,7 +396,7 @@ export class UpgradeAdapter {
this.ngZone.run(() => { this.ngZone.run(() => {
bootstrap(element, [this.ng1Module.name], config!); bootstrap(element, [this.ng1Module.name], config!);
}); });
const ng1BootstrapPromise = new Promise((resolve) => { const ng1BootstrapPromise = new Promise<void>((resolve) => {
if (windowAngular.resumeBootstrap) { if (windowAngular.resumeBootstrap) {
const originalResumeBootstrap: () => void = windowAngular.resumeBootstrap; const originalResumeBootstrap: () => void = windowAngular.resumeBootstrap;
windowAngular.resumeBootstrap = function() { windowAngular.resumeBootstrap = function() {

View File

@ -19,7 +19,7 @@
"mocha": "^3.1.2", "mocha": "^3.1.2",
"mock-require": "3.0.3", "mock-require": "3.0.3",
"promises-aplus-tests": "^2.1.2", "promises-aplus-tests": "^2.1.2",
"typescript": "4.0.2" "typescript": "4.1.2"
}, },
"scripts": { "scripts": {
"closuretest": "./scripts/closure/closure_compiler.sh", "closuretest": "./scripts/closure/closure_compiler.sh",

View File

@ -65,7 +65,7 @@ ifEnvSupports(supportJasmineSpec, () => {
}); });
it('should wait for promise to resolve', () => { it('should wait for promise to resolve', () => {
return new Promise((res, _) => { return new Promise<void>((res, _) => {
setTimeout(() => { setTimeout(() => {
log.push('resolved'); log.push('resolved');
res(); res();

View File

@ -103,7 +103,7 @@ ifEnvSupports('Mocha', function() {
}); });
it('should wait for promise to resolve', () => { it('should wait for promise to resolve', () => {
return new Promise((res, _) => { return new Promise<void>((res, _) => {
setTimeout(() => { setTimeout(() => {
log.push('resolved'); log.push('resolved');
res(); res();

View File

@ -14,6 +14,6 @@
"zone.js": "file:../../../../dist/bin/packages/zone.js/npm_package" "zone.js": "file:../../../../dist/bin/packages/zone.js/npm_package"
}, },
"devDependencies": { "devDependencies": {
"typescript": "~4.0.2" "typescript": "~4.1.2"
} }
} }

View File

@ -98,7 +98,7 @@ describe('AsyncTestZoneSpec', function() {
const atz = Zone.current.fork(testZoneSpec); const atz = Zone.current.fork(testZoneSpec);
atz.run(function() { atz.run(function() {
new Promise((resolve) => { new Promise<void>((resolve) => {
setTimeout(() => { setTimeout(() => {
resolve(); resolve();
}, 10); }, 10);

View File

@ -942,7 +942,7 @@ describe('FakeAsyncTestZoneSpec', () => {
}); });
it('should wait for promise to resolve', () => { it('should wait for promise to resolve', () => {
return new Promise((res, _) => { return new Promise<void>((res, _) => {
setTimeout(() => { setTimeout(() => {
log.push('resolved'); log.push('resolved');
res(); res();

View File

@ -3786,10 +3786,10 @@ typedarray-to-buffer@^3.1.5:
dependencies: dependencies:
is-typedarray "^1.0.0" is-typedarray "^1.0.0"
typescript@4.0.2: typescript@4.1.2:
version "4.0.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9"
integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ== integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==
underscore@~1.8.3: underscore@~1.8.3:
version "1.8.3" version "1.8.3"

View File

@ -33,7 +33,7 @@
"chai": "^4.1.2", "chai": "^4.1.2",
"jasmine": "^3.1.0", "jasmine": "^3.1.0",
"source-map-support": "^0.5.9", "source-map-support": "^0.5.9",
"typescript": "4.0.2" "typescript": "4.1.2"
}, },
"repository": {}, "repository": {},
"keywords": [ "keywords": [
@ -51,4 +51,4 @@
"url": "https://github.com/angular/angular/issues" "url": "https://github.com/angular/angular/issues"
}, },
"homepage": "https://github.com/angular/angular/tools/ts-api-guardian" "homepage": "https://github.com/angular/angular/tools/ts-api-guardian"
} }

View File

@ -15621,10 +15621,10 @@ typescript@~3.7.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae"
integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==
typescript@~4.0.2: typescript@~4.1.2:
version "4.0.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9"
integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ== integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==
uglify-js@^1.3.3: uglify-js@^1.3.3:
version "1.3.5" version "1.3.5"