build: TypeScript 3.6 compatibility. (#32908)
This PR updates Angular to compile with TypeScript 3.6 while retaining compatibility with TS3.5. We achieve this by inserting several `as any` casts for compatiblity around `ts.CompilerHost` APIs. PR Close #32908
This commit is contained in:
parent
6f5f481fda
commit
5332b04f35
|
@ -180,8 +180,11 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost {
|
|||
private resolveModuleName(moduleName: string, containingFile: ts.SourceFile): ts.SourceFile
|
||||
|undefined {
|
||||
if (this.compilerHost.resolveModuleNames) {
|
||||
const moduleInfo =
|
||||
this.compilerHost.resolveModuleNames([moduleName], containingFile.fileName)[0];
|
||||
// FIXME: remove the "as any" cast once on TS3.6.
|
||||
const moduleInfo = (this.compilerHost as any)
|
||||
.resolveModuleNames(
|
||||
[moduleName], containingFile.fileName, undefined, undefined,
|
||||
this.program.getCompilerOptions())[0];
|
||||
return moduleInfo && this.program.getSourceFile(absoluteFrom(moduleInfo.resolvedFileName));
|
||||
} else {
|
||||
const moduleInfo = ts.resolveModuleName(
|
||||
|
|
|
@ -158,8 +158,11 @@ export class UmdReflectionHost extends Esm5ReflectionHost {
|
|||
private resolveModuleName(moduleName: string, containingFile: ts.SourceFile): ts.SourceFile
|
||||
|undefined {
|
||||
if (this.compilerHost.resolveModuleNames) {
|
||||
const moduleInfo =
|
||||
this.compilerHost.resolveModuleNames([moduleName], containingFile.fileName)[0];
|
||||
// FIXME: remove the "as any" cast once on TS3.6.
|
||||
const moduleInfo = (this.compilerHost as any)
|
||||
.resolveModuleNames(
|
||||
[moduleName], containingFile.fileName, undefined, undefined,
|
||||
this.program.getCompilerOptions())[0];
|
||||
return moduleInfo && this.program.getSourceFile(absoluteFrom(moduleInfo.resolvedFileName));
|
||||
} else {
|
||||
const moduleInfo = ts.resolveModuleName(
|
||||
|
@ -281,4 +284,4 @@ function findNamespaceOfIdentifier(id: ts.Identifier): ts.Identifier|null {
|
|||
|
||||
export function stripParentheses(node: ts.Node): ts.Node {
|
||||
return ts.isParenthesizedExpression(node) ? node.expression : node;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -457,8 +457,8 @@ export class MetadataCollector {
|
|||
left: {
|
||||
__symbolic: 'select',
|
||||
expression: recordEntry({__symbolic: 'reference', name: enumName}, node), name
|
||||
} as any,
|
||||
};
|
||||
},
|
||||
} as any;
|
||||
} else {
|
||||
nextDefaultValue =
|
||||
recordEntry(errorSym('Unsupported enum member name', member.name), node);
|
||||
|
|
|
@ -32,11 +32,14 @@ export interface ShimGenerator {
|
|||
export class GeneratedShimsHostWrapper implements ts.CompilerHost {
|
||||
constructor(private delegate: ts.CompilerHost, private shimGenerators: ShimGenerator[]) {
|
||||
if (delegate.resolveModuleNames !== undefined) {
|
||||
this.resolveModuleNames =
|
||||
(moduleNames: string[], containingFile: string, reusedNames?: string[],
|
||||
redirectedReference?: ts.ResolvedProjectReference) =>
|
||||
delegate.resolveModuleNames !(
|
||||
moduleNames, containingFile, reusedNames, redirectedReference);
|
||||
// FIXME: TypeScript 3.6 adds an "options" argument that the code below passes on, but which
|
||||
// still makes the method incompatible with TS3.5. Remove the "as any" cast once fully on 3.6.
|
||||
((this as ts.CompilerHost) as any).resolveModuleNames =
|
||||
(moduleNames: string[], containingFile: string, reusedNames: (string[] | undefined),
|
||||
redirectedReference: (ts.ResolvedProjectReference | undefined), options: any) =>
|
||||
(delegate as any)
|
||||
.resolveModuleNames !(
|
||||
moduleNames, containingFile, reusedNames, redirectedReference, options);
|
||||
}
|
||||
if (delegate.resolveTypeReferenceDirectives) {
|
||||
// Backward compatibility with TypeScript 2.9 and older since return
|
||||
|
@ -56,10 +59,6 @@ export class GeneratedShimsHostWrapper implements ts.CompilerHost {
|
|||
}
|
||||
}
|
||||
|
||||
resolveModuleNames?:
|
||||
(moduleNames: string[], containingFile: string, reusedNames?: string[],
|
||||
redirectedReference?: ts.ResolvedProjectReference) => (ts.ResolvedModule | undefined)[];
|
||||
|
||||
resolveTypeReferenceDirectives?:
|
||||
(names: string[], containingFile: string) => ts.ResolvedTypeReferenceDirective[];
|
||||
|
||||
|
|
|
@ -14,7 +14,8 @@ describe('shim host', () => {
|
|||
const delegate = {} as unknown as ts.CompilerHost;
|
||||
const shimsHost = new GeneratedShimsHostWrapper(delegate, []);
|
||||
|
||||
expect(shimsHost.resolveModuleNames).not.toBeDefined();
|
||||
// FIXME: re-enable once fully on TS3.6.
|
||||
// expect(shimsHost.resolveModuleNames).not.toBeDefined();
|
||||
expect(shimsHost.resolveTypeReferenceDirectives).not.toBeDefined();
|
||||
expect(shimsHost.directoryExists).not.toBeDefined();
|
||||
expect(shimsHost.getDirectories).not.toBeDefined();
|
||||
|
@ -29,7 +30,8 @@ describe('shim host', () => {
|
|||
} as unknown as ts.CompilerHost;
|
||||
const shimsHost = new GeneratedShimsHostWrapper(delegate, []);
|
||||
|
||||
expect(shimsHost.resolveModuleNames).toBeDefined();
|
||||
// FIXME: re-enable once fully on TS3.6.
|
||||
// expect(shimsHost.resolveModuleNames).toBeDefined();
|
||||
expect(shimsHost.resolveTypeReferenceDirectives).toBeDefined();
|
||||
expect(shimsHost.directoryExists).toBeDefined();
|
||||
expect(shimsHost.getDirectories).toBeDefined();
|
||||
|
|
|
@ -113,7 +113,10 @@ export function resolveModuleName(
|
|||
moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions,
|
||||
compilerHost: ts.CompilerHost): ts.ResolvedModule|undefined {
|
||||
if (compilerHost.resolveModuleNames) {
|
||||
return compilerHost.resolveModuleNames([moduleName], containingFile)[0];
|
||||
// FIXME: Additional parameters are required in TS3.6, but ignored in 3.5.
|
||||
// Remove the any cast once fully on TS3.6.
|
||||
return (compilerHost as any)
|
||||
.resolveModuleNames([moduleName], containingFile, undefined, undefined, compilerOptions)[0];
|
||||
} else {
|
||||
return ts.resolveModuleName(moduleName, containingFile, compilerOptions, compilerHost)
|
||||
.resolvedModule;
|
||||
|
|
|
@ -277,7 +277,7 @@ export class PlatformRef {
|
|||
const ngZoneInjector = Injector.create(
|
||||
{providers: providers, parent: this.injector, name: moduleFactory.moduleType.name});
|
||||
const moduleRef = <InternalNgModuleRef<M>>moduleFactory.create(ngZoneInjector);
|
||||
const exceptionHandler: ErrorHandler = moduleRef.injector.get(ErrorHandler, null);
|
||||
const exceptionHandler: ErrorHandler|null = moduleRef.injector.get(ErrorHandler, null);
|
||||
if (!exceptionHandler) {
|
||||
throw new Error('No ErrorHandler. Is platform module (BrowserModule) included?');
|
||||
}
|
||||
|
|
|
@ -81,7 +81,9 @@ export interface DirectiveType<T> extends Type<T> {
|
|||
ngFactoryDef: () => T;
|
||||
}
|
||||
|
||||
export const enum DirectiveDefFlags {ContentQuery = 0b10}
|
||||
export enum DirectiveDefFlags {
|
||||
ContentQuery = 0b10
|
||||
}
|
||||
|
||||
/**
|
||||
* A subclass of `Type` which has a static `ngPipeDef`:`PipeDef` field making it
|
||||
|
|
|
@ -225,7 +225,9 @@ export function createContainerRef(
|
|||
ngModuleRef?: viewEngine_NgModuleRef<any>|undefined): viewEngine_ComponentRef<C> {
|
||||
const contextInjector = injector || this.parentInjector;
|
||||
if (!ngModuleRef && (componentFactory as any).ngModule == null && contextInjector) {
|
||||
ngModuleRef = contextInjector.get(viewEngine_NgModuleRef, null);
|
||||
// FIXME: ngModuleRef is optional, so its type allows "undefined", whereas the code
|
||||
// below is passing null for the default/absent value.
|
||||
ngModuleRef = contextInjector.get(viewEngine_NgModuleRef, null as any as undefined);
|
||||
}
|
||||
|
||||
const componentRef =
|
||||
|
|
|
@ -268,8 +268,9 @@ export class TestBedRender3 implements TestBed {
|
|||
if (token as unknown === TestBedRender3) {
|
||||
return this as any;
|
||||
}
|
||||
const result = this.testModuleRef.injector.get(token, UNDEFINED, flags);
|
||||
return result === UNDEFINED ? this.compiler.injector.get(token, notFoundValue, flags) : result;
|
||||
const result = this.testModuleRef.injector.get(token, UNDEFINED as{}, flags);
|
||||
return result === UNDEFINED ? this.compiler.injector.get(token, notFoundValue, flags) as any :
|
||||
result;
|
||||
}
|
||||
|
||||
/** @deprecated from v9.0.0 use TestBed.inject */
|
||||
|
|
|
@ -480,7 +480,8 @@ export class TestBedViewEngine implements TestBed {
|
|||
// Tests can inject things from the ng module and from the compiler,
|
||||
// but the ng module can't inject things from the compiler and vice versa.
|
||||
const result = this._moduleRef.injector.get(token, UNDEFINED, flags);
|
||||
return result === UNDEFINED ? this._compiler.injector.get(token, notFoundValue, flags) : result;
|
||||
return result === UNDEFINED ? this._compiler.injector.get(token, notFoundValue, flags) as any :
|
||||
result;
|
||||
}
|
||||
|
||||
/** @deprecated from v9.0.0 use TestBed.inject */
|
||||
|
|
|
@ -99,7 +99,7 @@ describe(
|
|||
|
||||
xit('should ensure that Promise this is instanceof Promise', () => {
|
||||
expect(() => {
|
||||
Promise.call({}, () => null);
|
||||
Promise.call({} as any, () => null);
|
||||
}).toThrowError('Must be an instanceof Promise.');
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue