style(ngcc): reformat of ngcc after clang update (#36447)
PR Close #36447
This commit is contained in:
		
							parent
							
								
									c8bef1259c
								
							
						
					
					
						commit
						8be8466a00
					
				| @ -7,9 +7,10 @@ | |||||||
|  */ |  */ | ||||||
| import {CachedFileSystem, NodeJSFileSystem, setFileSystem} from '../src/ngtsc/file_system'; | import {CachedFileSystem, NodeJSFileSystem, setFileSystem} from '../src/ngtsc/file_system'; | ||||||
| 
 | 
 | ||||||
| import {AsyncNgccOptions, NgccOptions, SyncNgccOptions, mainNgcc} from './src/main'; | import {AsyncNgccOptions, mainNgcc, NgccOptions, SyncNgccOptions} from './src/main'; | ||||||
|  | 
 | ||||||
| export {ConsoleLogger} from './src/logging/console_logger'; | export {ConsoleLogger} from './src/logging/console_logger'; | ||||||
| export {LogLevel, Logger} from './src/logging/logger'; | export {Logger, LogLevel} from './src/logging/logger'; | ||||||
| export {AsyncNgccOptions, NgccOptions, SyncNgccOptions} from './src/main'; | export {AsyncNgccOptions, NgccOptions, SyncNgccOptions} from './src/main'; | ||||||
| export {PathMappings} from './src/utils'; | export {PathMappings} from './src/utils'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -125,7 +125,7 @@ if (require.main === module) { | |||||||
|   // And we have to convert the option to a string to handle `no-tsconfig`, which will be `false`.
 |   // And we have to convert the option to a string to handle `no-tsconfig`, which will be `false`.
 | ||||||
|   const tsConfigPath = `${options['tsconfig']}` === 'false' ? null : options['tsconfig']; |   const tsConfigPath = `${options['tsconfig']}` === 'false' ? null : options['tsconfig']; | ||||||
| 
 | 
 | ||||||
|   (async() => { |   (async () => { | ||||||
|     try { |     try { | ||||||
|       const logger = logLevel && new ConsoleLogger(LogLevel[logLevel]); |       const logger = logLevel && new ConsoleLogger(LogLevel[logLevel]); | ||||||
| 
 | 
 | ||||||
| @ -137,7 +137,10 @@ if (require.main === module) { | |||||||
|         createNewEntryPointFormats, |         createNewEntryPointFormats, | ||||||
|         logger, |         logger, | ||||||
|         enableI18nLegacyMessageIdFormat, |         enableI18nLegacyMessageIdFormat, | ||||||
|         async: options['async'], invalidateEntryPointManifest, errorOnFailedEntryPoint, tsConfigPath |         async: options['async'], | ||||||
|  |         invalidateEntryPointManifest, | ||||||
|  |         errorOnFailedEntryPoint, | ||||||
|  |         tsConfigPath | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       if (logger) { |       if (logger) { | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ import {ParsedConfiguration} from '../../..'; | |||||||
| import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ReferencesRegistry, ResourceLoader} from '../../../src/ngtsc/annotations'; | import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ReferencesRegistry, ResourceLoader} from '../../../src/ngtsc/annotations'; | ||||||
| import {CycleAnalyzer, ImportGraph} from '../../../src/ngtsc/cycles'; | import {CycleAnalyzer, ImportGraph} from '../../../src/ngtsc/cycles'; | ||||||
| import {isFatalDiagnosticError} from '../../../src/ngtsc/diagnostics'; | import {isFatalDiagnosticError} from '../../../src/ngtsc/diagnostics'; | ||||||
| import {FileSystem, LogicalFileSystem, absoluteFrom, dirname, resolve} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, dirname, FileSystem, LogicalFileSystem, resolve} from '../../../src/ngtsc/file_system'; | ||||||
| import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, NOOP_DEFAULT_IMPORT_RECORDER, PrivateExportAliasingHost, Reexport, ReferenceEmitter} from '../../../src/ngtsc/imports'; | import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, NOOP_DEFAULT_IMPORT_RECORDER, PrivateExportAliasingHost, Reexport, ReferenceEmitter} from '../../../src/ngtsc/imports'; | ||||||
| import {CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry} from '../../../src/ngtsc/metadata'; | import {CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry} from '../../../src/ngtsc/metadata'; | ||||||
| import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator'; | import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator'; | ||||||
| @ -28,7 +28,7 @@ import {EntryPointBundle} from '../packages/entry_point_bundle'; | |||||||
| import {DefaultMigrationHost} from './migration_host'; | import {DefaultMigrationHost} from './migration_host'; | ||||||
| import {NgccTraitCompiler} from './ngcc_trait_compiler'; | import {NgccTraitCompiler} from './ngcc_trait_compiler'; | ||||||
| import {CompiledClass, CompiledFile, DecorationAnalyses} from './types'; | import {CompiledClass, CompiledFile, DecorationAnalyses} from './types'; | ||||||
| import {NOOP_DEPENDENCY_TRACKER, isWithinPackage} from './util'; | import {isWithinPackage, NOOP_DEPENDENCY_TRACKER} from './util'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -38,8 +38,12 @@ import {NOOP_DEPENDENCY_TRACKER, isWithinPackage} from './util'; | |||||||
| class NgccResourceLoader implements ResourceLoader { | class NgccResourceLoader implements ResourceLoader { | ||||||
|   constructor(private fs: FileSystem) {} |   constructor(private fs: FileSystem) {} | ||||||
|   canPreload = false; |   canPreload = false; | ||||||
|   preload(): undefined|Promise<void> { throw new Error('Not implemented.'); } |   preload(): undefined|Promise<void> { | ||||||
|   load(url: string): string { return this.fs.readFile(resolve(url)); } |     throw new Error('Not implemented.'); | ||||||
|  |   } | ||||||
|  |   load(url: string): string { | ||||||
|  |     return this.fs.readFile(resolve(url)); | ||||||
|  |   } | ||||||
|   resolve(url: string, containingFile: string): string { |   resolve(url: string, containingFile: string): string { | ||||||
|     return resolve(dirname(absoluteFrom(containingFile)), url); |     return resolve(dirname(absoluteFrom(containingFile)), url); | ||||||
|   } |   } | ||||||
| @ -56,7 +60,7 @@ export class DecorationAnalyzer { | |||||||
|   private rootDirs = this.bundle.rootDirs; |   private rootDirs = this.bundle.rootDirs; | ||||||
|   private packagePath = this.bundle.entryPoint.package; |   private packagePath = this.bundle.entryPoint.package; | ||||||
|   private isCore = this.bundle.isCore; |   private isCore = this.bundle.isCore; | ||||||
|   private compilerOptions = this.tsConfig !== null? this.tsConfig.options: {}; |   private compilerOptions = this.tsConfig !== null ? this.tsConfig.options : {}; | ||||||
| 
 | 
 | ||||||
|   moduleResolver = |   moduleResolver = | ||||||
|       new ModuleResolver(this.program, this.options, this.host, /* moduleResolutionCache */ null); |       new ModuleResolver(this.program, this.options, this.host, /* moduleResolutionCache */ null); | ||||||
| @ -73,8 +77,9 @@ export class DecorationAnalyzer { | |||||||
|     // based on whether a bestGuessOwningModule is present in the Reference.
 |     // based on whether a bestGuessOwningModule is present in the Reference.
 | ||||||
|     new LogicalProjectStrategy(this.reflectionHost, new LogicalFileSystem(this.rootDirs)), |     new LogicalProjectStrategy(this.reflectionHost, new LogicalFileSystem(this.rootDirs)), | ||||||
|   ]); |   ]); | ||||||
|   aliasingHost = this.bundle.entryPoint.generateDeepReexports? |   aliasingHost = this.bundle.entryPoint.generateDeepReexports ? | ||||||
|                  new PrivateExportAliasingHost(this.reflectionHost): null; |       new PrivateExportAliasingHost(this.reflectionHost) : | ||||||
|  |       null; | ||||||
|   dtsModuleScopeResolver = |   dtsModuleScopeResolver = | ||||||
|       new MetadataDtsModuleScopeResolver(this.dtsMetaReader, this.aliasingHost); |       new MetadataDtsModuleScopeResolver(this.dtsMetaReader, this.aliasingHost); | ||||||
|   scopeRegistry = new LocalModuleScopeRegistry( |   scopeRegistry = new LocalModuleScopeRegistry( | ||||||
| @ -191,7 +196,9 @@ export class DecorationAnalyzer { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   protected reportDiagnostics() { this.compiler.diagnostics.forEach(this.diagnosticHandler); } |   protected reportDiagnostics() { | ||||||
|  |     this.compiler.diagnostics.forEach(this.diagnosticHandler); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   protected compileFile(sourceFile: ts.SourceFile): CompiledFile { |   protected compileFile(sourceFile: ts.SourceFile): CompiledFile { | ||||||
|     const constantPool = new ConstantPool(); |     const constantPool = new ConstantPool(); | ||||||
| @ -211,7 +218,8 @@ export class DecorationAnalyzer { | |||||||
|       compiledClasses.push({ |       compiledClasses.push({ | ||||||
|         name: record.node.name.text, |         name: record.node.name.text, | ||||||
|         decorators: this.compiler.getAllDecorators(record.node), |         decorators: this.compiler.getAllDecorators(record.node), | ||||||
|         declaration: record.node, compilation |         declaration: record.node, | ||||||
|  |         compilation | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -224,7 +232,7 @@ export class DecorationAnalyzer { | |||||||
|     if (!exportStatements.has(sf.fileName)) { |     if (!exportStatements.has(sf.fileName)) { | ||||||
|       return []; |       return []; | ||||||
|     } |     } | ||||||
|     const exports = exportStatements.get(sf.fileName) !; |     const exports = exportStatements.get(sf.fileName)!; | ||||||
| 
 | 
 | ||||||
|     const reexports: Reexport[] = []; |     const reexports: Reexport[] = []; | ||||||
|     exports.forEach(([fromModule, symbolName], asAlias) => { |     exports.forEach(([fromModule, symbolName], asAlias) => { | ||||||
|  | |||||||
| @ -75,8 +75,7 @@ export class ModuleWithProvidersAnalyzer { | |||||||
|       const dtsClass = this.host.getDtsDeclaration(containerClass.declaration.valueDeclaration); |       const dtsClass = this.host.getDtsDeclaration(containerClass.declaration.valueDeclaration); | ||||||
|       // Get the declaration of the matching static method
 |       // Get the declaration of the matching static method
 | ||||||
|       dtsFn = dtsClass && ts.isClassDeclaration(dtsClass) ? |       dtsFn = dtsClass && ts.isClassDeclaration(dtsClass) ? | ||||||
|           dtsClass.members |           dtsClass.members.find( | ||||||
|               .find( |  | ||||||
|               member => ts.isMethodDeclaration(member) && ts.isIdentifier(member.name) && |               member => ts.isMethodDeclaration(member) && ts.isIdentifier(member.name) && | ||||||
|                   member.name.text === fn.name) as ts.Declaration : |                   member.name.text === fn.name) as ts.Declaration : | ||||||
|           null; |           null; | ||||||
| @ -87,8 +86,8 @@ export class ModuleWithProvidersAnalyzer { | |||||||
|       throw new Error(`Matching type declaration for ${fn.declaration.getText()} is missing`); |       throw new Error(`Matching type declaration for ${fn.declaration.getText()} is missing`); | ||||||
|     } |     } | ||||||
|     if (!isFunctionOrMethod(dtsFn)) { |     if (!isFunctionOrMethod(dtsFn)) { | ||||||
|       throw new Error( |       throw new Error(`Matching type declaration for ${ | ||||||
|           `Matching type declaration for ${fn.declaration.getText()} is not a function: ${dtsFn.getText()}`); |           fn.declaration.getText()} is not a function: ${dtsFn.getText()}`);
 | ||||||
|     } |     } | ||||||
|     return dtsFn; |     return dtsFn; | ||||||
|   } |   } | ||||||
| @ -106,12 +105,14 @@ export class ModuleWithProvidersAnalyzer { | |||||||
|     // to its type declaration.
 |     // to its type declaration.
 | ||||||
|     const dtsNgModule = this.host.getDtsDeclaration(ngModule.node); |     const dtsNgModule = this.host.getDtsDeclaration(ngModule.node); | ||||||
|     if (!dtsNgModule) { |     if (!dtsNgModule) { | ||||||
|       throw new Error( |       throw new Error(`No typings declaration can be found for the referenced NgModule class in ${ | ||||||
|           `No typings declaration can be found for the referenced NgModule class in ${fn.declaration.getText()}.`); |           fn.declaration.getText()}.`);
 | ||||||
|     } |     } | ||||||
|     if (!ts.isClassDeclaration(dtsNgModule) || !hasNameIdentifier(dtsNgModule)) { |     if (!ts.isClassDeclaration(dtsNgModule) || !hasNameIdentifier(dtsNgModule)) { | ||||||
|       throw new Error( |       throw new Error(`The referenced NgModule in ${ | ||||||
|           `The referenced NgModule in ${fn.declaration.getText()} is not a named class declaration in the typings program; instead we get ${dtsNgModule.getText()}`); |           fn.declaration | ||||||
|  |               .getText()} is not a named class declaration in the typings program; instead we get ${ | ||||||
|  |           dtsNgModule.getText()}`);
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return {node: dtsNgModule, known: null, viaModule: null}; |     return {node: dtsNgModule, known: null, viaModule: null}; | ||||||
|  | |||||||
| @ -45,5 +45,7 @@ export class NgccReferencesRegistry implements ReferencesRegistry { | |||||||
|    * Create and return a mapping for the registered resolved references. |    * Create and return a mapping for the registered resolved references. | ||||||
|    * @returns A map of reference identifiers to reference declarations. |    * @returns A map of reference identifiers to reference declarations. | ||||||
|    */ |    */ | ||||||
|   getDeclarationMap(): Map<ts.Identifier, ConcreteDeclaration> { return this.map; } |   getDeclarationMap(): Map<ts.Identifier, ConcreteDeclaration> { | ||||||
|  |     return this.map; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -29,7 +29,9 @@ export class NgccTraitCompiler extends TraitCompiler { | |||||||
|         /* compileNonExportedClasses */ true, new DtsTransformRegistry()); |         /* compileNonExportedClasses */ true, new DtsTransformRegistry()); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   get analyzedFiles(): ts.SourceFile[] { return Array.from(this.fileToClasses.keys()); } |   get analyzedFiles(): ts.SourceFile[] { | ||||||
|  |     return Array.from(this.fileToClasses.keys()); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Analyzes the source file in search for classes to process. For any class that is found in the |    * Analyzes the source file in search for classes to process. For any class that is found in the | ||||||
| @ -81,5 +83,7 @@ export class NgccTraitCompiler extends TraitCompiler { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class NoIncrementalBuild implements IncrementalBuild<any> { | class NoIncrementalBuild implements IncrementalBuild<any> { | ||||||
|   priorWorkFor(sf: ts.SourceFile): any[]|null { return null; } |   priorWorkFor(sf: ts.SourceFile): any[]|null { | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -7,10 +7,11 @@ | |||||||
|  */ |  */ | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| 
 | 
 | ||||||
| import {AbsoluteFsPath, absoluteFromSourceFile} from '../../../src/ngtsc/file_system'; | import {absoluteFromSourceFile, AbsoluteFsPath} from '../../../src/ngtsc/file_system'; | ||||||
| import {ConcreteDeclaration} from '../../../src/ngtsc/reflection'; | import {ConcreteDeclaration} from '../../../src/ngtsc/reflection'; | ||||||
| import {NgccReflectionHost} from '../host/ngcc_host'; | import {NgccReflectionHost} from '../host/ngcc_host'; | ||||||
| import {hasNameIdentifier, isDefined} from '../utils'; | import {hasNameIdentifier, isDefined} from '../utils'; | ||||||
|  | 
 | ||||||
| import {NgccReferencesRegistry} from './ngcc_references_registry'; | import {NgccReferencesRegistry} from './ngcc_references_registry'; | ||||||
| 
 | 
 | ||||||
| export interface ExportInfo { | export interface ExportInfo { | ||||||
| @ -48,7 +49,7 @@ export class PrivateDeclarationsAnalyzer { | |||||||
|         exports.forEach((declaration, exportedName) => { |         exports.forEach((declaration, exportedName) => { | ||||||
|           if (declaration.node !== null && hasNameIdentifier(declaration.node)) { |           if (declaration.node !== null && hasNameIdentifier(declaration.node)) { | ||||||
|             if (privateDeclarations.has(declaration.node.name)) { |             if (privateDeclarations.has(declaration.node.name)) { | ||||||
|               const privateDeclaration = privateDeclarations.get(declaration.node.name) !; |               const privateDeclaration = privateDeclarations.get(declaration.node.name)!; | ||||||
|               if (privateDeclaration.node !== declaration.node) { |               if (privateDeclaration.node !== declaration.node) { | ||||||
|                 throw new Error(`${declaration.node.name.text} is declared multiple times.`); |                 throw new Error(`${declaration.node.name.text} is declared multiple times.`); | ||||||
|               } |               } | ||||||
| @ -62,7 +63,7 @@ export class PrivateDeclarationsAnalyzer { | |||||||
| 
 | 
 | ||||||
|     return Array.from(privateDeclarations.keys()).map(id => { |     return Array.from(privateDeclarations.keys()).map(id => { | ||||||
|       const from = absoluteFromSourceFile(id.getSourceFile()); |       const from = absoluteFromSourceFile(id.getSourceFile()); | ||||||
|       const declaration = privateDeclarations.get(id) !; |       const declaration = privateDeclarations.get(id)!; | ||||||
|       const dtsDeclaration = this.host.getDtsDeclaration(declaration.node); |       const dtsDeclaration = this.host.getDtsDeclaration(declaration.node); | ||||||
|       const dtsFrom = dtsDeclaration && absoluteFromSourceFile(dtsDeclaration.getSourceFile()); |       const dtsFrom = dtsDeclaration && absoluteFromSourceFile(dtsDeclaration.getSourceFile()); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ | |||||||
|  */ |  */ | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| 
 | 
 | ||||||
| import {AbsoluteFsPath, absoluteFromSourceFile, relative} from '../../../src/ngtsc/file_system'; | import {absoluteFromSourceFile, AbsoluteFsPath, relative} from '../../../src/ngtsc/file_system'; | ||||||
| import {DependencyTracker} from '../../../src/ngtsc/incremental/api'; | import {DependencyTracker} from '../../../src/ngtsc/incremental/api'; | ||||||
| 
 | 
 | ||||||
| export function isWithinPackage(packagePath: AbsoluteFsPath, sourceFile: ts.SourceFile): boolean { | export function isWithinPackage(packagePath: AbsoluteFsPath, sourceFile: ts.SourceFile): boolean { | ||||||
|  | |||||||
| @ -6,8 +6,10 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
|  | 
 | ||||||
| import {AbsoluteFsPath} from '../../../src/ngtsc/file_system'; | import {AbsoluteFsPath} from '../../../src/ngtsc/file_system'; | ||||||
| import {RequireCall, isReexportStatement, isRequireCall} from '../host/commonjs_umd_utils'; | import {isReexportStatement, isRequireCall, RequireCall} from '../host/commonjs_umd_utils'; | ||||||
|  | 
 | ||||||
| import {DependencyHostBase} from './dependency_host'; | import {DependencyHostBase} from './dependency_host'; | ||||||
| import {ResolvedDeepImport, ResolvedRelativeModule} from './module_resolver'; | import {ResolvedDeepImport, ResolvedRelativeModule} from './module_resolver'; | ||||||
| 
 | 
 | ||||||
| @ -120,5 +122,7 @@ export class CommonJsDependencyHost extends DependencyHostBase { | |||||||
|    * @returns false if there are definitely no require calls |    * @returns false if there are definitely no require calls | ||||||
|    * in this file, true otherwise. |    * in this file, true otherwise. | ||||||
|    */ |    */ | ||||||
|   private hasRequireCalls(source: string): boolean { return /require\(['"]/.test(source); } |   private hasRequireCalls(source: string): boolean { | ||||||
|  |     return /require\(['"]/.test(source); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -7,12 +7,14 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| import {DepGraph} from 'dependency-graph'; | import {DepGraph} from 'dependency-graph'; | ||||||
|  | 
 | ||||||
| import {AbsoluteFsPath, FileSystem, resolve} from '../../../src/ngtsc/file_system'; | import {AbsoluteFsPath, FileSystem, resolve} from '../../../src/ngtsc/file_system'; | ||||||
| import {Logger} from '../logging/logger'; | import {Logger} from '../logging/logger'; | ||||||
| import {NgccConfiguration} from '../packages/configuration'; | import {NgccConfiguration} from '../packages/configuration'; | ||||||
| import {EntryPoint, EntryPointFormat, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from '../packages/entry_point'; | import {EntryPoint, EntryPointFormat, getEntryPointFormat, SUPPORTED_FORMAT_PROPERTIES} from '../packages/entry_point'; | ||||||
| import {PartiallyOrderedList} from '../utils'; | import {PartiallyOrderedList} from '../utils'; | ||||||
| import {DependencyHost, DependencyInfo, createDependencyInfo} from './dependency_host'; | 
 | ||||||
|  | import {createDependencyInfo, DependencyHost, DependencyInfo} from './dependency_host'; | ||||||
| 
 | 
 | ||||||
| const builtinNodeJsModules = new Set<string>(require('module').builtinModules); | const builtinNodeJsModules = new Set<string>(require('module').builtinModules); | ||||||
| 
 | 
 | ||||||
| @ -123,7 +125,8 @@ export class DependencyResolver { | |||||||
|     const host = this.hosts[formatInfo.format]; |     const host = this.hosts[formatInfo.format]; | ||||||
|     if (!host) { |     if (!host) { | ||||||
|       throw new Error( |       throw new Error( | ||||||
|           `Could not find a suitable format for computing dependencies of entry-point: '${entryPoint.path}'.`); |           `Could not find a suitable format for computing dependencies of entry-point: '${ | ||||||
|  |               entryPoint.path}'.`);
 | ||||||
|     } |     } | ||||||
|     const depInfo = createDependencyInfo(); |     const depInfo = createDependencyInfo(); | ||||||
|     host.collectDependencies(formatInfo.path, depInfo); |     host.collectDependencies(formatInfo.path, depInfo); | ||||||
|  | |||||||
| @ -5,8 +5,8 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {AbsoluteFsPath, FileSystem, absoluteFrom, dirname, isRoot, join, resolve} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath, dirname, FileSystem, isRoot, join, resolve} from '../../../src/ngtsc/file_system'; | ||||||
| import {PathMappings, isRelativePath, resolveFileWithPostfixes} from '../utils'; | import {isRelativePath, PathMappings, resolveFileWithPostfixes} from '../utils'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * This is a very cut-down implementation of the TypeScript module resolution strategy. |  * This is a very cut-down implementation of the TypeScript module resolution strategy. | ||||||
| @ -222,7 +222,7 @@ export class ModuleResolver { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** The result of resolving an import to a module. */ | /** The result of resolving an import to a module. */ | ||||||
| export type ResolvedModule = ResolvedExternalModule | ResolvedRelativeModule | ResolvedDeepImport; | export type ResolvedModule = ResolvedExternalModule|ResolvedRelativeModule|ResolvedDeepImport; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A module that is external to the package doing the importing. |  * A module that is external to the package doing the importing. | ||||||
|  | |||||||
| @ -84,5 +84,7 @@ export class UmdDependencyHost extends DependencyHostBase { | |||||||
|    * @returns false if there are definitely no require calls |    * @returns false if there are definitely no require calls | ||||||
|    * in this file, true otherwise. |    * in this file, true otherwise. | ||||||
|    */ |    */ | ||||||
|   private hasRequireCalls(source: string): boolean { return /require\(['"]/.test(source); } |   private hasRequireCalls(source: string): boolean { | ||||||
|  |     return /require\(['"]/.test(source); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -9,10 +9,11 @@ import {AbsoluteFsPath, FileSystem, PathSegment} from '../../../src/ngtsc/file_s | |||||||
| import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver'; | import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver'; | ||||||
| import {Logger} from '../logging/logger'; | import {Logger} from '../logging/logger'; | ||||||
| import {NgccConfiguration} from '../packages/configuration'; | import {NgccConfiguration} from '../packages/configuration'; | ||||||
| import {EntryPoint, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT, getEntryPointInfo} from '../packages/entry_point'; | import {EntryPoint, getEntryPointInfo, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT} from '../packages/entry_point'; | ||||||
| import {EntryPointManifest} from '../packages/entry_point_manifest'; | import {EntryPointManifest} from '../packages/entry_point_manifest'; | ||||||
| import {PathMappings} from '../utils'; | import {PathMappings} from '../utils'; | ||||||
| import {NGCC_DIRECTORY} from '../writing/new_entry_point_file_writer'; | import {NGCC_DIRECTORY} from '../writing/new_entry_point_file_writer'; | ||||||
|  | 
 | ||||||
| import {EntryPointFinder} from './interface'; | import {EntryPointFinder} from './interface'; | ||||||
| import {getBasePaths, trackDuration} from './utils'; | import {getBasePaths, trackDuration} from './utils'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -5,13 +5,14 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {AbsoluteFsPath, FileSystem, PathSegment, join, relative, relativeFrom} from '../../../src/ngtsc/file_system'; | import {AbsoluteFsPath, FileSystem, join, PathSegment, relative, relativeFrom} from '../../../src/ngtsc/file_system'; | ||||||
| import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver'; | import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver'; | ||||||
| import {Logger} from '../logging/logger'; | import {Logger} from '../logging/logger'; | ||||||
| import {hasBeenProcessed} from '../packages/build_marker'; | import {hasBeenProcessed} from '../packages/build_marker'; | ||||||
| import {NgccConfiguration} from '../packages/configuration'; | import {NgccConfiguration} from '../packages/configuration'; | ||||||
| import {EntryPoint, EntryPointJsonProperty, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT, getEntryPointInfo} from '../packages/entry_point'; | import {EntryPoint, EntryPointJsonProperty, getEntryPointInfo, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT} from '../packages/entry_point'; | ||||||
| import {PathMappings} from '../utils'; | import {PathMappings} from '../utils'; | ||||||
|  | 
 | ||||||
| import {EntryPointFinder} from './interface'; | import {EntryPointFinder} from './interface'; | ||||||
| import {getBasePaths} from './utils'; | import {getBasePaths} from './utils'; | ||||||
| 
 | 
 | ||||||
| @ -76,7 +77,7 @@ export class TargetedEntryPointFinder implements EntryPointFinder { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private processNextPath(): void { |   private processNextPath(): void { | ||||||
|     const path = this.unprocessedPaths.shift() !; |     const path = this.unprocessedPaths.shift()!; | ||||||
|     const entryPoint = this.getEntryPoint(path); |     const entryPoint = this.getEntryPoint(path); | ||||||
|     if (entryPoint === null || !entryPoint.compiledByAngular) { |     if (entryPoint === null || !entryPoint.compiledByAngular) { | ||||||
|       return; |       return; | ||||||
| @ -130,7 +131,7 @@ export class TargetedEntryPointFinder implements EntryPointFinder { | |||||||
|         // Start the search at the deepest nested `node_modules` folder that is below the `basePath`
 |         // Start the search at the deepest nested `node_modules` folder that is below the `basePath`
 | ||||||
|         // but above the `entryPointPath`, if there are any.
 |         // but above the `entryPointPath`, if there are any.
 | ||||||
|         while (nodeModulesIndex >= 0) { |         while (nodeModulesIndex >= 0) { | ||||||
|           packagePath = join(packagePath, segments.shift() !); |           packagePath = join(packagePath, segments.shift()!); | ||||||
|           nodeModulesIndex--; |           nodeModulesIndex--; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -30,7 +30,7 @@ import {PathMappings} from '../utils'; | |||||||
|  */ |  */ | ||||||
| export function getBasePaths( | export function getBasePaths( | ||||||
|     logger: Logger, sourceDirectory: AbsoluteFsPath, |     logger: Logger, sourceDirectory: AbsoluteFsPath, | ||||||
|     pathMappings: PathMappings | undefined): AbsoluteFsPath[] { |     pathMappings: PathMappings|undefined): AbsoluteFsPath[] { | ||||||
|   const fs = getFileSystem(); |   const fs = getFileSystem(); | ||||||
|   const basePaths = [sourceDirectory]; |   const basePaths = [sourceDirectory]; | ||||||
|   if (pathMappings) { |   if (pathMappings) { | ||||||
| @ -51,7 +51,8 @@ export function getBasePaths( | |||||||
|         basePaths.push(basePath); |         basePaths.push(basePath); | ||||||
|       } else { |       } else { | ||||||
|         logger.warn( |         logger.warn( | ||||||
|             `The basePath "${basePath}" computed from baseUrl "${baseUrl}" and path mapping "${path}" does not exist in the file-system.\n` + |             `The basePath "${basePath}" computed from baseUrl "${baseUrl}" and path mapping "${ | ||||||
|  |                 path}" does not exist in the file-system.\n` +
 | ||||||
|             `It will not be scanned for entry-points.`); |             `It will not be scanned for entry-points.`); | ||||||
|       } |       } | ||||||
|     })); |     })); | ||||||
| @ -109,8 +110,8 @@ function removeContainedPaths(value: AbsoluteFsPath, index: number, array: Absol | |||||||
|  * @param log The function to call with the duration of the task |  * @param log The function to call with the duration of the task | ||||||
|  * @returns The result of calling `task`. |  * @returns The result of calling `task`. | ||||||
|  */ |  */ | ||||||
| export function trackDuration<T = void>( | export function trackDuration<T = void>(task: () => T extends Promise<unknown>? never : T, | ||||||
|     task: () => T extends Promise<unknown>? never : T, log: (duration: number) => void): T { |                                                               log: (duration: number) => void): T { | ||||||
|   const startTime = Date.now(); |   const startTime = Date.now(); | ||||||
|   const result = task(); |   const result = task(); | ||||||
|   const duration = Math.round((Date.now() - startTime) / 100) / 10; |   const duration = Math.round((Date.now() - startTime) / 100) / 10; | ||||||
|  | |||||||
| @ -44,7 +44,7 @@ export interface UpdatePackageJsonMessage extends JsonObject { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** The type of messages sent from cluster workers to the cluster master. */ | /** The type of messages sent from cluster workers to the cluster master. */ | ||||||
| export type MessageFromWorker = ErrorMessage | TaskCompletedMessage | UpdatePackageJsonMessage; | export type MessageFromWorker = ErrorMessage|TaskCompletedMessage|UpdatePackageJsonMessage; | ||||||
| 
 | 
 | ||||||
| /** The type of messages sent from the cluster master to cluster workers. */ | /** The type of messages sent from the cluster master to cluster workers. */ | ||||||
| export type MessageToWorker = ProcessTaskMessage; | export type MessageToWorker = ProcessTaskMessage; | ||||||
|  | |||||||
| @ -35,8 +35,8 @@ export class ClusterExecutor implements Executor { | |||||||
|     if (cluster.isMaster) { |     if (cluster.isMaster) { | ||||||
|       // This process is the cluster master.
 |       // This process is the cluster master.
 | ||||||
|       return this.lockFile.lock(() => { |       return this.lockFile.lock(() => { | ||||||
|         this.logger.debug( |         this.logger.debug(`Running ngcc on ${this.constructor.name} (using ${ | ||||||
|             `Running ngcc on ${this.constructor.name} (using ${this.workerCount} worker processes).`); |             this.workerCount} worker processes).`);
 | ||||||
|         const master = new ClusterMaster( |         const master = new ClusterMaster( | ||||||
|             this.workerCount, this.logger, this.pkgJsonUpdater, analyzeEntryPoints, |             this.workerCount, this.logger, this.pkgJsonUpdater, analyzeEntryPoints, | ||||||
|             this.createTaskCompletedCallback); |             this.createTaskCompletedCallback); | ||||||
|  | |||||||
| @ -262,7 +262,7 @@ export class ClusterMaster { | |||||||
|    */ |    */ | ||||||
|   private wrapEventHandler<Args extends unknown[]>(fn: (...args: Args) => void|Promise<void>): |   private wrapEventHandler<Args extends unknown[]>(fn: (...args: Args) => void|Promise<void>): | ||||||
|       (...args: Args) => Promise<void> { |       (...args: Args) => Promise<void> { | ||||||
|     return async(...args: Args) => { |     return async (...args: Args) => { | ||||||
|       try { |       try { | ||||||
|         await fn(...args); |         await fn(...args); | ||||||
|       } catch (err) { |       } catch (err) { | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ import * as cluster from 'cluster'; | |||||||
| 
 | 
 | ||||||
| import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system'; | import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system'; | ||||||
| import {JsonObject} from '../../packages/entry_point'; | import {JsonObject} from '../../packages/entry_point'; | ||||||
| import {PackageJsonChange, PackageJsonUpdate, PackageJsonUpdater, applyChange} from '../../writing/package_json_updater'; | import {applyChange, PackageJsonChange, PackageJsonUpdate, PackageJsonUpdater} from '../../writing/package_json_updater'; | ||||||
| 
 | 
 | ||||||
| import {sendMessageToMaster} from './utils'; | import {sendMessageToMaster} from './utils'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -23,14 +23,14 @@ export class Deferred<T> { | |||||||
|    * |    * | ||||||
|    * @param value The value to resolve the promise with. |    * @param value The value to resolve the promise with. | ||||||
|    */ |    */ | ||||||
|   resolve !: (value: T) => void; |   resolve!: (value: T) => void; | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Rejects the associated promise with the specified reason. |    * Rejects the associated promise with the specified reason. | ||||||
|    * |    * | ||||||
|    * @param reason The rejection reason. |    * @param reason The rejection reason. | ||||||
|    */ |    */ | ||||||
|   reject !: (reason: any) => void; |   reject!: (reason: any) => void; | ||||||
| 
 | 
 | ||||||
|   /** The `Promise` instance associated with this deferred. */ |   /** The `Promise` instance associated with this deferred. */ | ||||||
|   promise = new Promise<T>((resolve, reject) => { |   promise = new Promise<T>((resolve, reject) => { | ||||||
|  | |||||||
| @ -30,7 +30,7 @@ export abstract class SingleProcessorExecutorBase { | |||||||
|     const startTime = Date.now(); |     const startTime = Date.now(); | ||||||
| 
 | 
 | ||||||
|     while (!taskQueue.allTasksCompleted) { |     while (!taskQueue.allTasksCompleted) { | ||||||
|       const task = taskQueue.getNextTask() !; |       const task = taskQueue.getNextTask()!; | ||||||
|       compile(task); |       compile(task); | ||||||
|       taskQueue.markTaskCompleted(task); |       taskQueue.markTaskCompleted(task); | ||||||
|     } |     } | ||||||
| @ -65,6 +65,6 @@ export class SingleProcessExecutorAsync extends SingleProcessorExecutorBase impl | |||||||
|   } |   } | ||||||
|   async execute(analyzeEntryPoints: AnalyzeEntryPointsFn, createCompileFn: CreateCompileFn): |   async execute(analyzeEntryPoints: AnalyzeEntryPointsFn, createCompileFn: CreateCompileFn): | ||||||
|       Promise<void> { |       Promise<void> { | ||||||
|     await this.lockFile.lock(async() => this.doExecute(analyzeEntryPoints, createCompileFn)); |     await this.lockFile.lock(async () => this.doExecute(analyzeEntryPoints, createCompileFn)); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -66,7 +66,7 @@ export type CreateTaskCompletedCallback = (taskQueue: TaskQueue) => TaskComplete | |||||||
|  * A function to be called once a task has been processed. |  * A function to be called once a task has been processed. | ||||||
|  */ |  */ | ||||||
| export type TaskCompletedCallback = | export type TaskCompletedCallback = | ||||||
|     (task: Task, outcome: TaskProcessingOutcome, message: string | null) => void; |     (task: Task, outcome: TaskProcessingOutcome, message: string|null) => void; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Represents the outcome of processing a `Task`. |  * Represents the outcome of processing a `Task`. | ||||||
|  | |||||||
| @ -8,8 +8,9 @@ | |||||||
| import {FileSystem, resolve} from '../../../../src/ngtsc/file_system'; | import {FileSystem, resolve} from '../../../../src/ngtsc/file_system'; | ||||||
| import {Logger} from '../../logging/logger'; | import {Logger} from '../../logging/logger'; | ||||||
| import {markAsProcessed} from '../../packages/build_marker'; | import {markAsProcessed} from '../../packages/build_marker'; | ||||||
| import {PackageJsonFormatProperties, getEntryPointFormat} from '../../packages/entry_point'; | import {getEntryPointFormat, PackageJsonFormatProperties} from '../../packages/entry_point'; | ||||||
| import {PackageJsonUpdater} from '../../writing/package_json_updater'; | import {PackageJsonUpdater} from '../../writing/package_json_updater'; | ||||||
|  | 
 | ||||||
| import {Task, TaskCompletedCallback, TaskProcessingOutcome, TaskQueue} from './api'; | import {Task, TaskCompletedCallback, TaskProcessingOutcome, TaskQueue} from './api'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -18,7 +19,7 @@ import {Task, TaskCompletedCallback, TaskProcessingOutcome, TaskQueue} from './a | |||||||
|  * These functions can be composed using the `composeTaskCompletedCallbacks()` |  * These functions can be composed using the `composeTaskCompletedCallbacks()` | ||||||
|  * to create a `TaskCompletedCallback` function that can be passed to an `Executor`. |  * to create a `TaskCompletedCallback` function that can be passed to an `Executor`. | ||||||
|  */ |  */ | ||||||
| export type TaskCompletedHandler = (task: Task, message: string | null) => void; | export type TaskCompletedHandler = (task: Task, message: string|null) => void; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Compose a group of TaskCompletedHandlers into a single TaskCompletedCallback. |  * Compose a group of TaskCompletedHandlers into a single TaskCompletedCallback. | ||||||
| @ -30,11 +31,11 @@ export type TaskCompletedHandler = (task: Task, message: string | null) => void; | |||||||
|  */ |  */ | ||||||
| export function composeTaskCompletedCallbacks( | export function composeTaskCompletedCallbacks( | ||||||
|     callbacks: Record<TaskProcessingOutcome, TaskCompletedHandler>): TaskCompletedCallback { |     callbacks: Record<TaskProcessingOutcome, TaskCompletedHandler>): TaskCompletedCallback { | ||||||
|   return (task: Task, outcome: TaskProcessingOutcome, message: string | null): void => { |   return (task: Task, outcome: TaskProcessingOutcome, message: string|null): void => { | ||||||
|     const callback = callbacks[outcome]; |     const callback = callbacks[outcome]; | ||||||
|     if (callback === undefined) { |     if (callback === undefined) { | ||||||
|       throw new Error( |       throw new Error(`Unknown task outcome: "${outcome}" - supported outcomes: ${ | ||||||
|           `Unknown task outcome: "${outcome}" - supported outcomes: ${JSON.stringify(Object.keys(callbacks))}`); |           JSON.stringify(Object.keys(callbacks))}`);
 | ||||||
|     } |     } | ||||||
|     callback(task, message); |     callback(task, message); | ||||||
|   }; |   }; | ||||||
| @ -64,10 +65,11 @@ export function createMarkAsProcessedHandler(pkgJsonUpdater: PackageJsonUpdater) | |||||||
|  * Create a handler that will throw an error. |  * Create a handler that will throw an error. | ||||||
|  */ |  */ | ||||||
| export function createThrowErrorHandler(fs: FileSystem): TaskCompletedHandler { | export function createThrowErrorHandler(fs: FileSystem): TaskCompletedHandler { | ||||||
|   return (task: Task, message: string | null): void => { |   return (task: Task, message: string|null): void => { | ||||||
|     const format = getEntryPointFormat(fs, task.entryPoint, task.formatProperty); |     const format = getEntryPointFormat(fs, task.entryPoint, task.formatProperty); | ||||||
|     throw new Error( |     throw new Error( | ||||||
|         `Failed to compile entry-point ${task.entryPoint.name} (${task.formatProperty} as ${format})` + |         `Failed to compile entry-point ${task.entryPoint.name} (${task.formatProperty} as ${ | ||||||
|  |             format})` +
 | ||||||
|         (message !== null ? ` due to ${message}` : '')); |         (message !== null ? ` due to ${message}` : '')); | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
| @ -77,11 +79,12 @@ export function createThrowErrorHandler(fs: FileSystem): TaskCompletedHandler { | |||||||
|  */ |  */ | ||||||
| export function createLogErrorHandler( | export function createLogErrorHandler( | ||||||
|     logger: Logger, fs: FileSystem, taskQueue: TaskQueue): TaskCompletedHandler { |     logger: Logger, fs: FileSystem, taskQueue: TaskQueue): TaskCompletedHandler { | ||||||
|   return (task: Task, message: string | null): void => { |   return (task: Task, message: string|null): void => { | ||||||
|     taskQueue.markAsFailed(task); |     taskQueue.markAsFailed(task); | ||||||
|     const format = getEntryPointFormat(fs, task.entryPoint, task.formatProperty); |     const format = getEntryPointFormat(fs, task.entryPoint, task.formatProperty); | ||||||
|     logger.error( |     logger.error( | ||||||
|         `Failed to compile entry-point ${task.entryPoint.name} (${task.formatProperty} as ${format})` + |         `Failed to compile entry-point ${task.entryPoint.name} (${task.formatProperty} as ${ | ||||||
|  |             format})` +
 | ||||||
|         (message !== null ? ` due to ${message}` : '')); |         (message !== null ? ` due to ${message}` : '')); | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -38,9 +38,9 @@ export abstract class BaseTaskQueue implements TaskQueue { | |||||||
|       } |       } | ||||||
|       // We are skipping this task so mark it as complete
 |       // We are skipping this task so mark it as complete
 | ||||||
|       this.markTaskCompleted(nextTask); |       this.markTaskCompleted(nextTask); | ||||||
|       const failedTask = this.tasksToSkip.get(nextTask) !; |       const failedTask = this.tasksToSkip.get(nextTask)!; | ||||||
|       this.logger.warn( |       this.logger.warn(`Skipping processing of ${nextTask.entryPoint.name} because its dependency ${ | ||||||
|           `Skipping processing of ${nextTask.entryPoint.name} because its dependency ${failedTask.entryPoint.name} failed to compile.`); |           failedTask.entryPoint.name} failed to compile.`);
 | ||||||
|       nextTask = this.computeNextTask(); |       nextTask = this.computeNextTask(); | ||||||
|     } |     } | ||||||
|     return nextTask; |     return nextTask; | ||||||
| @ -48,7 +48,7 @@ export abstract class BaseTaskQueue implements TaskQueue { | |||||||
| 
 | 
 | ||||||
|   markAsFailed(task: Task) { |   markAsFailed(task: Task) { | ||||||
|     if (this.dependencies.has(task)) { |     if (this.dependencies.has(task)) { | ||||||
|       for (const dependentTask of this.dependencies.get(task) !) { |       for (const dependentTask of this.dependencies.get(task)!) { | ||||||
|         this.skipDependentTasks(dependentTask, task); |         this.skipDependentTasks(dependentTask, task); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @ -81,7 +81,7 @@ export abstract class BaseTaskQueue implements TaskQueue { | |||||||
|   protected skipDependentTasks(task: Task, failedTask: Task) { |   protected skipDependentTasks(task: Task, failedTask: Task) { | ||||||
|     this.tasksToSkip.set(task, failedTask); |     this.tasksToSkip.set(task, failedTask); | ||||||
|     if (this.dependencies.has(task)) { |     if (this.dependencies.has(task)) { | ||||||
|       for (const dependentTask of this.dependencies.get(task) !) { |       for (const dependentTask of this.dependencies.get(task)!) { | ||||||
|         this.skipDependentTasks(dependentTask, failedTask); |         this.skipDependentTasks(dependentTask, failedTask); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -49,9 +49,9 @@ export class ParallelTaskQueue extends BaseTaskQueue { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Unblock the tasks that are dependent upon `task`
 |     // Unblock the tasks that are dependent upon `task`
 | ||||||
|     for (const dependentTask of this.dependencies.get(task) !) { |     for (const dependentTask of this.dependencies.get(task)!) { | ||||||
|       if (this.blockedTasks.has(dependentTask)) { |       if (this.blockedTasks.has(dependentTask)) { | ||||||
|         const blockingTasks = this.blockedTasks.get(dependentTask) !; |         const blockingTasks = this.blockedTasks.get(dependentTask)!; | ||||||
|         // Remove the completed task from the lists of tasks blocking other tasks.
 |         // Remove the completed task from the lists of tasks blocking other tasks.
 | ||||||
|         blockingTasks.delete(task); |         blockingTasks.delete(task); | ||||||
|         if (blockingTasks.size === 0) { |         if (blockingTasks.size === 0) { | ||||||
|  | |||||||
| @ -10,8 +10,8 @@ import {EntryPoint} from '../../packages/entry_point'; | |||||||
| import {PartiallyOrderedTasks, Task, TaskDependencies} from './api'; | import {PartiallyOrderedTasks, Task, TaskDependencies} from './api'; | ||||||
| 
 | 
 | ||||||
| /** Stringify a task for debugging purposes. */ | /** Stringify a task for debugging purposes. */ | ||||||
| export const stringifyTask = (task: Task): string => | export const stringifyTask = (task: Task): string => `{entryPoint: ${ | ||||||
|     `{entryPoint: ${task.entryPoint.name}, formatProperty: ${task.formatProperty}, processDts: ${task.processDts}}`; |     task.entryPoint.name}, formatProperty: ${task.formatProperty}, processDts: ${task.processDts}}`;
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Compute a mapping of tasks to the tasks that are dependent on them (if any). |  * Compute a mapping of tasks to the tasks that are dependent on them (if any). | ||||||
| @ -45,7 +45,7 @@ export function computeTaskDependencies( | |||||||
|     // Find the earlier tasks (`candidateDependencies`) that this task depends upon.
 |     // Find the earlier tasks (`candidateDependencies`) that this task depends upon.
 | ||||||
|     const deps = graph.dependenciesOf(entryPointPath); |     const deps = graph.dependenciesOf(entryPointPath); | ||||||
|     const taskDependencies = deps.filter(dep => candidateDependencies.has(dep)) |     const taskDependencies = deps.filter(dep => candidateDependencies.has(dep)) | ||||||
|                                  .map(dep => candidateDependencies.get(dep) !); |                                  .map(dep => candidateDependencies.get(dep)!); | ||||||
| 
 | 
 | ||||||
|     // If this task has dependencies, add it to the dependencies and dependents maps.
 |     // If this task has dependencies, add it to the dependencies and dependents maps.
 | ||||||
|     if (taskDependencies.length > 0) { |     if (taskDependencies.length > 0) { | ||||||
| @ -61,7 +61,7 @@ export function computeTaskDependencies( | |||||||
|       // dependency of other tasks), so the following should theoretically never happen, but check
 |       // dependency of other tasks), so the following should theoretically never happen, but check
 | ||||||
|       // just in case.
 |       // just in case.
 | ||||||
|       if (candidateDependencies.has(entryPointPath)) { |       if (candidateDependencies.has(entryPointPath)) { | ||||||
|         const otherTask = candidateDependencies.get(entryPointPath) !; |         const otherTask = candidateDependencies.get(entryPointPath)!; | ||||||
|         throw new Error( |         throw new Error( | ||||||
|             'Invariant violated: Multiple tasks are assigned generating typings for ' + |             'Invariant violated: Multiple tasks are assigned generating typings for ' + | ||||||
|             `'${entryPointPath}':\n  - ${stringifyTask(otherTask)}\n  - ${stringifyTask(task)}`); |             `'${entryPointPath}':\n  - ${stringifyTask(otherTask)}\n  - ${stringifyTask(task)}`); | ||||||
| @ -73,7 +73,7 @@ export function computeTaskDependencies( | |||||||
|       // This task is not generating typings so we need to add it to the dependents of the task that
 |       // This task is not generating typings so we need to add it to the dependents of the task that
 | ||||||
|       // does generate typings, if that exists
 |       // does generate typings, if that exists
 | ||||||
|       if (candidateDependencies.has(entryPointPath)) { |       if (candidateDependencies.has(entryPointPath)) { | ||||||
|         const typingsTask = candidateDependencies.get(entryPointPath) !; |         const typingsTask = candidateDependencies.get(entryPointPath)!; | ||||||
|         const typingsTaskDependents = getDependentsSet(dependencies, typingsTask); |         const typingsTaskDependents = getDependentsSet(dependencies, typingsTask); | ||||||
|         typingsTaskDependents.add(task); |         typingsTaskDependents.add(task); | ||||||
|       } |       } | ||||||
| @ -87,7 +87,7 @@ export function getDependentsSet(map: TaskDependencies, task: Task): Set<Task> { | |||||||
|   if (!map.has(task)) { |   if (!map.has(task)) { | ||||||
|     map.set(task, new Set()); |     map.set(task, new Set()); | ||||||
|   } |   } | ||||||
|   return map.get(task) !; |   return map.get(task)!; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -125,13 +125,13 @@ export function sortTasksByPriority( | |||||||
|     tasks: PartiallyOrderedTasks, dependencies: TaskDependencies): PartiallyOrderedTasks { |     tasks: PartiallyOrderedTasks, dependencies: TaskDependencies): PartiallyOrderedTasks { | ||||||
|   const priorityPerTask = new Map<Task, [number, number]>(); |   const priorityPerTask = new Map<Task, [number, number]>(); | ||||||
|   const computePriority = (task: Task, idx: number): |   const computePriority = (task: Task, idx: number): | ||||||
|       [number, number] => [dependencies.has(task) ? dependencies.get(task) !.size : 0, idx]; |       [number, number] => [dependencies.has(task) ? dependencies.get(task)!.size : 0, idx]; | ||||||
| 
 | 
 | ||||||
|   tasks.forEach((task, i) => priorityPerTask.set(task, computePriority(task, i))); |   tasks.forEach((task, i) => priorityPerTask.set(task, computePriority(task, i))); | ||||||
| 
 | 
 | ||||||
|   return tasks.slice().sort((task1, task2) => { |   return tasks.slice().sort((task1, task2) => { | ||||||
|     const [p1, idx1] = priorityPerTask.get(task1) !; |     const [p1, idx1] = priorityPerTask.get(task1)!; | ||||||
|     const [p2, idx2] = priorityPerTask.get(task2) !; |     const [p2, idx2] = priorityPerTask.get(task2)!; | ||||||
| 
 | 
 | ||||||
|     return (p2 - p1) || (idx1 - idx2); |     return (p2 - p1) || (idx1 - idx2); | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -7,13 +7,14 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
|  | 
 | ||||||
| import {absoluteFrom} from '../../../src/ngtsc/file_system'; | import {absoluteFrom} from '../../../src/ngtsc/file_system'; | ||||||
| import {Declaration, Import} from '../../../src/ngtsc/reflection'; | import {Declaration, Import} from '../../../src/ngtsc/reflection'; | ||||||
| import {Logger} from '../logging/logger'; | import {Logger} from '../logging/logger'; | ||||||
| import {BundleProgram} from '../packages/bundle_program'; | import {BundleProgram} from '../packages/bundle_program'; | ||||||
| import {FactoryMap, getTsHelperFnFromIdentifier, isDefined, stripExtension} from '../utils'; | import {FactoryMap, getTsHelperFnFromIdentifier, isDefined, stripExtension} from '../utils'; | ||||||
| 
 | 
 | ||||||
| import {ExportDeclaration, ExportStatement, ReexportStatement, RequireCall, findNamespaceOfIdentifier, findRequireCallReference, isExportStatement, isReexportStatement, isRequireCall} from './commonjs_umd_utils'; | import {ExportDeclaration, ExportStatement, findNamespaceOfIdentifier, findRequireCallReference, isExportStatement, isReexportStatement, isRequireCall, ReexportStatement, RequireCall} from './commonjs_umd_utils'; | ||||||
| import {Esm5ReflectionHost} from './esm5_host'; | import {Esm5ReflectionHost} from './esm5_host'; | ||||||
| import {NgccClassSymbol} from './ngcc_host'; | import {NgccClassSymbol} from './ngcc_host'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,7 +16,12 @@ export interface ExportDeclaration { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface ExportStatement extends ts.ExpressionStatement { | export interface ExportStatement extends ts.ExpressionStatement { | ||||||
|   expression: ts.BinaryExpression&{left: ts.PropertyAccessExpression & {expression: ts.Identifier}}; |   expression: ts.BinaryExpression&{ | ||||||
|  |     left: ts.PropertyAccessExpression & | ||||||
|  |         { | ||||||
|  |           expression: ts.Identifier | ||||||
|  |         } | ||||||
|  |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -34,7 +39,9 @@ export interface ExportStatement extends ts.ExpressionStatement { | |||||||
|  * expression and can be either a `require('...')` call or an identifier (initialized via a |  * expression and can be either a `require('...')` call or an identifier (initialized via a | ||||||
|  * `require('...')` call). |  * `require('...')` call). | ||||||
|  */ |  */ | ||||||
| export interface ReexportStatement extends ts.ExpressionStatement { expression: ts.CallExpression; } | export interface ReexportStatement extends ts.ExpressionStatement { | ||||||
|  |   expression: ts.CallExpression; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| export interface RequireCall extends ts.CallExpression { | export interface RequireCall extends ts.CallExpression { | ||||||
|   arguments: ts.CallExpression['arguments']&[ts.StringLiteral]; |   arguments: ts.CallExpression['arguments']&[ts.StringLiteral]; | ||||||
|  | |||||||
| @ -13,7 +13,8 @@ import {Declaration, Import} from '../../../src/ngtsc/reflection'; | |||||||
| import {Logger} from '../logging/logger'; | import {Logger} from '../logging/logger'; | ||||||
| import {BundleProgram} from '../packages/bundle_program'; | import {BundleProgram} from '../packages/bundle_program'; | ||||||
| import {FactoryMap, getTsHelperFnFromIdentifier, stripExtension} from '../utils'; | import {FactoryMap, getTsHelperFnFromIdentifier, stripExtension} from '../utils'; | ||||||
| import {ExportDeclaration, ExportStatement, ReexportStatement, findNamespaceOfIdentifier, findRequireCallReference, isExportStatement, isReexportStatement, isRequireCall} from './commonjs_umd_utils'; | 
 | ||||||
|  | import {ExportDeclaration, ExportStatement, findNamespaceOfIdentifier, findRequireCallReference, isExportStatement, isReexportStatement, isRequireCall, ReexportStatement} from './commonjs_umd_utils'; | ||||||
| import {Esm5ReflectionHost, stripParentheses} from './esm5_host'; | import {Esm5ReflectionHost, stripParentheses} from './esm5_host'; | ||||||
| 
 | 
 | ||||||
| export class UmdReflectionHost extends Esm5ReflectionHost { | export class UmdReflectionHost extends Esm5ReflectionHost { | ||||||
| @ -61,7 +62,8 @@ export class UmdReflectionHost extends Esm5ReflectionHost { | |||||||
|     return this.umdImportPaths.get(importParameter); |     return this.umdImportPaths.get(importParameter); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** Get the top level statements for a module. |   /** | ||||||
|  |    * Get the top level statements for a module. | ||||||
|    * |    * | ||||||
|    * In UMD modules these are the body of the UMD factory function. |    * In UMD modules these are the body of the UMD factory function. | ||||||
|    * |    * | ||||||
|  | |||||||
| @ -52,7 +52,7 @@ export class AsyncLocker { | |||||||
|         if (attempts === 0) { |         if (attempts === 0) { | ||||||
|           this.logger.info( |           this.logger.info( | ||||||
|               `Another process, with id ${pid}, is currently running ngcc.\n` + |               `Another process, with id ${pid}, is currently running ngcc.\n` + | ||||||
|               `Waiting up to ${this.retryDelay*this.retryAttempts/1000}s for it to finish.`); |               `Waiting up to ${this.retryDelay * this.retryAttempts / 1000}s for it to finish.`); | ||||||
|         } |         } | ||||||
|         // The file is still locked by another process so wait for a bit and retry
 |         // The file is still locked by another process so wait for a bit and retry
 | ||||||
|         await new Promise(resolve => setTimeout(resolve, this.retryDelay)); |         await new Promise(resolve => setTimeout(resolve, this.retryDelay)); | ||||||
| @ -60,7 +60,10 @@ export class AsyncLocker { | |||||||
|     } |     } | ||||||
|     // If we fall out of the loop then we ran out of rety attempts
 |     // If we fall out of the loop then we ran out of rety attempts
 | ||||||
|     throw new Error( |     throw new Error( | ||||||
|         `Timed out waiting ${this.retryAttempts * this.retryDelay/1000}s for another ngcc process, with id ${pid}, to complete.\n` + |         `Timed out waiting ${ | ||||||
|         `(If you are sure no ngcc process is running then you should delete the lock-file at ${this.lockFile.path}.)`); |             this.retryAttempts * this.retryDelay / | ||||||
|  |             1000}s for another ngcc process, with id ${pid}, to complete.\n` +
 | ||||||
|  |         `(If you are sure no ngcc process is running then you should delete the lock-file at ${ | ||||||
|  |             this.lockFile.path}.)`);
 | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -8,8 +8,8 @@ | |||||||
| import {ChildProcess, fork} from 'child_process'; | import {ChildProcess, fork} from 'child_process'; | ||||||
| 
 | 
 | ||||||
| import {AbsoluteFsPath, CachedFileSystem, FileSystem} from '../../../../src/ngtsc/file_system'; | import {AbsoluteFsPath, CachedFileSystem, FileSystem} from '../../../../src/ngtsc/file_system'; | ||||||
| import {LogLevel, Logger} from '../../logging/logger'; | import {Logger, LogLevel} from '../../logging/logger'; | ||||||
| import {LockFile, getLockFilePath} from '../lock_file'; | import {getLockFilePath, LockFile} from '../lock_file'; | ||||||
| 
 | 
 | ||||||
| import {removeLockFile} from './util'; | import {removeLockFile} from './util'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -20,14 +20,14 @@ const fs = new NodeJSFileSystem(); | |||||||
| 
 | 
 | ||||||
| // We create a logger that has the same logging level as the parent process, since it should have
 | // We create a logger that has the same logging level as the parent process, since it should have
 | ||||||
| // been passed through as one of the args
 | // been passed through as one of the args
 | ||||||
| const logLevel = parseInt(process.argv.pop() !, 10); | const logLevel = parseInt(process.argv.pop()!, 10); | ||||||
| const logger = new ConsoleLogger(logLevel); | const logger = new ConsoleLogger(logLevel); | ||||||
| 
 | 
 | ||||||
| // We must store the parent PID now as it changes if the parent process is killed early
 | // We must store the parent PID now as it changes if the parent process is killed early
 | ||||||
| const ppid = process.ppid.toString(); | const ppid = process.ppid.toString(); | ||||||
| 
 | 
 | ||||||
| // The path to the lock-file to remove should have been passed as one of the args
 | // The path to the lock-file to remove should have been passed as one of the args
 | ||||||
| const lockFilePath = fs.resolve(process.argv.pop() !); | const lockFilePath = fs.resolve(process.argv.pop()!); | ||||||
| 
 | 
 | ||||||
| logger.debug(`Starting unlocker at process ${process.pid} on behalf of process ${ppid}`); | logger.debug(`Starting unlocker at process ${process.pid} on behalf of process ${ppid}`); | ||||||
| logger.debug(`The lock-file path is ${lockFilePath}`); | logger.debug(`The lock-file path is ${lockFilePath}`); | ||||||
| @ -36,4 +36,6 @@ logger.debug(`The lock-file path is ${lockFilePath}`); | |||||||
|  * When the parent process exits (for whatever reason) remove the loc-file if it exists and as long |  * When the parent process exits (for whatever reason) remove the loc-file if it exists and as long | ||||||
|  * as it was one that was created by the parent process. |  * as it was one that was created by the parent process. | ||||||
|  */ |  */ | ||||||
| process.on('disconnect', () => { removeLockFile(fs, logger, lockFilePath, ppid); }); | process.on('disconnect', () => { | ||||||
|  |   removeLockFile(fs, logger, lockFilePath, ppid); | ||||||
|  | }); | ||||||
|  | |||||||
| @ -57,6 +57,7 @@ export class SyncLocker { | |||||||
|         `ngcc is already running at process with id ${pid}.\n` + |         `ngcc is already running at process with id ${pid}.\n` + | ||||||
|         `If you are running multiple builds in parallel then you should pre-process your node_modules via the command line ngcc tool before starting the builds;\n` + |         `If you are running multiple builds in parallel then you should pre-process your node_modules via the command line ngcc tool before starting the builds;\n` + | ||||||
|         `See https://v9.angular.io/guide/ivy#speeding-up-ngcc-compilation.\n` + |         `See https://v9.angular.io/guide/ivy#speeding-up-ngcc-compilation.\n` + | ||||||
|         `(If you are sure no ngcc process is running then you should delete the lock-file at ${this.lockFile.path}.)`); |         `(If you are sure no ngcc process is running then you should delete the lock-file at ${ | ||||||
|  |             this.lockFile.path}.)`);
 | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {LogLevel, Logger} from './logger'; | import {Logger, LogLevel} from './logger'; | ||||||
| 
 | 
 | ||||||
| const RESET = '\x1b[0m'; | const RESET = '\x1b[0m'; | ||||||
| const RED = '\x1b[31m'; | const RED = '\x1b[31m'; | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ import * as ts from 'typescript'; | |||||||
| 
 | 
 | ||||||
| import {readConfiguration} from '../..'; | import {readConfiguration} from '../..'; | ||||||
| import {replaceTsWithNgInErrors} from '../../src/ngtsc/diagnostics'; | import {replaceTsWithNgInErrors} from '../../src/ngtsc/diagnostics'; | ||||||
| import {AbsoluteFsPath, FileSystem, absoluteFrom, dirname, getFileSystem, resolve} from '../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath, dirname, FileSystem, getFileSystem, resolve} from '../../src/ngtsc/file_system'; | ||||||
| 
 | 
 | ||||||
| import {CommonJsDependencyHost} from './dependencies/commonjs_dependency_host'; | import {CommonJsDependencyHost} from './dependencies/commonjs_dependency_host'; | ||||||
| import {DependencyResolver, InvalidEntryPoint} from './dependencies/dependency_resolver'; | import {DependencyResolver, InvalidEntryPoint} from './dependencies/dependency_resolver'; | ||||||
| @ -38,10 +38,10 @@ import {AsyncLocker} from './locking/async_locker'; | |||||||
| import {LockFileWithChildProcess} from './locking/lock_file_with_child_process'; | import {LockFileWithChildProcess} from './locking/lock_file_with_child_process'; | ||||||
| import {SyncLocker} from './locking/sync_locker'; | import {SyncLocker} from './locking/sync_locker'; | ||||||
| import {ConsoleLogger} from './logging/console_logger'; | import {ConsoleLogger} from './logging/console_logger'; | ||||||
| import {LogLevel, Logger} from './logging/logger'; | import {Logger, LogLevel} from './logging/logger'; | ||||||
| import {hasBeenProcessed} from './packages/build_marker'; | import {hasBeenProcessed} from './packages/build_marker'; | ||||||
| import {NgccConfiguration} from './packages/configuration'; | import {NgccConfiguration} from './packages/configuration'; | ||||||
| import {EntryPoint, EntryPointJsonProperty, EntryPointPackageJson, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from './packages/entry_point'; | import {EntryPoint, EntryPointJsonProperty, EntryPointPackageJson, getEntryPointFormat, SUPPORTED_FORMAT_PROPERTIES} from './packages/entry_point'; | ||||||
| import {makeEntryPointBundle} from './packages/entry_point_bundle'; | import {makeEntryPointBundle} from './packages/entry_point_bundle'; | ||||||
| import {EntryPointManifest, InvalidatingEntryPointManifest} from './packages/entry_point_manifest'; | import {EntryPointManifest, InvalidatingEntryPointManifest} from './packages/entry_point_manifest'; | ||||||
| import {Transformer} from './packages/transformer'; | import {Transformer} from './packages/transformer'; | ||||||
| @ -164,12 +164,12 @@ export interface SyncNgccOptions { | |||||||
| /** | /** | ||||||
|  * The options to configure the ngcc compiler for asynchronous execution. |  * The options to configure the ngcc compiler for asynchronous execution. | ||||||
|  */ |  */ | ||||||
| export type AsyncNgccOptions = Omit<SyncNgccOptions, 'async'>& {async: true}; | export type AsyncNgccOptions = Omit<SyncNgccOptions, 'async'>&{async: true}; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * The options to configure the ngcc compiler. |  * The options to configure the ngcc compiler. | ||||||
|  */ |  */ | ||||||
| export type NgccOptions = AsyncNgccOptions | SyncNgccOptions; | export type NgccOptions = AsyncNgccOptions|SyncNgccOptions; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * This is the main entry-point into ngcc (aNGular Compatibility Compiler). |  * This is the main entry-point into ngcc (aNGular Compatibility Compiler). | ||||||
| @ -181,12 +181,20 @@ export type NgccOptions = AsyncNgccOptions | SyncNgccOptions; | |||||||
|  */ |  */ | ||||||
| export function mainNgcc(options: AsyncNgccOptions): Promise<void>; | export function mainNgcc(options: AsyncNgccOptions): Promise<void>; | ||||||
| export function mainNgcc(options: SyncNgccOptions): void; | export function mainNgcc(options: SyncNgccOptions): void; | ||||||
| export function mainNgcc( | export function mainNgcc({ | ||||||
|     {basePath, targetEntryPointPath, propertiesToConsider = SUPPORTED_FORMAT_PROPERTIES, |   basePath, | ||||||
|      compileAllFormats = true, createNewEntryPointFormats = false, |   targetEntryPointPath, | ||||||
|      logger = new ConsoleLogger(LogLevel.info), pathMappings, async = false, |   propertiesToConsider = SUPPORTED_FORMAT_PROPERTIES, | ||||||
|      errorOnFailedEntryPoint = false, enableI18nLegacyMessageIdFormat = true, |   compileAllFormats = true, | ||||||
|      invalidateEntryPointManifest = false, tsConfigPath}: NgccOptions): void|Promise<void> { |   createNewEntryPointFormats = false, | ||||||
|  |   logger = new ConsoleLogger(LogLevel.info), | ||||||
|  |   pathMappings, | ||||||
|  |   async = false, | ||||||
|  |   errorOnFailedEntryPoint = false, | ||||||
|  |   enableI18nLegacyMessageIdFormat = true, | ||||||
|  |   invalidateEntryPointManifest = false, | ||||||
|  |   tsConfigPath | ||||||
|  | }: NgccOptions): void|Promise<void> { | ||||||
|   if (!!targetEntryPointPath) { |   if (!!targetEntryPointPath) { | ||||||
|     // targetEntryPointPath forces us to error if an entry-point fails.
 |     // targetEntryPointPath forces us to error if an entry-point fails.
 | ||||||
|     errorOnFailedEntryPoint = true; |     errorOnFailedEntryPoint = true; | ||||||
| @ -279,7 +287,7 @@ export function mainNgcc( | |||||||
|           continue; |           continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const formatPropertiesToMarkAsProcessed = equivalentPropertiesMap.get(formatProperty) !; |         const formatPropertiesToMarkAsProcessed = equivalentPropertiesMap.get(formatProperty)!; | ||||||
|         tasks.push({entryPoint, formatProperty, formatPropertiesToMarkAsProcessed, processDts}); |         tasks.push({entryPoint, formatProperty, formatPropertiesToMarkAsProcessed, processDts}); | ||||||
| 
 | 
 | ||||||
|         // Only process typings for the first property (if not already processed).
 |         // Only process typings for the first property (if not already processed).
 | ||||||
| @ -442,7 +450,7 @@ function getExecutor( | |||||||
| 
 | 
 | ||||||
| function getDependencyResolver( | function getDependencyResolver( | ||||||
|     fileSystem: FileSystem, logger: Logger, config: NgccConfiguration, |     fileSystem: FileSystem, logger: Logger, config: NgccConfiguration, | ||||||
|     pathMappings: PathMappings | undefined): DependencyResolver { |     pathMappings: PathMappings|undefined): DependencyResolver { | ||||||
|   const moduleResolver = new ModuleResolver(fileSystem, pathMappings); |   const moduleResolver = new ModuleResolver(fileSystem, pathMappings); | ||||||
|   const esmDependencyHost = new EsmDependencyHost(fileSystem, moduleResolver); |   const esmDependencyHost = new EsmDependencyHost(fileSystem, moduleResolver); | ||||||
|   const umdDependencyHost = new UmdDependencyHost(fileSystem, moduleResolver); |   const umdDependencyHost = new UmdDependencyHost(fileSystem, moduleResolver); | ||||||
| @ -461,8 +469,8 @@ function getDependencyResolver( | |||||||
| function getEntryPointFinder( | function getEntryPointFinder( | ||||||
|     fs: FileSystem, logger: Logger, resolver: DependencyResolver, config: NgccConfiguration, |     fs: FileSystem, logger: Logger, resolver: DependencyResolver, config: NgccConfiguration, | ||||||
|     entryPointManifest: EntryPointManifest, basePath: AbsoluteFsPath, |     entryPointManifest: EntryPointManifest, basePath: AbsoluteFsPath, | ||||||
|     absoluteTargetEntryPointPath: AbsoluteFsPath | null, |     absoluteTargetEntryPointPath: AbsoluteFsPath|null, | ||||||
|     pathMappings: PathMappings | undefined): EntryPointFinder { |     pathMappings: PathMappings|undefined): EntryPointFinder { | ||||||
|   if (absoluteTargetEntryPointPath !== null) { |   if (absoluteTargetEntryPointPath !== null) { | ||||||
|     return new TargetedEntryPointFinder( |     return new TargetedEntryPointFinder( | ||||||
|         fs, config, logger, resolver, basePath, absoluteTargetEntryPointPath, pathMappings); |         fs, config, logger, resolver, basePath, absoluteTargetEntryPointPath, pathMappings); | ||||||
| @ -533,7 +541,7 @@ function getPropertiesToProcess( | |||||||
| 
 | 
 | ||||||
|   const equivalentPropertiesMap = new Map<EntryPointJsonProperty, EntryPointJsonProperty[]>(); |   const equivalentPropertiesMap = new Map<EntryPointJsonProperty, EntryPointJsonProperty[]>(); | ||||||
|   for (const prop of propertiesToConsider) { |   for (const prop of propertiesToConsider) { | ||||||
|     const formatPath = packageJson[prop] !; |     const formatPath = packageJson[prop]!; | ||||||
|     const equivalentProperties = formatPathToProperties[formatPath]; |     const equivalentProperties = formatPathToProperties[formatPath]; | ||||||
|     equivalentPropertiesMap.set(prop, equivalentProperties); |     equivalentPropertiesMap.set(prop, equivalentProperties); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -102,7 +102,7 @@ function migrateProviders(metadata: ResolvedValueMap, field: string, host: Migra | |||||||
|   if (!metadata.has(field)) { |   if (!metadata.has(field)) { | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   const providers = metadata.get(field) !; |   const providers = metadata.get(field)!; | ||||||
|   if (!Array.isArray(providers)) { |   if (!Array.isArray(providers)) { | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| @ -127,10 +127,10 @@ function migrateProvider(provider: ResolvedValue, host: MigrationHost): void { | |||||||
|       // as the provider itself configures 'deps'. Only if 'deps' is missing will this require a
 |       // as the provider itself configures 'deps'. Only if 'deps' is missing will this require a
 | ||||||
|       // factory to exist on SomeClass.
 |       // factory to exist on SomeClass.
 | ||||||
|       if (!provider.has('deps')) { |       if (!provider.has('deps')) { | ||||||
|         migrateProviderClass(provider.get('useClass') !, host); |         migrateProviderClass(provider.get('useClass')!, host); | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       migrateProviderClass(provider.get('provide') !, host); |       migrateProviderClass(provider.get('provide')!, host); | ||||||
|     } |     } | ||||||
|   } else if (Array.isArray(provider)) { |   } else if (Array.isArray(provider)) { | ||||||
|     for (const v of provider) { |     for (const v of provider) { | ||||||
|  | |||||||
| @ -43,7 +43,7 @@ export function hasConstructor(host: MigrationHost, clazz: ClassDeclaration): bo | |||||||
|  */ |  */ | ||||||
| export function createDirectiveDecorator( | export function createDirectiveDecorator( | ||||||
|     clazz: ClassDeclaration, |     clazz: ClassDeclaration, | ||||||
|     metadata?: {selector: string | null, exportAs: string[] | null}): Decorator { |     metadata?: {selector: string|null, exportAs: string[]|null}): Decorator { | ||||||
|   const args: ts.Expression[] = []; |   const args: ts.Expression[] = []; | ||||||
|   if (metadata !== undefined) { |   if (metadata !== undefined) { | ||||||
|     const metaArgs: ts.PropertyAssignment[] = []; |     const metaArgs: ts.PropertyAssignment[] = []; | ||||||
| @ -60,7 +60,8 @@ export function createDirectiveDecorator( | |||||||
|     identifier: null, |     identifier: null, | ||||||
|     import: {name: 'Directive', from: '@angular/core'}, |     import: {name: 'Directive', from: '@angular/core'}, | ||||||
|     node: null, |     node: null, | ||||||
|     synthesizedFor: clazz.name, args, |     synthesizedFor: clazz.name, | ||||||
|  |     args, | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -69,7 +70,7 @@ export function createDirectiveDecorator( | |||||||
|  */ |  */ | ||||||
| export function createComponentDecorator( | export function createComponentDecorator( | ||||||
|     clazz: ClassDeclaration, |     clazz: ClassDeclaration, | ||||||
|     metadata: {selector: string | null, exportAs: string[] | null}): Decorator { |     metadata: {selector: string|null, exportAs: string[]|null}): Decorator { | ||||||
|   const metaArgs: ts.PropertyAssignment[] = [ |   const metaArgs: ts.PropertyAssignment[] = [ | ||||||
|     property('template', ''), |     property('template', ''), | ||||||
|   ]; |   ]; | ||||||
| @ -127,5 +128,5 @@ function reifySourceFile(expr: ts.Expression): ts.Expression { | |||||||
|   if (!ts.isVariableStatement(stmt)) { |   if (!ts.isVariableStatement(stmt)) { | ||||||
|     throw new Error(`Expected VariableStatement, got ${ts.SyntaxKind[stmt.kind]}`); |     throw new Error(`Expected VariableStatement, got ${ts.SyntaxKind[stmt.kind]}`); | ||||||
|   } |   } | ||||||
|   return stmt.declarationList.declarations[0].initializer !; |   return stmt.declarationList.declarations[0].initializer!; | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,17 +6,19 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| import {AbsoluteFsPath, FileSystem, dirname, resolve} from '../../../src/ngtsc/file_system'; | 
 | ||||||
|  | import {AbsoluteFsPath, dirname, FileSystem, resolve} from '../../../src/ngtsc/file_system'; | ||||||
|  | 
 | ||||||
| import {patchTsGetExpandoInitializer, restoreGetExpandoInitializer} from './patch_ts_expando_initializer'; | import {patchTsGetExpandoInitializer, restoreGetExpandoInitializer} from './patch_ts_expando_initializer'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| * An entry point bundle contains one or two programs, e.g. `src` and `dts`, |  * An entry point bundle contains one or two programs, e.g. `src` and `dts`, | ||||||
| * that are compiled via TypeScript. |  * that are compiled via TypeScript. | ||||||
| * |  * | ||||||
| * To aid with processing the program, this interface exposes the program itself, |  * To aid with processing the program, this interface exposes the program itself, | ||||||
| * as well as path and TS file of the entry-point to the program and the r3Symbols |  * as well as path and TS file of the entry-point to the program and the r3Symbols | ||||||
| * file, if appropriate. |  * file, if appropriate. | ||||||
| */ |  */ | ||||||
| export interface BundleProgram { | export interface BundleProgram { | ||||||
|   program: ts.Program; |   program: ts.Program; | ||||||
|   options: ts.CompilerOptions; |   options: ts.CompilerOptions; | ||||||
| @ -46,7 +48,7 @@ export function makeBundleProgram( | |||||||
|   program.getTypeChecker(); |   program.getTypeChecker(); | ||||||
|   restoreGetExpandoInitializer(originalGetExpandoInitializer); |   restoreGetExpandoInitializer(originalGetExpandoInitializer); | ||||||
| 
 | 
 | ||||||
|   const file = program.getSourceFile(path) !; |   const file = program.getSourceFile(path)!; | ||||||
|   const r3SymbolsFile = r3SymbolsPath && program.getSourceFile(r3SymbolsPath) || null; |   const r3SymbolsFile = r3SymbolsPath && program.getSourceFile(r3SymbolsPath) || null; | ||||||
| 
 | 
 | ||||||
|   return {program, options, host, package: pkg, path, file, r3SymbolsPath, r3SymbolsFile}; |   return {program, options, host, package: pkg, path, file, r3SymbolsPath, r3SymbolsFile}; | ||||||
|  | |||||||
| @ -8,7 +8,9 @@ | |||||||
| import {createHash} from 'crypto'; | import {createHash} from 'crypto'; | ||||||
| import {satisfies} from 'semver'; | import {satisfies} from 'semver'; | ||||||
| import * as vm from 'vm'; | import * as vm from 'vm'; | ||||||
| import {AbsoluteFsPath, FileSystem, dirname, join, resolve} from '../../../src/ngtsc/file_system'; | 
 | ||||||
|  | import {AbsoluteFsPath, dirname, FileSystem, join, resolve} from '../../../src/ngtsc/file_system'; | ||||||
|  | 
 | ||||||
| import {PackageJsonFormatPropertiesMap} from './entry_point'; | import {PackageJsonFormatPropertiesMap} from './entry_point'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -178,7 +180,7 @@ export class NgccConfiguration { | |||||||
|   getConfig(packagePath: AbsoluteFsPath, version: string|null): VersionedPackageConfig { |   getConfig(packagePath: AbsoluteFsPath, version: string|null): VersionedPackageConfig { | ||||||
|     const cacheKey = packagePath + (version !== null ? `@${version}` : ''); |     const cacheKey = packagePath + (version !== null ? `@${version}` : ''); | ||||||
|     if (this.cache.has(cacheKey)) { |     if (this.cache.has(cacheKey)) { | ||||||
|       return this.cache.get(cacheKey) !; |       return this.cache.get(cacheKey)!; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const projectLevelConfig = |     const projectLevelConfig = | ||||||
| @ -256,7 +258,8 @@ export class NgccConfiguration { | |||||||
|     const theExports = {}; |     const theExports = {}; | ||||||
|     const sandbox = { |     const sandbox = { | ||||||
|       module: {exports: theExports}, |       module: {exports: theExports}, | ||||||
|       exports: theExports, require, |       exports: theExports, | ||||||
|  |       require, | ||||||
|       __dirname: dirname(srcPath), |       __dirname: dirname(srcPath), | ||||||
|       __filename: srcPath |       __filename: srcPath | ||||||
|     }; |     }; | ||||||
| @ -292,9 +295,8 @@ export class NgccConfiguration { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function findSatisfactoryVersion( | function findSatisfactoryVersion(configs: VersionedPackageConfig[]|undefined, version: string|null): | ||||||
|     configs: VersionedPackageConfig[] | undefined, version: string | null): VersionedPackageConfig| |     VersionedPackageConfig|null { | ||||||
|     null { |  | ||||||
|   if (configs === undefined) { |   if (configs === undefined) { | ||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ import {NgccConfiguration, NgccEntryPointConfig} from './configuration'; | |||||||
| /** | /** | ||||||
|  * The possible values for the format of an entry-point. |  * The possible values for the format of an entry-point. | ||||||
|  */ |  */ | ||||||
| export type EntryPointFormat = 'esm5' | 'esm2015' | 'umd' | 'commonjs'; | export type EntryPointFormat = 'esm5'|'esm2015'|'umd'|'commonjs'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * An object containing information about an entry-point, including paths |  * An object containing information about an entry-point, including paths | ||||||
| @ -42,10 +42,12 @@ export interface EntryPoint extends JsonObject { | |||||||
|   generateDeepReexports: boolean; |   generateDeepReexports: boolean; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export type JsonPrimitive = string | number | boolean | null; | export type JsonPrimitive = string|number|boolean|null; | ||||||
| export type JsonValue = JsonPrimitive | JsonArray | JsonObject | undefined; | export type JsonValue = JsonPrimitive|JsonArray|JsonObject|undefined; | ||||||
| export interface JsonArray extends Array<JsonValue> {} | export interface JsonArray extends Array<JsonValue> {} | ||||||
| export interface JsonObject { [key: string]: JsonValue; } | export interface JsonObject { | ||||||
|  |   [key: string]: JsonValue; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| export interface PackageJsonFormatPropertiesMap { | export interface PackageJsonFormatPropertiesMap { | ||||||
|   fesm2015?: string; |   fesm2015?: string; | ||||||
| @ -97,8 +99,7 @@ export const INCOMPATIBLE_ENTRY_POINT = 'incompatible-entry-point'; | |||||||
|  * * INCOMPATIBLE_ENTRY_POINT - the path was a non-processable entry-point that should be searched |  * * INCOMPATIBLE_ENTRY_POINT - the path was a non-processable entry-point that should be searched | ||||||
|  * for sub-entry-points |  * for sub-entry-points | ||||||
|  */ |  */ | ||||||
| export type GetEntryPointResult = | export type GetEntryPointResult = EntryPoint|typeof INCOMPATIBLE_ENTRY_POINT|typeof NO_ENTRY_POINT; | ||||||
|     EntryPoint | typeof INCOMPATIBLE_ENTRY_POINT | typeof NO_ENTRY_POINT; |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -161,7 +162,8 @@ export function getEntryPointInfo( | |||||||
|     packageJson: entryPointPackageJson, |     packageJson: entryPointPackageJson, | ||||||
|     package: packagePath, |     package: packagePath, | ||||||
|     path: entryPointPath, |     path: entryPointPath, | ||||||
|     typings: resolve(entryPointPath, typings), compiledByAngular, |     typings: resolve(entryPointPath, typings), | ||||||
|  |     compiledByAngular, | ||||||
|     ignoreMissingDependencies: |     ignoreMissingDependencies: | ||||||
|         entryPointConfig !== undefined ? !!entryPointConfig.ignoreMissingDependencies : false, |         entryPointConfig !== undefined ? !!entryPointConfig.ignoreMissingDependencies : false, | ||||||
|     generateDeepReexports: |     generateDeepReexports: | ||||||
| @ -236,7 +238,7 @@ function isUmdModule(fs: FileSystem, sourceFilePath: AbsoluteFsPath): boolean { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function mergeConfigAndPackageJson( | function mergeConfigAndPackageJson( | ||||||
|     entryPointPackageJson: EntryPointPackageJson | null, entryPointConfig: NgccEntryPointConfig, |     entryPointPackageJson: EntryPointPackageJson|null, entryPointConfig: NgccEntryPointConfig, | ||||||
|     packagePath: AbsoluteFsPath, entryPointPath: AbsoluteFsPath): EntryPointPackageJson { |     packagePath: AbsoluteFsPath, entryPointPath: AbsoluteFsPath): EntryPointPackageJson { | ||||||
|   if (entryPointPackageJson !== null) { |   if (entryPointPackageJson !== null) { | ||||||
|     return {...entryPointPackageJson, ...entryPointConfig.override}; |     return {...entryPointPackageJson, ...entryPointConfig.override}; | ||||||
|  | |||||||
| @ -48,10 +48,8 @@ export function makeEntryPointBundle( | |||||||
|     enableI18nLegacyMessageIdFormat: boolean = true): EntryPointBundle { |     enableI18nLegacyMessageIdFormat: boolean = true): EntryPointBundle { | ||||||
|   // Create the TS program and necessary helpers.
 |   // Create the TS program and necessary helpers.
 | ||||||
|   const rootDir = entryPoint.package; |   const rootDir = entryPoint.package; | ||||||
|   const options: ts.CompilerOptions = { |   const options: ts | ||||||
|     allowJs: true, |       .CompilerOptions = {allowJs: true, maxNodeModuleJsDepth: Infinity, rootDir, ...pathMappings}; | ||||||
|     maxNodeModuleJsDepth: Infinity, rootDir, ...pathMappings |  | ||||||
|   }; |  | ||||||
|   const srcHost = new NgccSourcesCompilerHost(fs, options, entryPoint.path); |   const srcHost = new NgccSourcesCompilerHost(fs, options, entryPoint.path); | ||||||
|   const dtsHost = new NgtscCompilerHost(fs, options); |   const dtsHost = new NgtscCompilerHost(fs, options); | ||||||
| 
 | 
 | ||||||
| @ -72,7 +70,12 @@ export function makeEntryPointBundle( | |||||||
|   return { |   return { | ||||||
|     entryPoint, |     entryPoint, | ||||||
|     format, |     format, | ||||||
|     rootDirs: [rootDir], isCore, isFlatCore, src, dts, enableI18nLegacyMessageIdFormat |     rootDirs: [rootDir], | ||||||
|  |     isCore, | ||||||
|  |     isFlatCore, | ||||||
|  |     src, | ||||||
|  |     dts, | ||||||
|  |     enableI18nLegacyMessageIdFormat | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ import {Logger} from '../logging/logger'; | |||||||
| 
 | 
 | ||||||
| import {NGCC_VERSION} from './build_marker'; | import {NGCC_VERSION} from './build_marker'; | ||||||
| import {NgccConfiguration} from './configuration'; | import {NgccConfiguration} from './configuration'; | ||||||
| import {EntryPoint, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT, getEntryPointInfo} from './entry_point'; | import {EntryPoint, getEntryPointInfo, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT} from './entry_point'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Manages reading and writing a manifest file that contains a list of all the entry-points that |  * Manages reading and writing a manifest file that contains a list of all the entry-points that | ||||||
| @ -63,8 +63,8 @@ export class EntryPointManifest { | |||||||
|         return null; |         return null; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       this.logger.debug( |       this.logger.debug(`Entry-point manifest found for ${ | ||||||
|           `Entry-point manifest found for ${basePath} so loading entry-point information directly.`); |           basePath} so loading entry-point information directly.`);
 | ||||||
|       const startTime = Date.now(); |       const startTime = Date.now(); | ||||||
| 
 | 
 | ||||||
|       const entryPoints: EntryPoint[] = []; |       const entryPoints: EntryPoint[] = []; | ||||||
| @ -72,8 +72,9 @@ export class EntryPointManifest { | |||||||
|         const result = |         const result = | ||||||
|             getEntryPointInfo(this.fs, this.config, this.logger, packagePath, entryPointPath); |             getEntryPointInfo(this.fs, this.config, this.logger, packagePath, entryPointPath); | ||||||
|         if (result === NO_ENTRY_POINT || result === INCOMPATIBLE_ENTRY_POINT) { |         if (result === NO_ENTRY_POINT || result === INCOMPATIBLE_ENTRY_POINT) { | ||||||
|           throw new Error( |           throw new Error(`The entry-point manifest at ${ | ||||||
|               `The entry-point manifest at ${manifestPath} contained an invalid pair of package paths: [${packagePath}, ${entryPointPath}]`); |               manifestPath} contained an invalid pair of package paths: [${packagePath}, ${ | ||||||
|  |               entryPointPath}]`);
 | ||||||
|         } else { |         } else { | ||||||
|           entryPoints.push(result); |           entryPoints.push(result); | ||||||
|         } |         } | ||||||
| @ -142,7 +143,9 @@ export class EntryPointManifest { | |||||||
|  * called. |  * called. | ||||||
|  */ |  */ | ||||||
| export class InvalidatingEntryPointManifest extends EntryPointManifest { | export class InvalidatingEntryPointManifest extends EntryPointManifest { | ||||||
|   readEntryPointsUsingManifest(basePath: AbsoluteFsPath): EntryPoint[]|null { return null; } |   readEntryPointsUsingManifest(basePath: AbsoluteFsPath): EntryPoint[]|null { | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -58,13 +58,12 @@ export function patchTsGetExpandoInitializer(): unknown { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // Override the function to add support for recognizing the IIFE structure used in ES5 bundles.
 |   // Override the function to add support for recognizing the IIFE structure used in ES5 bundles.
 | ||||||
|   (ts as any).getExpandoInitializer = |   (ts as any).getExpandoInitializer = (initializer: ts.Node, | ||||||
|       (initializer: ts.Node, isPrototypeAssignment: boolean): ts.Expression | undefined => { |                                        isPrototypeAssignment: boolean): ts.Expression|undefined => { | ||||||
|     // If the initializer is a call expression within parenthesis, unwrap the parenthesis
 |     // If the initializer is a call expression within parenthesis, unwrap the parenthesis
 | ||||||
|     // upfront such that unsupported IIFE syntax `(function(){}())` becomes `function(){}()`,
 |     // upfront such that unsupported IIFE syntax `(function(){}())` becomes `function(){}()`,
 | ||||||
|     // which is supported.
 |     // which is supported.
 | ||||||
|         if (ts.isParenthesizedExpression(initializer) && |     if (ts.isParenthesizedExpression(initializer) && ts.isCallExpression(initializer.expression)) { | ||||||
|             ts.isCallExpression(initializer.expression)) { |  | ||||||
|       initializer = initializer.expression; |       initializer = initializer.expression; | ||||||
|     } |     } | ||||||
|     return originalGetExpandoInitializer(initializer, isPrototypeAssignment); |     return originalGetExpandoInitializer(initializer, isPrototypeAssignment); | ||||||
| @ -125,16 +124,36 @@ function checkIfExpandoPropertyIsPresent(): boolean { | |||||||
|   const sourceFile = |   const sourceFile = | ||||||
|       ts.createSourceFile('test.js', sourceText, ts.ScriptTarget.ES5, true, ts.ScriptKind.JS); |       ts.createSourceFile('test.js', sourceText, ts.ScriptTarget.ES5, true, ts.ScriptKind.JS); | ||||||
|   const host: ts.CompilerHost = { |   const host: ts.CompilerHost = { | ||||||
|     getSourceFile(): ts.SourceFile | undefined{return sourceFile;}, |     getSourceFile(): ts.SourceFile | | ||||||
|     fileExists(): boolean{return true;}, |         undefined { | ||||||
|     readFile(): string | undefined{return '';}, |           return sourceFile; | ||||||
|  |         }, | ||||||
|  |     fileExists(): boolean { | ||||||
|  |       return true; | ||||||
|  |     }, | ||||||
|  |     readFile(): string | | ||||||
|  |         undefined { | ||||||
|  |           return ''; | ||||||
|  |         }, | ||||||
|     writeFile() {}, |     writeFile() {}, | ||||||
|     getDefaultLibFileName(): string{return '';}, |     getDefaultLibFileName(): string { | ||||||
|     getCurrentDirectory(): string{return '';}, |       return ''; | ||||||
|     getDirectories(): string[]{return [];}, |     }, | ||||||
|     getCanonicalFileName(fileName: string): string{return fileName;}, |     getCurrentDirectory(): string { | ||||||
|     useCaseSensitiveFileNames(): boolean{return true;}, |       return ''; | ||||||
|     getNewLine(): string{return '\n';}, |     }, | ||||||
|  |     getDirectories(): string[] { | ||||||
|  |       return []; | ||||||
|  |     }, | ||||||
|  |     getCanonicalFileName(fileName: string): string { | ||||||
|  |       return fileName; | ||||||
|  |     }, | ||||||
|  |     useCaseSensitiveFileNames(): boolean { | ||||||
|  |       return true; | ||||||
|  |     }, | ||||||
|  |     getNewLine(): string { | ||||||
|  |       return '\n'; | ||||||
|  |     }, | ||||||
|   }; |   }; | ||||||
|   const options = {noResolve: true, noLib: true, noEmit: true, allowJs: true}; |   const options = {noResolve: true, noLib: true, noEmit: true, allowJs: true}; | ||||||
|   const program = ts.createProgram(['test.js'], options, host); |   const program = ts.createProgram(['test.js'], options, host); | ||||||
|  | |||||||
| @ -36,8 +36,7 @@ import {EntryPointBundle} from './entry_point_bundle'; | |||||||
| 
 | 
 | ||||||
| export type TransformResult = { | export type TransformResult = { | ||||||
|   success: true; diagnostics: ts.Diagnostic[]; transformedFiles: FileToWrite[]; |   success: true; diagnostics: ts.Diagnostic[]; transformedFiles: FileToWrite[]; | ||||||
| } | | }|{ | ||||||
| { |  | ||||||
|   success: false; |   success: false; | ||||||
|   diagnostics: ts.Diagnostic[]; |   diagnostics: ts.Diagnostic[]; | ||||||
| }; | }; | ||||||
| @ -79,8 +78,13 @@ export class Transformer { | |||||||
|     const reflectionHost = new DelegatingReflectionHost(tsReflectionHost, ngccReflectionHost); |     const reflectionHost = new DelegatingReflectionHost(tsReflectionHost, ngccReflectionHost); | ||||||
| 
 | 
 | ||||||
|     // Parse and analyze the files.
 |     // Parse and analyze the files.
 | ||||||
|     const {decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses, |     const { | ||||||
|            moduleWithProvidersAnalyses, diagnostics} = this.analyzeProgram(reflectionHost, bundle); |       decorationAnalyses, | ||||||
|  |       switchMarkerAnalyses, | ||||||
|  |       privateDeclarationsAnalyses, | ||||||
|  |       moduleWithProvidersAnalyses, | ||||||
|  |       diagnostics | ||||||
|  |     } = this.analyzeProgram(reflectionHost, bundle); | ||||||
| 
 | 
 | ||||||
|     // Bail if the analysis produced any errors.
 |     // Bail if the analysis produced any errors.
 | ||||||
|     if (hasErrors(diagnostics)) { |     if (hasErrors(diagnostics)) { | ||||||
| @ -162,8 +166,13 @@ export class Transformer { | |||||||
|     const privateDeclarationsAnalyses = |     const privateDeclarationsAnalyses = | ||||||
|         privateDeclarationsAnalyzer.analyzeProgram(bundle.src.program); |         privateDeclarationsAnalyzer.analyzeProgram(bundle.src.program); | ||||||
| 
 | 
 | ||||||
|     return {decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses, |     return { | ||||||
|             moduleWithProvidersAnalyses, diagnostics}; |       decorationAnalyses, | ||||||
|  |       switchMarkerAnalyses, | ||||||
|  |       privateDeclarationsAnalyses, | ||||||
|  |       moduleWithProvidersAnalyses, | ||||||
|  |       diagnostics | ||||||
|  |     }; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,13 +6,15 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {dirname, relative} from 'canonical-path'; | import {dirname, relative} from 'canonical-path'; | ||||||
| import * as ts from 'typescript'; |  | ||||||
| import MagicString from 'magic-string'; | import MagicString from 'magic-string'; | ||||||
|  | import * as ts from 'typescript'; | ||||||
|  | 
 | ||||||
| import {Reexport} from '../../../src/ngtsc/imports'; | import {Reexport} from '../../../src/ngtsc/imports'; | ||||||
| import {Import, ImportManager} from '../../../src/ngtsc/translator'; | import {Import, ImportManager} from '../../../src/ngtsc/translator'; | ||||||
| import {ExportInfo} from '../analysis/private_declarations_analyzer'; | import {ExportInfo} from '../analysis/private_declarations_analyzer'; | ||||||
| import {isRequireCall} from '../host/commonjs_umd_utils'; | import {isRequireCall} from '../host/commonjs_umd_utils'; | ||||||
| import {NgccReflectionHost} from '../host/ngcc_host'; | import {NgccReflectionHost} from '../host/ngcc_host'; | ||||||
|  | 
 | ||||||
| import {Esm5RenderingFormatter} from './esm5_rendering_formatter'; | import {Esm5RenderingFormatter} from './esm5_rendering_formatter'; | ||||||
| import {stripExtension} from './utils'; | import {stripExtension} from './utils'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -7,20 +7,22 @@ | |||||||
|  */ |  */ | ||||||
| import MagicString from 'magic-string'; | import MagicString from 'magic-string'; | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
|  | 
 | ||||||
| import {FileSystem} from '../../../src/ngtsc/file_system'; | import {FileSystem} from '../../../src/ngtsc/file_system'; | ||||||
| import {Reexport} from '../../../src/ngtsc/imports'; | import {Reexport} from '../../../src/ngtsc/imports'; | ||||||
| import {CompileResult} from '../../../src/ngtsc/transform'; | import {CompileResult} from '../../../src/ngtsc/transform'; | ||||||
| import {translateType, ImportManager} from '../../../src/ngtsc/translator'; | import {ImportManager, translateType} from '../../../src/ngtsc/translator'; | ||||||
|  | import {ModuleWithProvidersAnalyses, ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer'; | ||||||
|  | import {ExportInfo, PrivateDeclarationsAnalyses} from '../analysis/private_declarations_analyzer'; | ||||||
| import {DecorationAnalyses} from '../analysis/types'; | import {DecorationAnalyses} from '../analysis/types'; | ||||||
| import {ModuleWithProvidersInfo, ModuleWithProvidersAnalyses} from '../analysis/module_with_providers_analyzer'; |  | ||||||
| import {PrivateDeclarationsAnalyses, ExportInfo} from '../analysis/private_declarations_analyzer'; |  | ||||||
| import {IMPORT_PREFIX} from '../constants'; | import {IMPORT_PREFIX} from '../constants'; | ||||||
| import {NgccReflectionHost} from '../host/ngcc_host'; | import {NgccReflectionHost} from '../host/ngcc_host'; | ||||||
| import {EntryPointBundle} from '../packages/entry_point_bundle'; |  | ||||||
| import {Logger} from '../logging/logger'; | import {Logger} from '../logging/logger'; | ||||||
| import {FileToWrite, getImportRewriter} from './utils'; | import {EntryPointBundle} from '../packages/entry_point_bundle'; | ||||||
|  | 
 | ||||||
| import {RenderingFormatter} from './rendering_formatter'; | import {RenderingFormatter} from './rendering_formatter'; | ||||||
| import {renderSourceAndMap} from './source_maps'; | import {renderSourceAndMap} from './source_maps'; | ||||||
|  | import {FileToWrite, getImportRewriter} from './utils'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A structure that captures information about what needs to be rendered |  * A structure that captures information about what needs to be rendered | ||||||
| @ -84,7 +86,7 @@ export class DtsRenderer { | |||||||
|     const outputText = new MagicString(dtsFile.text); |     const outputText = new MagicString(dtsFile.text); | ||||||
|     const printer = ts.createPrinter(); |     const printer = ts.createPrinter(); | ||||||
|     const importManager = new ImportManager( |     const importManager = new ImportManager( | ||||||
|         getImportRewriter(this.bundle.dts !.r3SymbolsFile, this.bundle.isCore, false), |         getImportRewriter(this.bundle.dts!.r3SymbolsFile, this.bundle.isCore, false), | ||||||
|         IMPORT_PREFIX); |         IMPORT_PREFIX); | ||||||
| 
 | 
 | ||||||
|     renderInfo.classInfo.forEach(dtsClass => { |     renderInfo.classInfo.forEach(dtsClass => { | ||||||
| @ -129,7 +131,7 @@ export class DtsRenderer { | |||||||
|         const dtsDeclaration = this.host.getDtsDeclaration(compiledClass.declaration); |         const dtsDeclaration = this.host.getDtsDeclaration(compiledClass.declaration); | ||||||
|         if (dtsDeclaration) { |         if (dtsDeclaration) { | ||||||
|           const dtsFile = dtsDeclaration.getSourceFile(); |           const dtsFile = dtsDeclaration.getSourceFile(); | ||||||
|           const renderInfo = dtsMap.has(dtsFile) ? dtsMap.get(dtsFile) ! : new DtsRenderInfo(); |           const renderInfo = dtsMap.has(dtsFile) ? dtsMap.get(dtsFile)! : new DtsRenderInfo(); | ||||||
|           renderInfo.classInfo.push({dtsDeclaration, compilation: compiledClass.compilation}); |           renderInfo.classInfo.push({dtsDeclaration, compilation: compiledClass.compilation}); | ||||||
|           // Only add re-exports if the .d.ts tree is overlayed with the .js tree, as re-exports in
 |           // Only add re-exports if the .d.ts tree is overlayed with the .js tree, as re-exports in
 | ||||||
|           // ngcc are only used to support deep imports into e.g. commonjs code. For a deep import
 |           // ngcc are only used to support deep imports into e.g. commonjs code. For a deep import
 | ||||||
| @ -150,7 +152,7 @@ export class DtsRenderer { | |||||||
|     // Capture the ModuleWithProviders functions/methods that need updating
 |     // Capture the ModuleWithProviders functions/methods that need updating
 | ||||||
|     if (moduleWithProvidersAnalyses !== null) { |     if (moduleWithProvidersAnalyses !== null) { | ||||||
|       moduleWithProvidersAnalyses.forEach((moduleWithProvidersToFix, dtsFile) => { |       moduleWithProvidersAnalyses.forEach((moduleWithProvidersToFix, dtsFile) => { | ||||||
|         const renderInfo = dtsMap.has(dtsFile) ? dtsMap.get(dtsFile) ! : new DtsRenderInfo(); |         const renderInfo = dtsMap.has(dtsFile) ? dtsMap.get(dtsFile)! : new DtsRenderInfo(); | ||||||
|         renderInfo.moduleWithProviders = moduleWithProvidersToFix; |         renderInfo.moduleWithProviders = moduleWithProvidersToFix; | ||||||
|         dtsMap.set(dtsFile, renderInfo); |         dtsMap.set(dtsFile, renderInfo); | ||||||
|       }); |       }); | ||||||
| @ -167,9 +169,9 @@ export class DtsRenderer { | |||||||
|               `The simplest fix for this is to ensure that this class is exported from the package's entry-point.`); |               `The simplest fix for this is to ensure that this class is exported from the package's entry-point.`); | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|       const dtsEntryPoint = this.bundle.dts !.file; |       const dtsEntryPoint = this.bundle.dts!.file; | ||||||
|       const renderInfo = |       const renderInfo = | ||||||
|           dtsMap.has(dtsEntryPoint) ? dtsMap.get(dtsEntryPoint) ! : new DtsRenderInfo(); |           dtsMap.has(dtsEntryPoint) ? dtsMap.get(dtsEntryPoint)! : new DtsRenderInfo(); | ||||||
|       renderInfo.privateExports = privateDeclarationsAnalyses; |       renderInfo.privateExports = privateDeclarationsAnalyses; | ||||||
|       dtsMap.set(dtsEntryPoint, renderInfo); |       dtsMap.set(dtsEntryPoint, renderInfo); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -25,14 +25,14 @@ export class Esm5RenderingFormatter extends EsmRenderingFormatter { | |||||||
|   addDefinitions(output: MagicString, compiledClass: CompiledClass, definitions: string): void { |   addDefinitions(output: MagicString, compiledClass: CompiledClass, definitions: string): void { | ||||||
|     const iifeBody = getIifeBody(compiledClass.declaration); |     const iifeBody = getIifeBody(compiledClass.declaration); | ||||||
|     if (!iifeBody) { |     if (!iifeBody) { | ||||||
|       throw new Error( |       throw new Error(`Compiled class declaration is not inside an IIFE: ${compiledClass.name} in ${ | ||||||
|           `Compiled class declaration is not inside an IIFE: ${compiledClass.name} in ${compiledClass.declaration.getSourceFile().fileName}`); |           compiledClass.declaration.getSourceFile().fileName}`);
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const returnStatement = iifeBody.statements.find(ts.isReturnStatement); |     const returnStatement = iifeBody.statements.find(ts.isReturnStatement); | ||||||
|     if (!returnStatement) { |     if (!returnStatement) { | ||||||
|       throw new Error( |       throw new Error(`Compiled class wrapper IIFE does not have a return statement: ${ | ||||||
|           `Compiled class wrapper IIFE does not have a return statement: ${compiledClass.name} in ${compiledClass.declaration.getSourceFile().fileName}`); |           compiledClass.name} in ${compiledClass.declaration.getSourceFile().fileName}`);
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const insertionPoint = returnStatement.getFullStart(); |     const insertionPoint = returnStatement.getFullStart(); | ||||||
|  | |||||||
| @ -8,17 +8,19 @@ | |||||||
| import {Statement} from '@angular/compiler'; | import {Statement} from '@angular/compiler'; | ||||||
| import MagicString from 'magic-string'; | import MagicString from 'magic-string'; | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| import {relative, dirname, AbsoluteFsPath, absoluteFromSourceFile} from '../../../src/ngtsc/file_system'; | 
 | ||||||
|  | import {absoluteFromSourceFile, AbsoluteFsPath, dirname, relative} from '../../../src/ngtsc/file_system'; | ||||||
| import {NOOP_DEFAULT_IMPORT_RECORDER, Reexport} from '../../../src/ngtsc/imports'; | import {NOOP_DEFAULT_IMPORT_RECORDER, Reexport} from '../../../src/ngtsc/imports'; | ||||||
| import {Import, ImportManager, translateStatement} from '../../../src/ngtsc/translator'; | import {Import, ImportManager, translateStatement} from '../../../src/ngtsc/translator'; | ||||||
| import {isDtsPath} from '../../../src/ngtsc/util/src/typescript'; | import {isDtsPath} from '../../../src/ngtsc/util/src/typescript'; | ||||||
| import {CompiledClass} from '../analysis/types'; |  | ||||||
| import {NgccReflectionHost, POST_R3_MARKER, PRE_R3_MARKER, SwitchableVariableDeclaration} from '../host/ngcc_host'; |  | ||||||
| import {ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer'; | import {ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer'; | ||||||
| import {ExportInfo} from '../analysis/private_declarations_analyzer'; | import {ExportInfo} from '../analysis/private_declarations_analyzer'; | ||||||
| import {RenderingFormatter, RedundantDecoratorMap} from './rendering_formatter'; | import {CompiledClass} from '../analysis/types'; | ||||||
| import {stripExtension} from './utils'; |  | ||||||
| import {isAssignment} from '../host/esm2015_host'; | import {isAssignment} from '../host/esm2015_host'; | ||||||
|  | import {NgccReflectionHost, POST_R3_MARKER, PRE_R3_MARKER, SwitchableVariableDeclaration} from '../host/ngcc_host'; | ||||||
|  | 
 | ||||||
|  | import {RedundantDecoratorMap, RenderingFormatter} from './rendering_formatter'; | ||||||
|  | import {stripExtension} from './utils'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A RenderingFormatter that works with ECMAScript Module import and export statements. |  * A RenderingFormatter that works with ECMAScript Module import and export statements. | ||||||
| @ -226,7 +228,8 @@ export class EsmRenderingFormatter implements RenderingFormatter { | |||||||
|             info.declaration.getEnd(); |             info.declaration.getEnd(); | ||||||
|         outputText.appendLeft( |         outputText.appendLeft( | ||||||
|             insertPoint, |             insertPoint, | ||||||
|             `: ${generateImportString(importManager, '@angular/core', 'ModuleWithProviders')}<${ngModule}>`); |             `: ${generateImportString(importManager, '@angular/core', 'ModuleWithProviders')}<${ | ||||||
|  |                 ngModule}>`);
 | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| @ -296,7 +299,7 @@ function findStatement(node: ts.Node): ts.Statement|undefined { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function generateImportString( | function generateImportString( | ||||||
|     importManager: ImportManager, importPath: string | null, importName: string) { |     importManager: ImportManager, importPath: string|null, importName: string) { | ||||||
|   const importAs = importPath ? importManager.generateNamedImport(importPath, importName) : null; |   const importAs = importPath ? importManager.generateNamedImport(importPath, importName) : null; | ||||||
|   return importAs ? `${importAs.moduleImport}.${importAs.symbol}` : `${importName}`; |   return importAs ? `${importAs.moduleImport}.${importAs.symbol}` : `${importName}`; | ||||||
| } | } | ||||||
|  | |||||||
| @ -8,16 +8,18 @@ | |||||||
| import {ConstantPool, Expression, Statement, WrappedNodeExpr, WritePropExpr} from '@angular/compiler'; | import {ConstantPool, Expression, Statement, WrappedNodeExpr, WritePropExpr} from '@angular/compiler'; | ||||||
| import MagicString from 'magic-string'; | import MagicString from 'magic-string'; | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
|  | 
 | ||||||
|  | import {FileSystem} from '../../../src/ngtsc/file_system'; | ||||||
| import {ImportManager} from '../../../src/ngtsc/translator'; | import {ImportManager} from '../../../src/ngtsc/translator'; | ||||||
| import {CompiledClass, CompiledFile, DecorationAnalyses} from '../analysis/types'; |  | ||||||
| import {PrivateDeclarationsAnalyses} from '../analysis/private_declarations_analyzer'; | import {PrivateDeclarationsAnalyses} from '../analysis/private_declarations_analyzer'; | ||||||
| import {SwitchMarkerAnalyses, SwitchMarkerAnalysis} from '../analysis/switch_marker_analyzer'; | import {SwitchMarkerAnalyses, SwitchMarkerAnalysis} from '../analysis/switch_marker_analyzer'; | ||||||
|  | import {CompiledClass, CompiledFile, DecorationAnalyses} from '../analysis/types'; | ||||||
| import {IMPORT_PREFIX} from '../constants'; | import {IMPORT_PREFIX} from '../constants'; | ||||||
| import {FileSystem} from '../../../src/ngtsc/file_system'; |  | ||||||
| import {NgccReflectionHost} from '../host/ngcc_host'; | import {NgccReflectionHost} from '../host/ngcc_host'; | ||||||
| import {Logger} from '../logging/logger'; | import {Logger} from '../logging/logger'; | ||||||
| import {EntryPointBundle} from '../packages/entry_point_bundle'; | import {EntryPointBundle} from '../packages/entry_point_bundle'; | ||||||
| import {RenderingFormatter, RedundantDecoratorMap} from './rendering_formatter'; | 
 | ||||||
|  | import {RedundantDecoratorMap, RenderingFormatter} from './rendering_formatter'; | ||||||
| import {renderSourceAndMap} from './source_maps'; | import {renderSourceAndMap} from './source_maps'; | ||||||
| import {FileToWrite, getImportRewriter, stripExtension} from './utils'; | import {FileToWrite, getImportRewriter, stripExtension} from './utils'; | ||||||
| 
 | 
 | ||||||
| @ -138,11 +140,11 @@ export class Renderer { | |||||||
|         if (dec.node === null) { |         if (dec.node === null) { | ||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
|         const decoratorArray = dec.node.parent !; |         const decoratorArray = dec.node.parent!; | ||||||
|         if (!decoratorsToRemove.has(decoratorArray)) { |         if (!decoratorsToRemove.has(decoratorArray)) { | ||||||
|           decoratorsToRemove.set(decoratorArray, [dec.node]); |           decoratorsToRemove.set(decoratorArray, [dec.node]); | ||||||
|         } else { |         } else { | ||||||
|           decoratorsToRemove.get(decoratorArray) !.push(dec.node); |           decoratorsToRemove.get(decoratorArray)!.push(dec.node); | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
| @ -160,8 +162,9 @@ export class Renderer { | |||||||
|   private renderDefinitions( |   private renderDefinitions( | ||||||
|       sourceFile: ts.SourceFile, compiledClass: CompiledClass, imports: ImportManager): string { |       sourceFile: ts.SourceFile, compiledClass: CompiledClass, imports: ImportManager): string { | ||||||
|     const name = this.host.getInternalNameOfClass(compiledClass.declaration); |     const name = this.host.getInternalNameOfClass(compiledClass.declaration); | ||||||
|     const statements: Statement[] = compiledClass.compilation.map( |     const statements: Statement[] = compiledClass.compilation.map(c => { | ||||||
|         c => { return createAssignmentStatement(name, c.name, c.initializer); }); |       return createAssignmentStatement(name, c.name, c.initializer); | ||||||
|  |     }); | ||||||
|     return this.renderStatements(sourceFile, statements, imports); |     return this.renderStatements(sourceFile, statements, imports); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -8,12 +8,13 @@ | |||||||
| import {Statement} from '@angular/compiler'; | import {Statement} from '@angular/compiler'; | ||||||
| import MagicString from 'magic-string'; | import MagicString from 'magic-string'; | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
|  | 
 | ||||||
| import {Reexport} from '../../../src/ngtsc/imports'; | import {Reexport} from '../../../src/ngtsc/imports'; | ||||||
| import {Import, ImportManager} from '../../../src/ngtsc/translator'; | import {Import, ImportManager} from '../../../src/ngtsc/translator'; | ||||||
|  | import {ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer'; | ||||||
| import {ExportInfo} from '../analysis/private_declarations_analyzer'; | import {ExportInfo} from '../analysis/private_declarations_analyzer'; | ||||||
| import {CompiledClass} from '../analysis/types'; | import {CompiledClass} from '../analysis/types'; | ||||||
| import {SwitchableVariableDeclaration} from '../host/ngcc_host'; | import {SwitchableVariableDeclaration} from '../host/ngcc_host'; | ||||||
| import {ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer'; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * The collected decorators that have become redundant after the compilation |  * The collected decorators that have become redundant after the compilation | ||||||
|  | |||||||
| @ -5,14 +5,16 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {SourceMapConverter, fromObject, generateMapFileComment} from 'convert-source-map'; | import {fromObject, generateMapFileComment, SourceMapConverter} from 'convert-source-map'; | ||||||
| import MagicString from 'magic-string'; | import MagicString from 'magic-string'; | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| import {FileSystem, absoluteFromSourceFile, basename, absoluteFrom} from '../../../src/ngtsc/file_system'; | 
 | ||||||
| import {FileToWrite} from './utils'; | import {absoluteFrom, absoluteFromSourceFile, basename, FileSystem} from '../../../src/ngtsc/file_system'; | ||||||
| import {SourceFileLoader} from '../sourcemaps/source_file_loader'; |  | ||||||
| import {RawSourceMap} from '../sourcemaps/raw_source_map'; |  | ||||||
| import {Logger} from '../logging/logger'; | import {Logger} from '../logging/logger'; | ||||||
|  | import {RawSourceMap} from '../sourcemaps/raw_source_map'; | ||||||
|  | import {SourceFileLoader} from '../sourcemaps/source_file_loader'; | ||||||
|  | 
 | ||||||
|  | import {FileToWrite} from './utils'; | ||||||
| 
 | 
 | ||||||
| export interface SourceMapInfo { | export interface SourceMapInfo { | ||||||
|   source: string; |   source: string; | ||||||
| @ -53,8 +55,8 @@ export function renderSourceAndMap( | |||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|   } catch (e) { |   } catch (e) { | ||||||
|     logger.error( |     logger.error(`Error when flattening the source-map "${generatedMapPath}" for "${ | ||||||
|         `Error when flattening the source-map "${generatedMapPath}" for "${generatedPath}": ${e.toString()}`); |         generatedPath}": ${e.toString()}`);
 | ||||||
|     return [ |     return [ | ||||||
|       {path: generatedPath, contents: generatedContent}, |       {path: generatedPath, contents: generatedContent}, | ||||||
|       {path: generatedMapPath, contents: fromObject(generatedMap).toJSON()}, |       {path: generatedMapPath, contents: fromObject(generatedMap).toJSON()}, | ||||||
|  | |||||||
| @ -6,17 +6,19 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {dirname, relative} from 'canonical-path'; | import {dirname, relative} from 'canonical-path'; | ||||||
| import * as ts from 'typescript'; |  | ||||||
| import MagicString from 'magic-string'; | import MagicString from 'magic-string'; | ||||||
|  | import * as ts from 'typescript'; | ||||||
|  | 
 | ||||||
|  | import {Reexport} from '../../../src/ngtsc/imports'; | ||||||
| import {Import, ImportManager} from '../../../src/ngtsc/translator'; | import {Import, ImportManager} from '../../../src/ngtsc/translator'; | ||||||
| import {ExportInfo} from '../analysis/private_declarations_analyzer'; | import {ExportInfo} from '../analysis/private_declarations_analyzer'; | ||||||
| import {UmdReflectionHost} from '../host/umd_host'; | import {UmdReflectionHost} from '../host/umd_host'; | ||||||
|  | 
 | ||||||
| import {Esm5RenderingFormatter} from './esm5_rendering_formatter'; | import {Esm5RenderingFormatter} from './esm5_rendering_formatter'; | ||||||
| import {stripExtension} from './utils'; | import {stripExtension} from './utils'; | ||||||
| import {Reexport} from '../../../src/ngtsc/imports'; |  | ||||||
| 
 | 
 | ||||||
| type CommonJsConditional = ts.ConditionalExpression & {whenTrue: ts.CallExpression}; | type CommonJsConditional = ts.ConditionalExpression&{whenTrue: ts.CallExpression}; | ||||||
| type AmdConditional = ts.ConditionalExpression & {whenTrue: ts.CallExpression}; | type AmdConditional = ts.ConditionalExpression&{whenTrue: ts.CallExpression}; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * A RenderingFormatter that works with UMD files, instead of `import` and `export` statements |  * A RenderingFormatter that works with UMD files, instead of `import` and `export` statements | ||||||
| @ -24,7 +26,9 @@ type AmdConditional = ts.ConditionalExpression & {whenTrue: ts.CallExpression}; | |||||||
|  * wrapper function for AMD, CommonJS and global module formats. |  * wrapper function for AMD, CommonJS and global module formats. | ||||||
|  */ |  */ | ||||||
| export class UmdRenderingFormatter extends Esm5RenderingFormatter { | export class UmdRenderingFormatter extends Esm5RenderingFormatter { | ||||||
|   constructor(protected umdHost: UmdReflectionHost, isCore: boolean) { super(umdHost, isCore); } |   constructor(protected umdHost: UmdReflectionHost, isCore: boolean) { | ||||||
|  |     super(umdHost, isCore); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * Add the imports to the UMD module IIFE. |    * Add the imports to the UMD module IIFE. | ||||||
|  | |||||||
| @ -24,11 +24,11 @@ export interface FileToWrite { | |||||||
|  * Create an appropriate ImportRewriter given the parameters. |  * Create an appropriate ImportRewriter given the parameters. | ||||||
|  */ |  */ | ||||||
| export function getImportRewriter( | export function getImportRewriter( | ||||||
|     r3SymbolsFile: ts.SourceFile | null, isCore: boolean, isFlat: boolean): ImportRewriter { |     r3SymbolsFile: ts.SourceFile|null, isCore: boolean, isFlat: boolean): ImportRewriter { | ||||||
|   if (isCore && isFlat) { |   if (isCore && isFlat) { | ||||||
|     return new NgccFlatImportRewriter(); |     return new NgccFlatImportRewriter(); | ||||||
|   } else if (isCore) { |   } else if (isCore) { | ||||||
|     return new R3SymbolsImportRewriter(r3SymbolsFile !.fileName); |     return new R3SymbolsImportRewriter(r3SymbolsFile!.fileName); | ||||||
|   } else { |   } else { | ||||||
|     return new NoopImportRewriter(); |     return new NoopImportRewriter(); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -8,11 +8,11 @@ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| * A marker that indicates the start of a segment in a mapping. |  * A marker that indicates the start of a segment in a mapping. | ||||||
| * |  * | ||||||
| * The end of a segment is indicated by the the first segment-marker of another mapping whose start |  * The end of a segment is indicated by the the first segment-marker of another mapping whose start | ||||||
| * is greater or equal to this one. |  * is greater or equal to this one. | ||||||
| */ |  */ | ||||||
| export interface SegmentMarker { | export interface SegmentMarker { | ||||||
|   readonly line: number; |   readonly line: number; | ||||||
|   readonly column: number; |   readonly column: number; | ||||||
|  | |||||||
| @ -6,10 +6,12 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {removeComments, removeMapFileComments} from 'convert-source-map'; | import {removeComments, removeMapFileComments} from 'convert-source-map'; | ||||||
| import {SourceMapMappings, SourceMapSegment, decode, encode} from 'sourcemap-codec'; | import {decode, encode, SourceMapMappings, SourceMapSegment} from 'sourcemap-codec'; | ||||||
|  | 
 | ||||||
| import {AbsoluteFsPath, dirname, relative} from '../../../src/ngtsc/file_system'; | import {AbsoluteFsPath, dirname, relative} from '../../../src/ngtsc/file_system'; | ||||||
|  | 
 | ||||||
| import {RawSourceMap} from './raw_source_map'; | import {RawSourceMap} from './raw_source_map'; | ||||||
| import {SegmentMarker, compareSegments, offsetSegment} from './segment_marker'; | import {compareSegments, offsetSegment, SegmentMarker} from './segment_marker'; | ||||||
| 
 | 
 | ||||||
| export function removeSourceMapComments(contents: string): string { | export function removeSourceMapComments(contents: string): string { | ||||||
|   return removeMapFileComments(removeComments(contents)).replace(/\n\n$/, '\n'); |   return removeMapFileComments(removeComments(contents)).replace(/\n\n$/, '\n'); | ||||||
| @ -77,7 +79,8 @@ export class SourceFile { | |||||||
|     const sourceMap: RawSourceMap = { |     const sourceMap: RawSourceMap = { | ||||||
|       version: 3, |       version: 3, | ||||||
|       file: relative(sourcePathDir, this.sourcePath), |       file: relative(sourcePathDir, this.sourcePath), | ||||||
|       sources: sources.map(sf => relative(sourcePathDir, sf.sourcePath)), names, |       sources: sources.map(sf => relative(sourcePathDir, sf.sourcePath)), | ||||||
|  |       names, | ||||||
|       mappings: encode(mappings), |       mappings: encode(mappings), | ||||||
|       sourcesContent: sources.map(sf => sf.contents), |       sourcesContent: sources.map(sf => sf.contents), | ||||||
|     }; |     }; | ||||||
| @ -302,7 +305,7 @@ export function mergeMappings(generatedSource: SourceFile, ab: Mapping, bc: Mapp | |||||||
|  * in the `sources` parameter. |  * in the `sources` parameter. | ||||||
|  */ |  */ | ||||||
| export function parseMappings( | export function parseMappings( | ||||||
|     rawMap: RawSourceMap | null, sources: (SourceFile | null)[], |     rawMap: RawSourceMap|null, sources: (SourceFile|null)[], | ||||||
|     generatedSourceStartOfLinePositions: number[]): Mapping[] { |     generatedSourceStartOfLinePositions: number[]): Mapping[] { | ||||||
|   if (rawMap === null) { |   if (rawMap === null) { | ||||||
|     return []; |     return []; | ||||||
| @ -318,15 +321,15 @@ export function parseMappings( | |||||||
|     const generatedLineMappings = rawMappings[generatedLine]; |     const generatedLineMappings = rawMappings[generatedLine]; | ||||||
|     for (const rawMapping of generatedLineMappings) { |     for (const rawMapping of generatedLineMappings) { | ||||||
|       if (rawMapping.length >= 4) { |       if (rawMapping.length >= 4) { | ||||||
|         const originalSource = sources[rawMapping[1] !]; |         const originalSource = sources[rawMapping[1]!]; | ||||||
|         if (originalSource === null || originalSource === undefined) { |         if (originalSource === null || originalSource === undefined) { | ||||||
|           // the original source is missing so ignore this mapping
 |           // the original source is missing so ignore this mapping
 | ||||||
|           continue; |           continue; | ||||||
|         } |         } | ||||||
|         const generatedColumn = rawMapping[0]; |         const generatedColumn = rawMapping[0]; | ||||||
|         const name = rawMapping.length === 5 ? rawMap.names[rawMapping[4]] : undefined; |         const name = rawMapping.length === 5 ? rawMap.names[rawMapping[4]] : undefined; | ||||||
|         const line = rawMapping[2] !; |         const line = rawMapping[2]!; | ||||||
|         const column = rawMapping[3] !; |         const column = rawMapping[3]!; | ||||||
|         const generatedSegment: SegmentMarker = { |         const generatedSegment: SegmentMarker = { | ||||||
|           line: generatedLine, |           line: generatedLine, | ||||||
|           column: generatedColumn, |           column: generatedColumn, | ||||||
| @ -361,7 +364,7 @@ export function extractOriginalSegments(mappings: Mapping[]): Map<SourceFile, Se | |||||||
|     if (!originalSegments.has(originalSource)) { |     if (!originalSegments.has(originalSource)) { | ||||||
|       originalSegments.set(originalSource, []); |       originalSegments.set(originalSource, []); | ||||||
|     } |     } | ||||||
|     const segments = originalSegments.get(originalSource) !; |     const segments = originalSegments.get(originalSource)!; | ||||||
|     segments.push(mapping.originalSegment); |     segments.push(mapping.originalSegment); | ||||||
|   } |   } | ||||||
|   originalSegments.forEach(segmentMarkers => segmentMarkers.sort(compareSegments)); |   originalSegments.forEach(segmentMarkers => segmentMarkers.sort(compareSegments)); | ||||||
|  | |||||||
| @ -6,7 +6,9 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {commentRegex, fromComment, mapFileCommentRegex} from 'convert-source-map'; | import {commentRegex, fromComment, mapFileCommentRegex} from 'convert-source-map'; | ||||||
| import {AbsoluteFsPath, FileSystem, absoluteFrom} from '../../../src/ngtsc/file_system'; | 
 | ||||||
|  | import {absoluteFrom, AbsoluteFsPath, FileSystem} from '../../../src/ngtsc/file_system'; | ||||||
|  | 
 | ||||||
| import {RawSourceMap} from './raw_source_map'; | import {RawSourceMap} from './raw_source_map'; | ||||||
| import {SourceFile} from './source_file'; | import {SourceFile} from './source_file'; | ||||||
| 
 | 
 | ||||||
| @ -51,8 +53,8 @@ export class SourceFileLoader { | |||||||
|       // Track source file paths if we have loaded them from disk so that we don't get into an
 |       // Track source file paths if we have loaded them from disk so that we don't get into an
 | ||||||
|       // infinite recursion
 |       // infinite recursion
 | ||||||
|       if (previousPaths.includes(sourcePath)) { |       if (previousPaths.includes(sourcePath)) { | ||||||
|         throw new Error( |         throw new Error(`Circular source file mapping dependency: ${ | ||||||
|             `Circular source file mapping dependency: ${previousPaths.join(' -> ')} -> ${sourcePath}`); |             previousPaths.join(' -> ')} -> ${sourcePath}`);
 | ||||||
|       } |       } | ||||||
|       previousPaths = previousPaths.concat([sourcePath]); |       previousPaths = previousPaths.concat([sourcePath]); | ||||||
| 
 | 
 | ||||||
| @ -66,7 +68,7 @@ export class SourceFileLoader { | |||||||
| 
 | 
 | ||||||
|     let map: RawSourceMap|null = null; |     let map: RawSourceMap|null = null; | ||||||
|     let inline = true; |     let inline = true; | ||||||
|     let sources: (SourceFile | null)[] = []; |     let sources: (SourceFile|null)[] = []; | ||||||
|     if (mapAndPath !== null) { |     if (mapAndPath !== null) { | ||||||
|       const basePath = mapAndPath.mapPath || sourcePath; |       const basePath = mapAndPath.mapPath || sourcePath; | ||||||
|       sources = this.processSources(basePath, mapAndPath.map, previousPaths); |       sources = this.processSources(basePath, mapAndPath.map, previousPaths); | ||||||
| @ -87,7 +89,7 @@ export class SourceFileLoader { | |||||||
|   private loadSourceMap(sourcePath: AbsoluteFsPath, contents: string): MapAndPath|null { |   private loadSourceMap(sourcePath: AbsoluteFsPath, contents: string): MapAndPath|null { | ||||||
|     const inline = commentRegex.exec(contents); |     const inline = commentRegex.exec(contents); | ||||||
|     if (inline !== null) { |     if (inline !== null) { | ||||||
|       return {map: fromComment(inline.pop() !).sourcemap, mapPath: null}; |       return {map: fromComment(inline.pop()!).sourcemap, mapPath: null}; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const external = mapFileCommentRegex.exec(contents); |     const external = mapFileCommentRegex.exec(contents); | ||||||
|  | |||||||
| @ -6,7 +6,8 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| import {AbsoluteFsPath, FileSystem, absoluteFrom} from '../../src/ngtsc/file_system'; | 
 | ||||||
|  | import {absoluteFrom, AbsoluteFsPath, FileSystem} from '../../src/ngtsc/file_system'; | ||||||
| import {KnownDeclaration} from '../../src/ngtsc/reflection'; | import {KnownDeclaration} from '../../src/ngtsc/reflection'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -37,11 +38,11 @@ export function getOriginalSymbol(checker: ts.TypeChecker): (symbol: ts.Symbol) | |||||||
|   }; |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function isDefined<T>(value: T | undefined | null): value is T { | export function isDefined<T>(value: T|undefined|null): value is T { | ||||||
|   return (value !== undefined) && (value !== null); |   return (value !== undefined) && (value !== null); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function getNameText(name: ts.PropertyName | ts.BindingName): string { | export function getNameText(name: ts.PropertyName|ts.BindingName): string { | ||||||
|   return ts.isIdentifier(name) || ts.isLiteralExpression(name) ? name.text : name.getText(); |   return ts.isIdentifier(name) || ts.isLiteralExpression(name) ? name.text : name.getText(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -111,10 +112,12 @@ export class FactoryMap<K, V> { | |||||||
|       this.internalMap.set(key, this.factory(key)); |       this.internalMap.set(key, this.factory(key)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return this.internalMap.get(key) !; |     return this.internalMap.get(key)!; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   set(key: K, value: V): void { this.internalMap.set(key, value); } |   set(key: K, value: V): void { | ||||||
|  |     this.internalMap.set(key, value); | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -5,15 +5,16 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {AbsoluteFsPath, FileSystem, PathSegment, absoluteFrom} from '../../../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath, FileSystem, PathSegment} from '../../../../src/ngtsc/file_system'; | ||||||
| import {cleanPackageJson} from '../../packages/build_marker'; | import {cleanPackageJson} from '../../packages/build_marker'; | ||||||
| import {NGCC_BACKUP_EXTENSION} from '../in_place_file_writer'; | import {NGCC_BACKUP_EXTENSION} from '../in_place_file_writer'; | ||||||
| import {NGCC_DIRECTORY} from '../new_entry_point_file_writer'; | import {NGCC_DIRECTORY} from '../new_entry_point_file_writer'; | ||||||
|  | 
 | ||||||
| import {isLocalDirectory} from './utils'; | import {isLocalDirectory} from './utils'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| * Implement this interface to extend the cleaning strategies of the `PackageCleaner`. |  * Implement this interface to extend the cleaning strategies of the `PackageCleaner`. | ||||||
| */ |  */ | ||||||
| export interface CleaningStrategy { | export interface CleaningStrategy { | ||||||
|   canClean(path: AbsoluteFsPath, basename: PathSegment): boolean; |   canClean(path: AbsoluteFsPath, basename: PathSegment): boolean; | ||||||
|   clean(path: AbsoluteFsPath, basename: PathSegment): void; |   clean(path: AbsoluteFsPath, basename: PathSegment): void; | ||||||
| @ -44,7 +45,9 @@ export class NgccDirectoryCleaner implements CleaningStrategy { | |||||||
|   canClean(path: AbsoluteFsPath, basename: PathSegment): boolean { |   canClean(path: AbsoluteFsPath, basename: PathSegment): boolean { | ||||||
|     return basename === NGCC_DIRECTORY && isLocalDirectory(this.fs, path); |     return basename === NGCC_DIRECTORY && isLocalDirectory(this.fs, path); | ||||||
|   } |   } | ||||||
|   clean(path: AbsoluteFsPath, _basename: PathSegment): void { this.fs.removeDeep(path); } |   clean(path: AbsoluteFsPath, _basename: PathSegment): void { | ||||||
|  |     this.fs.removeDeep(path); | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -5,11 +5,12 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {FileSystem, absoluteFrom, dirname} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, dirname, FileSystem} from '../../../src/ngtsc/file_system'; | ||||||
| import {Logger} from '../logging/logger'; | import {Logger} from '../logging/logger'; | ||||||
| import {EntryPointJsonProperty} from '../packages/entry_point'; | import {EntryPointJsonProperty} from '../packages/entry_point'; | ||||||
| import {EntryPointBundle} from '../packages/entry_point_bundle'; | import {EntryPointBundle} from '../packages/entry_point_bundle'; | ||||||
| import {FileToWrite} from '../rendering/utils'; | import {FileToWrite} from '../rendering/utils'; | ||||||
|  | 
 | ||||||
| import {FileWriter} from './file_writer'; | import {FileWriter} from './file_writer'; | ||||||
| 
 | 
 | ||||||
| export const NGCC_BACKUP_EXTENSION = '.__ivy_ngcc_bak'; | export const NGCC_BACKUP_EXTENSION = '.__ivy_ngcc_bak'; | ||||||
| @ -37,7 +38,9 @@ export class InPlaceFileWriter implements FileWriter { | |||||||
|             `Tried to overwrite ${backPath} with an ngcc back up file, which is disallowed.`); |             `Tried to overwrite ${backPath} with an ngcc back up file, which is disallowed.`); | ||||||
|       } else { |       } else { | ||||||
|         this.logger.error( |         this.logger.error( | ||||||
|             `Tried to write ${backPath} with an ngcc back up file but it already exists so not writing, nor backing up, ${file.path}.\n` + |             `Tried to write ${ | ||||||
|  |                 backPath} with an ngcc back up file but it already exists so not writing, nor backing up, ${ | ||||||
|  |                 file.path}.\n` +
 | ||||||
|             `This error may be because two or more entry-points overlap and ngcc has been asked to process some files more than once.\n` + |             `This error may be because two or more entry-points overlap and ngcc has been asked to process some files more than once.\n` + | ||||||
|             `You should check other entry-points in this package and set up a config to ignore any that you are not using.`); |             `You should check other entry-points in this package and set up a config to ignore any that you are not using.`); | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {AbsoluteFsPath, FileSystem, absoluteFromSourceFile, dirname, join, relative} from '../../../src/ngtsc/file_system'; | import {absoluteFromSourceFile, AbsoluteFsPath, dirname, FileSystem, join, relative} from '../../../src/ngtsc/file_system'; | ||||||
| import {isDtsPath} from '../../../src/ngtsc/util/src/typescript'; | import {isDtsPath} from '../../../src/ngtsc/util/src/typescript'; | ||||||
| import {Logger} from '../logging/logger'; | import {Logger} from '../logging/logger'; | ||||||
| import {EntryPoint, EntryPointJsonProperty} from '../packages/entry_point'; | import {EntryPoint, EntryPointJsonProperty} from '../packages/entry_point'; | ||||||
| @ -83,8 +83,8 @@ export class NewEntryPointFileWriter extends InPlaceFileWriter { | |||||||
|     const packageJsonPath = join(entryPoint.path, 'package.json'); |     const packageJsonPath = join(entryPoint.path, 'package.json'); | ||||||
| 
 | 
 | ||||||
|     // All format properties point to the same format-path.
 |     // All format properties point to the same format-path.
 | ||||||
|     const oldFormatProp = formatProperties[0] !; |     const oldFormatProp = formatProperties[0]!; | ||||||
|     const oldFormatPath = packageJson[oldFormatProp] !; |     const oldFormatPath = packageJson[oldFormatProp]!; | ||||||
|     const oldAbsFormatPath = join(entryPoint.path, oldFormatPath); |     const oldAbsFormatPath = join(entryPoint.path, oldFormatPath); | ||||||
|     const newAbsFormatPath = join(ngccFolder, relative(entryPoint.package, oldAbsFormatPath)); |     const newAbsFormatPath = join(ngccFolder, relative(entryPoint.package, oldAbsFormatPath)); | ||||||
|     const newFormatPath = relative(entryPoint.path, newAbsFormatPath); |     const newFormatPath = relative(entryPoint.path, newAbsFormatPath); | ||||||
|  | |||||||
| @ -6,12 +6,12 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| import {AbsoluteFsPath, FileSystem, dirname} from '../../../src/ngtsc/file_system'; | import {AbsoluteFsPath, dirname, FileSystem} from '../../../src/ngtsc/file_system'; | ||||||
| import {JsonObject, JsonValue} from '../packages/entry_point'; | import {JsonObject, JsonValue} from '../packages/entry_point'; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| export type PackageJsonChange = [string[], JsonValue, PackageJsonPropertyPositioning]; | export type PackageJsonChange = [string[], JsonValue, PackageJsonPropertyPositioning]; | ||||||
| export type PackageJsonPropertyPositioning = 'unimportant' | 'alphabetic' | {before: string}; | export type PackageJsonPropertyPositioning = 'unimportant'|'alphabetic'|{before: string}; | ||||||
| export type WritePackageJsonChangesFn = | export type WritePackageJsonChangesFn = | ||||||
|     (changes: PackageJsonChange[], packageJsonPath: AbsoluteFsPath, parsedJson?: JsonObject) => |     (changes: PackageJsonChange[], packageJsonPath: AbsoluteFsPath, parsedJson?: JsonObject) => | ||||||
|         void; |         void; | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ import * as ts from 'typescript'; | |||||||
| 
 | 
 | ||||||
| import {FatalDiagnosticError, makeDiagnostic} from '../../../src/ngtsc/diagnostics'; | import {FatalDiagnosticError, makeDiagnostic} from '../../../src/ngtsc/diagnostics'; | ||||||
| import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {ClassDeclaration, Decorator} from '../../../src/ngtsc/reflection'; | import {ClassDeclaration, Decorator} from '../../../src/ngtsc/reflection'; | ||||||
| import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../../src/ngtsc/transform'; | import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../../src/ngtsc/transform'; | ||||||
| import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; | import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; | ||||||
| @ -21,7 +21,7 @@ import {Migration, MigrationHost} from '../../src/migrations/migration'; | |||||||
| import {MockLogger} from '../helpers/mock_logger'; | import {MockLogger} from '../helpers/mock_logger'; | ||||||
| import {getRootFiles, makeTestEntryPointBundle} from '../helpers/utils'; | import {getRootFiles, makeTestEntryPointBundle} from '../helpers/utils'; | ||||||
| 
 | 
 | ||||||
| type DecoratorHandlerWithResolve = DecoratorHandler<unknown, unknown, unknown>& { | type DecoratorHandlerWithResolve = DecoratorHandler<unknown, unknown, unknown>&{ | ||||||
|   resolve: NonNullable<DecoratorHandler<unknown, unknown, unknown>['resolve']>; |   resolve: NonNullable<DecoratorHandler<unknown, unknown, unknown>['resolve']>; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -29,7 +29,9 @@ runInEachFileSystem(() => { | |||||||
|   describe('DecorationAnalyzer', () => { |   describe('DecorationAnalyzer', () => { | ||||||
|     let _: typeof absoluteFrom; |     let _: typeof absoluteFrom; | ||||||
| 
 | 
 | ||||||
|     beforeEach(() => { _ = absoluteFrom; }); |     beforeEach(() => { | ||||||
|  |       _ = absoluteFrom; | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     describe('analyzeProgram()', () => { |     describe('analyzeProgram()', () => { | ||||||
|       let logs: string[]; |       let logs: string[]; | ||||||
| @ -50,7 +52,7 @@ runInEachFileSystem(() => { | |||||||
|         ]); |         ]); | ||||||
|         // Only detect the Component and Directive decorators
 |         // Only detect the Component and Directive decorators
 | ||||||
|         handler.detect.and.callFake( |         handler.detect.and.callFake( | ||||||
|             (node: ts.Declaration, decorators: Decorator[] | null): DetectResult<unknown>| |             (node: ts.Declaration, decorators: Decorator[]|null): DetectResult<unknown>| | ||||||
|             undefined => { |             undefined => { | ||||||
|               const className = (node as any).name.text; |               const className = (node as any).name.text; | ||||||
|               if (decorators === null) { |               if (decorators === null) { | ||||||
| @ -94,17 +96,17 @@ runInEachFileSystem(() => { | |||||||
|         // The "test" compilation result is just the name of the decorator being compiled
 |         // The "test" compilation result is just the name of the decorator being compiled
 | ||||||
|         // (suffixed with `(compiled)`)
 |         // (suffixed with `(compiled)`)
 | ||||||
|         handler.compile.and.callFake((decl: ts.Declaration, analysis: any) => { |         handler.compile.and.callFake((decl: ts.Declaration, analysis: any) => { | ||||||
|           logs.push( |           logs.push(`compile: ${(decl as any).name.text}@${analysis.decoratorName} (resolved: ${ | ||||||
|               `compile: ${(decl as any).name.text}@${analysis.decoratorName} (resolved: ${analysis.resolved})`); |               analysis.resolved})`);
 | ||||||
|           return `@${analysis.decoratorName} (compiled)`; |           return `@${analysis.decoratorName} (compiled)`; | ||||||
|         }); |         }); | ||||||
|         return handler; |         return handler; | ||||||
|       }; |       }; | ||||||
| 
 | 
 | ||||||
|       function setUpAnalyzer( |       function setUpAnalyzer(testFiles: TestFile[], options: { | ||||||
|           testFiles: TestFile[], |         analyzeError: boolean, | ||||||
|           options: {analyzeError: boolean, |         resolveError: boolean | ||||||
|                     resolveError: boolean} = {analyzeError: false, resolveError: false}) { |       } = {analyzeError: false, resolveError: false}) { | ||||||
|         logs = []; |         logs = []; | ||||||
|         loadTestFiles(testFiles); |         loadTestFiles(testFiles); | ||||||
|         loadFakeCore(getFileSystem()); |         loadFakeCore(getFileSystem()); | ||||||
| @ -173,9 +175,9 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|         it('should return an object containing a reference to the original source file', () => { |         it('should return an object containing a reference to the original source file', () => { | ||||||
|           const testFile = getSourceFileOrError(program, _('/node_modules/test-package/test.js')); |           const testFile = getSourceFileOrError(program, _('/node_modules/test-package/test.js')); | ||||||
|           expect(result.get(testFile) !.sourceFile).toBe(testFile); |           expect(result.get(testFile)!.sourceFile).toBe(testFile); | ||||||
|           const otherFile = getSourceFileOrError(program, _('/node_modules/test-package/other.js')); |           const otherFile = getSourceFileOrError(program, _('/node_modules/test-package/other.js')); | ||||||
|           expect(result.get(otherFile) !.sourceFile).toBe(otherFile); |           expect(result.get(otherFile)!.sourceFile).toBe(otherFile); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         it('should call detect on the decorator handlers with each class from the parsed file', |         it('should call detect on the decorator handlers with each class from the parsed file', | ||||||
| @ -192,20 +194,23 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|         it('should return an object containing the classes that were analyzed', () => { |         it('should return an object containing the classes that were analyzed', () => { | ||||||
|           const file1 = getSourceFileOrError(program, _('/node_modules/test-package/test.js')); |           const file1 = getSourceFileOrError(program, _('/node_modules/test-package/test.js')); | ||||||
|           const compiledFile1 = result.get(file1) !; |           const compiledFile1 = result.get(file1)!; | ||||||
|           expect(compiledFile1.compiledClasses.length).toEqual(2); |           expect(compiledFile1.compiledClasses.length).toEqual(2); | ||||||
|           expect(compiledFile1.compiledClasses[0]).toEqual(jasmine.objectContaining({ |           expect(compiledFile1.compiledClasses[0]).toEqual(jasmine.objectContaining({ | ||||||
|             name: 'MyComponent', compilation: ['@Component (compiled)'], |             name: 'MyComponent', | ||||||
|  |             compilation: ['@Component (compiled)'], | ||||||
|           } as unknown as CompiledClass)); |           } as unknown as CompiledClass)); | ||||||
|           expect(compiledFile1.compiledClasses[1]).toEqual(jasmine.objectContaining({ |           expect(compiledFile1.compiledClasses[1]).toEqual(jasmine.objectContaining({ | ||||||
|             name: 'MyDirective', compilation: ['@Directive (compiled)'], |             name: 'MyDirective', | ||||||
|  |             compilation: ['@Directive (compiled)'], | ||||||
|           } as unknown as CompiledClass)); |           } as unknown as CompiledClass)); | ||||||
| 
 | 
 | ||||||
|           const file2 = getSourceFileOrError(program, _('/node_modules/test-package/other.js')); |           const file2 = getSourceFileOrError(program, _('/node_modules/test-package/other.js')); | ||||||
|           const compiledFile2 = result.get(file2) !; |           const compiledFile2 = result.get(file2)!; | ||||||
|           expect(compiledFile2.compiledClasses.length).toEqual(1); |           expect(compiledFile2.compiledClasses.length).toEqual(1); | ||||||
|           expect(compiledFile2.compiledClasses[0]).toEqual(jasmine.objectContaining({ |           expect(compiledFile2.compiledClasses[0]).toEqual(jasmine.objectContaining({ | ||||||
|             name: 'MyOtherComponent', compilation: ['@Component (compiled)'], |             name: 'MyOtherComponent', | ||||||
|  |             compilation: ['@Component (compiled)'], | ||||||
|           } as unknown as CompiledClass)); |           } as unknown as CompiledClass)); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -284,18 +289,18 @@ runInEachFileSystem(() => { | |||||||
|            () => { |            () => { | ||||||
|              const file = |              const file = | ||||||
|                  getSourceFileOrError(program, _('/node_modules/test-package/component.js')); |                  getSourceFileOrError(program, _('/node_modules/test-package/component.js')); | ||||||
|              const analysis = result.get(file) !; |              const analysis = result.get(file)!; | ||||||
|              expect(analysis).toBeDefined(); |              expect(analysis).toBeDefined(); | ||||||
|              const ImportedComponent = |              const ImportedComponent = | ||||||
|                  analysis.compiledClasses.find(f => f.name === 'ImportedComponent') !; |                  analysis.compiledClasses.find(f => f.name === 'ImportedComponent')!; | ||||||
|              expect(ImportedComponent).toBeDefined(); |              expect(ImportedComponent).toBeDefined(); | ||||||
|            }); |            }); | ||||||
| 
 | 
 | ||||||
|         it('should analyze an internally defined component, which is not exported at all', () => { |         it('should analyze an internally defined component, which is not exported at all', () => { | ||||||
|           const file = getSourceFileOrError(program, _('/node_modules/test-package/entrypoint.js')); |           const file = getSourceFileOrError(program, _('/node_modules/test-package/entrypoint.js')); | ||||||
|           const analysis = result.get(file) !; |           const analysis = result.get(file)!; | ||||||
|           expect(analysis).toBeDefined(); |           expect(analysis).toBeDefined(); | ||||||
|           const LocalComponent = analysis.compiledClasses.find(f => f.name === 'LocalComponent') !; |           const LocalComponent = analysis.compiledClasses.find(f => f.name === 'LocalComponent')!; | ||||||
|           expect(LocalComponent).toBeDefined(); |           expect(LocalComponent).toBeDefined(); | ||||||
|         }); |         }); | ||||||
|       }); |       }); | ||||||
| @ -341,7 +346,7 @@ runInEachFileSystem(() => { | |||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         it('should ignore classes from an externally imported file', () => { |         it('should ignore classes from an externally imported file', () => { | ||||||
|           const file = program.getSourceFile(_('/node_modules/other/component.js')) !; |           const file = program.getSourceFile(_('/node_modules/other/component.js'))!; | ||||||
|           expect(result.has(file)).toBe(false); |           expect(result.has(file)).toBe(false); | ||||||
|         }); |         }); | ||||||
|       }); |       }); | ||||||
| @ -427,11 +432,15 @@ runInEachFileSystem(() => { | |||||||
|             name = 'FakeDecoratorHandler'; |             name = 'FakeDecoratorHandler'; | ||||||
|             precedence = HandlerPrecedence.PRIMARY; |             precedence = HandlerPrecedence.PRIMARY; | ||||||
| 
 | 
 | ||||||
|             detect(): undefined { throw new Error('detect should not have been called'); } |             detect(): undefined { | ||||||
|  |               throw new Error('detect should not have been called'); | ||||||
|  |             } | ||||||
|             analyze(): AnalysisOutput<unknown> { |             analyze(): AnalysisOutput<unknown> { | ||||||
|               throw new Error('analyze should not have been called'); |               throw new Error('analyze should not have been called'); | ||||||
|             } |             } | ||||||
|             compile(): CompileResult { throw new Error('compile should not have been called'); } |             compile(): CompileResult { | ||||||
|  |               throw new Error('compile should not have been called'); | ||||||
|  |             } | ||||||
|           } |           } | ||||||
| 
 | 
 | ||||||
|           const analyzer = setUpAnalyzer([{ |           const analyzer = setUpAnalyzer([{ | ||||||
|  | |||||||
| @ -62,7 +62,7 @@ runInEachFileSystem(() => { | |||||||
|         const {host, compiler} = createMigrationHost({entryPoint, handlers: [handler]}); |         const {host, compiler} = createMigrationHost({entryPoint, handlers: [handler]}); | ||||||
|         host.injectSyntheticDecorator(mockClazz, injectedDecorator); |         host.injectSyntheticDecorator(mockClazz, injectedDecorator); | ||||||
| 
 | 
 | ||||||
|         const record = compiler.recordFor(mockClazz) !; |         const record = compiler.recordFor(mockClazz)!; | ||||||
|         expect(record).toBeDefined(); |         expect(record).toBeDefined(); | ||||||
|         expect(record.traits.length).toBe(1); |         expect(record.traits.length).toBe(1); | ||||||
|         expect(record.traits[0].detected.decorator).toBe(injectedDecorator); |         expect(record.traits[0].detected.decorator).toBe(injectedDecorator); | ||||||
| @ -77,7 +77,7 @@ runInEachFileSystem(() => { | |||||||
|         const decorator = createComponentDecorator(mockClazz, {selector: 'comp', exportAs: null}); |         const decorator = createComponentDecorator(mockClazz, {selector: 'comp', exportAs: null}); | ||||||
|         host.injectSyntheticDecorator(mockClazz, decorator); |         host.injectSyntheticDecorator(mockClazz, decorator); | ||||||
| 
 | 
 | ||||||
|         const record = compiler.recordFor(mockClazz) !; |         const record = compiler.recordFor(mockClazz)!; | ||||||
|         const migratedTrait = record.traits[0]; |         const migratedTrait = record.traits[0]; | ||||||
|         if (migratedTrait.state !== TraitState.ERRORED) { |         if (migratedTrait.state !== TraitState.ERRORED) { | ||||||
|           return fail('Expected migrated class trait to be in an error state'); |           return fail('Expected migrated class trait to be in an error state'); | ||||||
| @ -120,7 +120,7 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|         host.injectSyntheticDecorator(myClass, injectedDecorator); |         host.injectSyntheticDecorator(myClass, injectedDecorator); | ||||||
| 
 | 
 | ||||||
|         const decorators = host.getAllDecorators(myClass) !; |         const decorators = host.getAllDecorators(myClass)!; | ||||||
|         expect(decorators.length).toBe(2); |         expect(decorators.length).toBe(2); | ||||||
|         expect(decorators[0].name).toBe('Directive'); |         expect(decorators[0].name).toBe('Directive'); | ||||||
|         expect(decorators[1].name).toBe('InjectedDecorator'); |         expect(decorators[1].name).toBe('InjectedDecorator'); | ||||||
| @ -183,9 +183,13 @@ class DetectDecoratorHandler implements DecoratorHandler<unknown, unknown, unkno | |||||||
|     return {trigger: node, decorator, metadata: {}}; |     return {trigger: node, decorator, metadata: {}}; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   analyze(node: ClassDeclaration): AnalysisOutput<unknown> { return {}; } |   analyze(node: ClassDeclaration): AnalysisOutput<unknown> { | ||||||
|  |     return {}; | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   compile(node: ClassDeclaration): CompileResult|CompileResult[] { return []; } |   compile(node: ClassDeclaration): CompileResult|CompileResult[] { | ||||||
|  |     return []; | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| class DiagnosticProducingHandler implements DecoratorHandler<unknown, unknown, unknown> { | class DiagnosticProducingHandler implements DecoratorHandler<unknown, unknown, unknown> { | ||||||
| @ -201,5 +205,7 @@ class DiagnosticProducingHandler implements DecoratorHandler<unknown, unknown, u | |||||||
|     return {diagnostics: [makeDiagnostic(9999, node, 'test diagnostic')]}; |     return {diagnostics: [makeDiagnostic(9999, node, 'test diagnostic')]}; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   compile(node: ClassDeclaration): CompileResult|CompileResult[] { return []; } |   compile(node: ClassDeclaration): CompileResult|CompileResult[] { | ||||||
|  |     return []; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -7,8 +7,8 @@ | |||||||
|  */ |  */ | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| 
 | 
 | ||||||
| import {AbsoluteFsPath, absoluteFrom, getSourceFileOrError} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath, getSourceFileOrError} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {getDeclaration} from '../../../src/ngtsc/testing'; | import {getDeclaration} from '../../../src/ngtsc/testing'; | ||||||
| import {loadTestFiles} from '../../../test/helpers'; | import {loadTestFiles} from '../../../test/helpers'; | ||||||
| import {ModuleWithProvidersAnalyses, ModuleWithProvidersAnalyzer} from '../../src/analysis/module_with_providers_analyzer'; | import {ModuleWithProvidersAnalyses, ModuleWithProvidersAnalyzer} from '../../src/analysis/module_with_providers_analyzer'; | ||||||
| @ -333,7 +333,7 @@ runInEachFileSystem(() => { | |||||||
|             'test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM), |             'test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM), | ||||||
|             getRootFiles(TEST_DTS_PROGRAM)); |             getRootFiles(TEST_DTS_PROGRAM)); | ||||||
|         program = bundle.src.program; |         program = bundle.src.program; | ||||||
|         dtsProgram = bundle.dts !; |         dtsProgram = bundle.dts!; | ||||||
|         const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle.src, dtsProgram); |         const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle.src, dtsProgram); | ||||||
|         referencesRegistry = new NgccReferencesRegistry(host); |         referencesRegistry = new NgccReferencesRegistry(host); | ||||||
| 
 | 
 | ||||||
| @ -367,8 +367,8 @@ runInEachFileSystem(() => { | |||||||
|         const libraryModuleDeclaration = getDeclaration( |         const libraryModuleDeclaration = getDeclaration( | ||||||
|             program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule', |             program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule', | ||||||
|             ts.isClassDeclaration); |             ts.isClassDeclaration); | ||||||
|         expect(declarations.has(externalModuleDeclaration.name !)).toBe(true); |         expect(declarations.has(externalModuleDeclaration.name!)).toBe(true); | ||||||
|         expect(declarations.has(libraryModuleDeclaration.name !)).toBe(false); |         expect(declarations.has(libraryModuleDeclaration.name!)).toBe(false); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should find declarations that have implicit return types', () => { |       it('should find declarations that have implicit return types', () => { | ||||||
| @ -414,11 +414,10 @@ runInEachFileSystem(() => { | |||||||
|           analyses: ModuleWithProvidersAnalyses, fileName: AbsoluteFsPath) { |           analyses: ModuleWithProvidersAnalyses, fileName: AbsoluteFsPath) { | ||||||
|         const file = getSourceFileOrError(dtsProgram.program, fileName); |         const file = getSourceFileOrError(dtsProgram.program, fileName); | ||||||
|         const analysis = analyses.get(file); |         const analysis = analyses.get(file); | ||||||
|         return analysis ? |         return analysis ? analysis.map( | ||||||
|             analysis.map( |  | ||||||
|                               info => |                               info => | ||||||
|                     [info.declaration.name !.getText(), |                                   [info.declaration.name!.getText(), | ||||||
|                      (info.ngModule.node as ts.ClassDeclaration).name !.getText(), |                                    (info.ngModule.node as ts.ClassDeclaration).name!.getText(), | ||||||
|                                    info.ngModule.viaModule]) : |                                    info.ngModule.viaModule]) : | ||||||
|                           []; |                           []; | ||||||
|       } |       } | ||||||
| @ -536,7 +535,7 @@ runInEachFileSystem(() => { | |||||||
|           'test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM), |           'test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM), | ||||||
|           getRootFiles(TEST_DTS_PROGRAM)); |           getRootFiles(TEST_DTS_PROGRAM)); | ||||||
|       const program = bundle.src.program; |       const program = bundle.src.program; | ||||||
|       const dtsProgram = bundle.dts !; |       const dtsProgram = bundle.dts!; | ||||||
|       const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle.src, dtsProgram); |       const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle.src, dtsProgram); | ||||||
|       const referencesRegistry = new NgccReferencesRegistry(host); |       const referencesRegistry = new NgccReferencesRegistry(host); | ||||||
| 
 | 
 | ||||||
| @ -558,9 +557,9 @@ runInEachFileSystem(() => { | |||||||
|       const libraryModuleDeclaration = getDeclaration( |       const libraryModuleDeclaration = getDeclaration( | ||||||
|           program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule', |           program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule', | ||||||
|           ts.isClassDeclaration); |           ts.isClassDeclaration); | ||||||
|       expect(declarations.has(explicitInternalModuleDeclaration.name !)).toBe(true); |       expect(declarations.has(explicitInternalModuleDeclaration.name!)).toBe(true); | ||||||
|       expect(declarations.has(externalModuleDeclaration.name !)).toBe(true); |       expect(declarations.has(externalModuleDeclaration.name!)).toBe(true); | ||||||
|       expect(declarations.has(libraryModuleDeclaration.name !)).toBe(false); |       expect(declarations.has(libraryModuleDeclaration.name!)).toBe(false); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should track references even when typings have already been processed', () => { |     it('should track references even when typings have already been processed', () => { | ||||||
| @ -586,9 +585,9 @@ runInEachFileSystem(() => { | |||||||
|       const libraryModuleDeclaration = getDeclaration( |       const libraryModuleDeclaration = getDeclaration( | ||||||
|           program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule', |           program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule', | ||||||
|           ts.isClassDeclaration); |           ts.isClassDeclaration); | ||||||
|       expect(declarations.has(explicitInternalModuleDeclaration.name !)).toBe(true); |       expect(declarations.has(explicitInternalModuleDeclaration.name!)).toBe(true); | ||||||
|       expect(declarations.has(externalModuleDeclaration.name !)).toBe(true); |       expect(declarations.has(externalModuleDeclaration.name!)).toBe(true); | ||||||
|       expect(declarations.has(libraryModuleDeclaration.name !)).toBe(false); |       expect(declarations.has(libraryModuleDeclaration.name!)).toBe(false); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -91,7 +91,7 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|         const record = compiler.recordFor(mockClazz); |         const record = compiler.recordFor(mockClazz); | ||||||
|         expect(record).toBeDefined(); |         expect(record).toBeDefined(); | ||||||
|         expect(record !.traits.length).toBe(1); |         expect(record!.traits.length).toBe(1); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should add a new trait to an existing class record', () => { |       it('should add a new trait to an existing class record', () => { | ||||||
| @ -118,11 +118,11 @@ runInEachFileSystem(() => { | |||||||
|         compiler.analyzeFile(entryPoint.src.file); |         compiler.analyzeFile(entryPoint.src.file); | ||||||
|         compiler.injectSyntheticDecorator(myClass, injectedDecorator); |         compiler.injectSyntheticDecorator(myClass, injectedDecorator); | ||||||
| 
 | 
 | ||||||
|         const record = compiler.recordFor(myClass) !; |         const record = compiler.recordFor(myClass)!; | ||||||
|         expect(record).toBeDefined(); |         expect(record).toBeDefined(); | ||||||
|         expect(record.traits.length).toBe(2); |         expect(record.traits.length).toBe(2); | ||||||
|         expect(record.traits[0].detected.decorator !.name).toBe('Directive'); |         expect(record.traits[0].detected.decorator!.name).toBe('Directive'); | ||||||
|         expect(record.traits[1].detected.decorator !.name).toBe('InjectedDecorator'); |         expect(record.traits[1].detected.decorator!.name).toBe('InjectedDecorator'); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should not add a weak handler when a primary handler already exists', () => { |       it('should not add a weak handler when a primary handler already exists', () => { | ||||||
| @ -150,10 +150,10 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|         compiler.injectSyntheticDecorator(myClass, injectedDecorator); |         compiler.injectSyntheticDecorator(myClass, injectedDecorator); | ||||||
| 
 | 
 | ||||||
|         const record = compiler.recordFor(myClass) !; |         const record = compiler.recordFor(myClass)!; | ||||||
|         expect(record).toBeDefined(); |         expect(record).toBeDefined(); | ||||||
|         expect(record.traits.length).toBe(1); |         expect(record.traits.length).toBe(1); | ||||||
|         expect(record.traits[0].detected.decorator !.name).toBe('Directive'); |         expect(record.traits[0].detected.decorator!.name).toBe('Directive'); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should replace an existing weak handler when injecting a primary handler', () => { |       it('should replace an existing weak handler when injecting a primary handler', () => { | ||||||
| @ -181,10 +181,10 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|         compiler.injectSyntheticDecorator(myClass, injectedDecorator); |         compiler.injectSyntheticDecorator(myClass, injectedDecorator); | ||||||
| 
 | 
 | ||||||
|         const record = compiler.recordFor(myClass) !; |         const record = compiler.recordFor(myClass)!; | ||||||
|         expect(record).toBeDefined(); |         expect(record).toBeDefined(); | ||||||
|         expect(record.traits.length).toBe(1); |         expect(record.traits.length).toBe(1); | ||||||
|         expect(record.traits[0].detected.decorator !.name).toBe('InjectedDecorator'); |         expect(record.traits[0].detected.decorator!.name).toBe('InjectedDecorator'); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should produce an error when a primary handler is added when a primary handler is already present', |       it('should produce an error when a primary handler is added when a primary handler is already present', | ||||||
| @ -214,12 +214,11 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|            compiler.injectSyntheticDecorator(myClass, injectedDecorator); |            compiler.injectSyntheticDecorator(myClass, injectedDecorator); | ||||||
| 
 | 
 | ||||||
|            const record = compiler.recordFor(myClass) !; |            const record = compiler.recordFor(myClass)!; | ||||||
|            expect(record).toBeDefined(); |            expect(record).toBeDefined(); | ||||||
|            expect(record.metaDiagnostics).toBeDefined(); |            expect(record.metaDiagnostics).toBeDefined(); | ||||||
|            expect(record.metaDiagnostics !.length).toBe(1); |            expect(record.metaDiagnostics!.length).toBe(1); | ||||||
|            expect(record.metaDiagnostics ![0].code) |            expect(record.metaDiagnostics![0].code).toBe(ngErrorCode(ErrorCode.DECORATOR_COLLISION)); | ||||||
|                .toBe(ngErrorCode(ErrorCode.DECORATOR_COLLISION)); |  | ||||||
|            expect(record.traits.length).toBe(0); |            expect(record.traits.length).toBe(0); | ||||||
|          }); |          }); | ||||||
| 
 | 
 | ||||||
| @ -233,7 +232,7 @@ runInEachFileSystem(() => { | |||||||
|         const decorator = createComponentDecorator(mockClazz, {selector: 'comp', exportAs: null}); |         const decorator = createComponentDecorator(mockClazz, {selector: 'comp', exportAs: null}); | ||||||
|         compiler.injectSyntheticDecorator(mockClazz, decorator); |         compiler.injectSyntheticDecorator(mockClazz, decorator); | ||||||
| 
 | 
 | ||||||
|         const record = compiler.recordFor(mockClazz) !; |         const record = compiler.recordFor(mockClazz)!; | ||||||
|         const migratedTrait = record.traits[0]; |         const migratedTrait = record.traits[0]; | ||||||
|         if (migratedTrait.state !== TraitState.ERRORED) { |         if (migratedTrait.state !== TraitState.ERRORED) { | ||||||
|           return fail('Expected migrated class trait to be in an error state'); |           return fail('Expected migrated class trait to be in an error state'); | ||||||
| @ -286,13 +285,12 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|         compiler.injectSyntheticDecorator(myClass, injectedDecorator); |         compiler.injectSyntheticDecorator(myClass, injectedDecorator); | ||||||
| 
 | 
 | ||||||
|         const decorators = compiler.getAllDecorators(myClass) !; |         const decorators = compiler.getAllDecorators(myClass)!; | ||||||
|         expect(decorators.length).toBe(2); |         expect(decorators.length).toBe(2); | ||||||
|         expect(decorators[0].name).toBe('Directive'); |         expect(decorators[0].name).toBe('Directive'); | ||||||
|         expect(decorators[1].name).toBe('InjectedDecorator'); |         expect(decorators[1].name).toBe('InjectedDecorator'); | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
| 
 |  | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| @ -302,7 +300,7 @@ class TestHandler implements DecoratorHandler<unknown, unknown, unknown> { | |||||||
|   precedence = HandlerPrecedence.PRIMARY; |   precedence = HandlerPrecedence.PRIMARY; | ||||||
| 
 | 
 | ||||||
|   detect(node: ClassDeclaration, decorators: Decorator[]|null): DetectResult<unknown>|undefined { |   detect(node: ClassDeclaration, decorators: Decorator[]|null): DetectResult<unknown>|undefined { | ||||||
|     this.log.push(`${this.name}:detect:${node.name.text}:${decorators !.map(d => d.name)}`); |     this.log.push(`${this.name}:detect:${node.name.text}:${decorators!.map(d => d.name)}`); | ||||||
|     return undefined; |     return undefined; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -7,8 +7,8 @@ | |||||||
|  */ |  */ | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| 
 | 
 | ||||||
| import {AbsoluteFsPath, absoluteFrom} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {Reference} from '../../../src/ngtsc/imports'; | import {Reference} from '../../../src/ngtsc/imports'; | ||||||
| import {getDeclaration} from '../../../src/ngtsc/testing'; | import {getDeclaration} from '../../../src/ngtsc/testing'; | ||||||
| import {loadTestFiles} from '../../../test/helpers/src/mock_file_loading'; | import {loadTestFiles} from '../../../test/helpers/src/mock_file_loading'; | ||||||
| @ -192,6 +192,6 @@ runInEachFileSystem(() => { | |||||||
|       program: ts.Program, registry: NgccReferencesRegistry, fileName: AbsoluteFsPath, |       program: ts.Program, registry: NgccReferencesRegistry, fileName: AbsoluteFsPath, | ||||||
|       componentName: string) { |       componentName: string) { | ||||||
|     const declaration = getDeclaration(program, fileName, componentName, ts.isClassDeclaration); |     const declaration = getDeclaration(program, fileName, componentName, ts.isClassDeclaration); | ||||||
|     registry.add(null !, new Reference(declaration)); |     registry.add(null!, new Reference(declaration)); | ||||||
|   } |   } | ||||||
| }); | }); | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ | |||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| 
 | 
 | ||||||
| import {absoluteFrom} from '../../../src/ngtsc/file_system'; | import {absoluteFrom} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {Reference} from '../../../src/ngtsc/imports'; | import {Reference} from '../../../src/ngtsc/imports'; | ||||||
| import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator'; | import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator'; | ||||||
| import {TypeScriptReflectionHost} from '../../../src/ngtsc/reflection'; | import {TypeScriptReflectionHost} from '../../../src/ngtsc/reflection'; | ||||||
| @ -44,19 +44,19 @@ runInEachFileSystem(() => { | |||||||
|           getDeclaration(program, indexPath, 'someFunction', ts.isFunctionDeclaration); |           getDeclaration(program, indexPath, 'someFunction', ts.isFunctionDeclaration); | ||||||
|       const someVariableDecl = |       const someVariableDecl = | ||||||
|           getDeclaration(program, indexPath, 'someVariable', ts.isVariableDeclaration); |           getDeclaration(program, indexPath, 'someVariable', ts.isVariableDeclaration); | ||||||
|       const testArrayExpression = testArrayDeclaration.initializer !; |       const testArrayExpression = testArrayDeclaration.initializer!; | ||||||
| 
 | 
 | ||||||
|       const reflectionHost = new TypeScriptReflectionHost(checker); |       const reflectionHost = new TypeScriptReflectionHost(checker); | ||||||
|       const evaluator = new PartialEvaluator(reflectionHost, checker, /* dependencyTracker */ null); |       const evaluator = new PartialEvaluator(reflectionHost, checker, /* dependencyTracker */ null); | ||||||
|       const registry = new NgccReferencesRegistry(reflectionHost); |       const registry = new NgccReferencesRegistry(reflectionHost); | ||||||
| 
 | 
 | ||||||
|       const references = (evaluator.evaluate(testArrayExpression) as any[]).filter(isReference); |       const references = (evaluator.evaluate(testArrayExpression) as any[]).filter(isReference); | ||||||
|       registry.add(null !, ...references); |       registry.add(null!, ...references); | ||||||
| 
 | 
 | ||||||
|       const map = registry.getDeclarationMap(); |       const map = registry.getDeclarationMap(); | ||||||
|       expect(map.size).toEqual(2); |       expect(map.size).toEqual(2); | ||||||
|       expect(map.get(someClassDecl.name !) !.node).toBe(someClassDecl); |       expect(map.get(someClassDecl.name!)!.node).toBe(someClassDecl); | ||||||
|       expect(map.get(someFunctionDecl.name !) !.node).toBe(someFunctionDecl); |       expect(map.get(someFunctionDecl.name!)!.node).toBe(someFunctionDecl); | ||||||
|       expect(map.has(someVariableDecl.name as ts.Identifier)).toBe(false); |       expect(map.has(someVariableDecl.name as ts.Identifier)).toBe(false); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {absoluteFrom, getSourceFileOrError} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, getSourceFileOrError} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {loadTestFiles} from '../../../test/helpers'; | import {loadTestFiles} from '../../../test/helpers'; | ||||||
| import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer'; | import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer'; | ||||||
| import {Esm2015ReflectionHost} from '../../src/host/esm2015_host'; | import {Esm2015ReflectionHost} from '../../src/host/esm2015_host'; | ||||||
| @ -15,7 +15,6 @@ import {makeTestEntryPointBundle} from '../helpers/utils'; | |||||||
| 
 | 
 | ||||||
| runInEachFileSystem(() => { | runInEachFileSystem(() => { | ||||||
|   describe('SwitchMarkerAnalyzer', () => { |   describe('SwitchMarkerAnalyzer', () => { | ||||||
| 
 |  | ||||||
|     let _: typeof absoluteFrom; |     let _: typeof absoluteFrom; | ||||||
|     let TEST_PROGRAM: TestFile[]; |     let TEST_PROGRAM: TestFile[]; | ||||||
| 
 | 
 | ||||||
| @ -87,14 +86,14 @@ runInEachFileSystem(() => { | |||||||
|         expect(analysis.has(entrypoint)).toBe(false); |         expect(analysis.has(entrypoint)).toBe(false); | ||||||
|         expect(analysis.has(a)).toBe(false); |         expect(analysis.has(a)).toBe(false); | ||||||
|         expect(analysis.has(b)).toBe(true); |         expect(analysis.has(b)).toBe(true); | ||||||
|         expect(analysis.get(b) !.sourceFile).toBe(b); |         expect(analysis.get(b)!.sourceFile).toBe(b); | ||||||
|         expect(analysis.get(b) !.declarations.map(decl => decl.getText())).toEqual([ |         expect(analysis.get(b)!.declarations.map(decl => decl.getText())).toEqual([ | ||||||
|           'factoryB = factory__PRE_R3__' |           'factoryB = factory__PRE_R3__' | ||||||
|         ]); |         ]); | ||||||
| 
 | 
 | ||||||
|         expect(analysis.has(c)).toBe(true); |         expect(analysis.has(c)).toBe(true); | ||||||
|         expect(analysis.get(c) !.sourceFile).toBe(c); |         expect(analysis.get(c)!.sourceFile).toBe(c); | ||||||
|         expect(analysis.get(c) !.declarations.map(decl => decl.getText())).toEqual([ |         expect(analysis.get(c)!.declarations.map(decl => decl.getText())).toEqual([ | ||||||
|           'factoryC = factory__PRE_R3__', |           'factoryC = factory__PRE_R3__', | ||||||
|           'factoryD = factory__PRE_R3__', |           'factoryD = factory__PRE_R3__', | ||||||
|         ]); |         ]); | ||||||
|  | |||||||
| @ -387,7 +387,7 @@ runInEachFileSystem(() => { | |||||||
|     reExportsWithoutRequire?: string[]; |     reExportsWithoutRequire?: string[]; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   function commonJs(importsPerType: ImportsPerType | string[], exportNames: string[] = []): string { |   function commonJs(importsPerType: ImportsPerType|string[], exportNames: string[] = []): string { | ||||||
|     if (Array.isArray(importsPerType)) { |     if (Array.isArray(importsPerType)) { | ||||||
|       importsPerType = {varDeclaration: importsPerType}; |       importsPerType = {varDeclaration: importsPerType}; | ||||||
|     } |     } | ||||||
| @ -414,8 +414,9 @@ runInEachFileSystem(() => { | |||||||
|     } = importsPerType; |     } = importsPerType; | ||||||
| 
 | 
 | ||||||
|     // var foo = require('...');
 |     // var foo = require('...');
 | ||||||
|     importsOfTypeVarDeclaration.forEach( |     importsOfTypeVarDeclaration.forEach(p => { | ||||||
|         p => { importStatements.push(`var ${pathToVarName(p)} = require('${p}');`); }); |       importStatements.push(`var ${pathToVarName(p)} = require('${p}');`); | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     // var foo = require('...'), bar = require('...');
 |     // var foo = require('...'), bar = require('...');
 | ||||||
|     importsOfTypeVarDeclarations.forEach(pp => { |     importsOfTypeVarDeclarations.forEach(pp => { | ||||||
| @ -424,8 +425,9 @@ runInEachFileSystem(() => { | |||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     // exports.foo = require('...');
 |     // exports.foo = require('...');
 | ||||||
|     importsOfTypePropAssignment.forEach( |     importsOfTypePropAssignment.forEach(p => { | ||||||
|         p => { importStatements.push(`exports.${pathToVarName(p)} = require('${p}');`); }); |       importStatements.push(`exports.${pathToVarName(p)} = require('${p}');`); | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     // module.exports = {foo: require('...')};
 |     // module.exports = {foo: require('...')};
 | ||||||
|     const propAssignments = |     const propAssignments = | ||||||
| @ -434,15 +436,19 @@ runInEachFileSystem(() => { | |||||||
|     importStatements.push(`module.exports = {${propAssignments}\n};`); |     importStatements.push(`module.exports = {${propAssignments}\n};`); | ||||||
| 
 | 
 | ||||||
|     // require('...');
 |     // require('...');
 | ||||||
|     importsOfTypeForSideEffects.forEach(p => { importStatements.push(`require('${p}');`); }); |     importsOfTypeForSideEffects.forEach(p => { | ||||||
|  |       importStatements.push(`require('${p}');`); | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     // __export(require('...'));
 |     // __export(require('...'));
 | ||||||
|     importsOfTypeReExportsWithEmittedHelper.forEach( |     importsOfTypeReExportsWithEmittedHelper.forEach(p => { | ||||||
|         p => { importStatements.push(`__export(require('${p}'));`); }); |       importStatements.push(`__export(require('${p}'));`); | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     // tslib_1.__exportStar(require('...'), exports);
 |     // tslib_1.__exportStar(require('...'), exports);
 | ||||||
|     importsOfTypeReExportsWithImportedHelper.forEach( |     importsOfTypeReExportsWithImportedHelper.forEach(p => { | ||||||
|         p => { importStatements.push(`tslib_1.__exportStar(require('${p}'), exports);`); }); |       importStatements.push(`tslib_1.__exportStar(require('${p}'), exports);`); | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     // var foo = require('...');
 |     // var foo = require('...');
 | ||||||
|     // __export(foo);
 |     // __export(foo);
 | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ | |||||||
| 
 | 
 | ||||||
| import {DepGraph} from 'dependency-graph'; | import {DepGraph} from 'dependency-graph'; | ||||||
| 
 | 
 | ||||||
| import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, relativeFrom} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, relativeFrom} from '../../../src/ngtsc/file_system'; | ||||||
| import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {DependencyInfo} from '../../src/dependencies/dependency_host'; | import {DependencyInfo} from '../../src/dependencies/dependency_host'; | ||||||
| import {DependencyResolver, SortedEntryPointsInfo} from '../../src/dependencies/dependency_resolver'; | import {DependencyResolver, SortedEntryPointsInfo} from '../../src/dependencies/dependency_resolver'; | ||||||
| @ -254,7 +254,8 @@ runInEachFileSystem(() => { | |||||||
|         const result = resolver.sortEntryPointsByDependency([first]); |         const result = resolver.sortEntryPointsByDependency([first]); | ||||||
|         expect(result.entryPoints).toEqual([first]); |         expect(result.entryPoints).toEqual([first]); | ||||||
|         expect(logger.logs.warn).toEqual([[ |         expect(logger.logs.warn).toEqual([[ | ||||||
|           `Entry point 'first' contains deep imports into '${_('/deep/one')}'. This is probably not a problem, but may cause the compilation of entry points to be out of order.` |           `Entry point 'first' contains deep imports into '${ | ||||||
|  |               _('/deep/one')}'. This is probably not a problem, but may cause the compilation of entry points to be out of order.` | ||||||
|         ]]); |         ]]); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -292,14 +293,14 @@ runInEachFileSystem(() => { | |||||||
|         const result = resolver.sortEntryPointsByDependency([testEntryPoint]); |         const result = resolver.sortEntryPointsByDependency([testEntryPoint]); | ||||||
|         expect(result.entryPoints).toEqual([testEntryPoint]); |         expect(result.entryPoints).toEqual([testEntryPoint]); | ||||||
|         expect(logger.logs.warn).toEqual([[ |         expect(logger.logs.warn).toEqual([[ | ||||||
|           `Entry point 'test-package' contains deep imports into '${_('/project/node_modules/deeper/one')}'. This is probably not a problem, but may cause the compilation of entry points to be out of order.` |           `Entry point 'test-package' contains deep imports into '${ | ||||||
|  |               _('/project/node_modules/deeper/one')}'. This is probably not a problem, but may cause the compilation of entry points to be out of order.` | ||||||
|         ]]); |         ]]); | ||||||
| 
 |  | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should error if the entry point does not have a suitable format', () => { |       it('should error if the entry point does not have a suitable format', () => { | ||||||
|         expect(() => resolver.sortEntryPointsByDependency([ |         expect(() => resolver.sortEntryPointsByDependency([ | ||||||
|           { path: '/first', packageJson: {}, compiledByAngular: true } as EntryPoint |           {path: '/first', packageJson: {}, compiledByAngular: true} as EntryPoint | ||||||
|         ])).toThrowError(`There is no appropriate source code format in '/first' entry-point.`); |         ])).toThrowError(`There is no appropriate source code format in '/first' entry-point.`); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -307,7 +308,8 @@ runInEachFileSystem(() => { | |||||||
|         resolver = new DependencyResolver(fs, new MockLogger(), config, {esm2015: host}, host); |         resolver = new DependencyResolver(fs, new MockLogger(), config, {esm2015: host}, host); | ||||||
|         expect(() => resolver.sortEntryPointsByDependency([first])) |         expect(() => resolver.sortEntryPointsByDependency([first])) | ||||||
|             .toThrowError( |             .toThrowError( | ||||||
|                 `Could not find a suitable format for computing dependencies of entry-point: '${first.path}'.`); |                 `Could not find a suitable format for computing dependencies of entry-point: '${ | ||||||
|  |                     first.path}'.`);
 | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should capture any dependencies that were ignored', () => { |       it('should capture any dependencies that were ignored', () => { | ||||||
| @ -462,7 +464,7 @@ runInEachFileSystem(() => { | |||||||
|           deps[entryPointPath].missing.forEach( |           deps[entryPointPath].missing.forEach( | ||||||
|               dep => missing.add(fs.isRooted(dep) ? absoluteFrom(dep) : relativeFrom(dep))); |               dep => missing.add(fs.isRooted(dep) ? absoluteFrom(dep) : relativeFrom(dep))); | ||||||
|           if (deps[entryPointPath].deepImports) { |           if (deps[entryPointPath].deepImports) { | ||||||
|             deps[entryPointPath].deepImports !.forEach(dep => deepImports.add(dep)); |             deps[entryPointPath].deepImports!.forEach(dep => deepImports.add(dep)); | ||||||
|           } |           } | ||||||
|           return {dependencies, missing, deepImports}; |           return {dependencies, missing, deepImports}; | ||||||
|         }; |         }; | ||||||
|  | |||||||
| @ -14,7 +14,6 @@ import {createDependencyInfo} from '../../src/dependencies/dependency_host'; | |||||||
| import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host'; | import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host'; | ||||||
| 
 | 
 | ||||||
| runInEachFileSystem(() => { | runInEachFileSystem(() => { | ||||||
| 
 |  | ||||||
|   describe('DtsDependencyHost', () => { |   describe('DtsDependencyHost', () => { | ||||||
|     let _: typeof absoluteFrom; |     let _: typeof absoluteFrom; | ||||||
|     let host: DtsDependencyHost; |     let host: DtsDependencyHost; | ||||||
|  | |||||||
| @ -16,7 +16,6 @@ import {EsmDependencyHost, hasImportOrReexportStatements, isStringImportOrReexpo | |||||||
| import {ModuleResolver} from '../../src/dependencies/module_resolver'; | import {ModuleResolver} from '../../src/dependencies/module_resolver'; | ||||||
| 
 | 
 | ||||||
| runInEachFileSystem(() => { | runInEachFileSystem(() => { | ||||||
| 
 |  | ||||||
|   describe('EsmDependencyHost', () => { |   describe('EsmDependencyHost', () => { | ||||||
|     let _: typeof absoluteFrom; |     let _: typeof absoluteFrom; | ||||||
|     let host: EsmDependencyHost; |     let host: EsmDependencyHost; | ||||||
|  | |||||||
| @ -251,8 +251,10 @@ runInEachFileSystem(() => { | |||||||
|         exportNames.map(e => `  exports.${e.replace(/.+\./, '')} = ${e};`).join('\n'); |         exportNames.map(e => `  exports.${e.replace(/.+\./, '')} = ${e};`).join('\n'); | ||||||
|     return ` |     return ` | ||||||
| (function (global, factory) { | (function (global, factory) { | ||||||
|   typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports${commonJsRequires}) : |   typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports${ | ||||||
|   typeof define === 'function' && define.amd ? define('${moduleName}', ['exports'${amdDeps}], factory) : |         commonJsRequires}) : | ||||||
|  |   typeof define === 'function' && define.amd ? define('${moduleName}', ['exports'${ | ||||||
|  |         amdDeps}], factory) : | ||||||
|   (factory(global.${moduleName}${globalParams})); |   (factory(global.${moduleName}${globalParams})); | ||||||
| }(this, (function (exports${params}) { 'use strict'; | }(this, (function (exports${params}) { 'use strict'; | ||||||
| ${exportStatements} | ${exportStatements} | ||||||
|  | |||||||
| @ -5,8 +5,8 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, relative} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, relative} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {loadTestFiles} from '../../../test/helpers'; | import {loadTestFiles} from '../../../test/helpers'; | ||||||
| import {DependencyResolver} from '../../src/dependencies/dependency_resolver'; | import {DependencyResolver} from '../../src/dependencies/dependency_resolver'; | ||||||
| import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host'; | import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host'; | ||||||
|  | |||||||
| @ -5,8 +5,8 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, relative} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, relative} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {loadTestFiles} from '../../../test/helpers'; | import {loadTestFiles} from '../../../test/helpers'; | ||||||
| import {DependencyResolver} from '../../src/dependencies/dependency_resolver'; | import {DependencyResolver} from '../../src/dependencies/dependency_resolver'; | ||||||
| import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host'; | import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host'; | ||||||
| @ -365,7 +365,6 @@ runInEachFileSystem(() => { | |||||||
|           basePath: AbsoluteFsPath, entryPoints: EntryPoint[]): [string, string][] { |           basePath: AbsoluteFsPath, entryPoints: EntryPoint[]): [string, string][] { | ||||||
|         return entryPoints.map(x => [relative(basePath, x.package), relative(basePath, x.path)]); |         return entryPoints.map(x => [relative(basePath, x.package), relative(basePath, x.path)]); | ||||||
|       } |       } | ||||||
| 
 |  | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     describe('targetNeedsProcessingOrCleaning()', () => { |     describe('targetNeedsProcessingOrCleaning()', () => { | ||||||
|  | |||||||
| @ -132,9 +132,12 @@ runInEachFileSystem(() => { | |||||||
|         fs.resolve(projectDirectory, 'dist-1'), |         fs.resolve(projectDirectory, 'dist-1'), | ||||||
|       ]); |       ]); | ||||||
|       expect(logger.logs.warn).toEqual([ |       expect(logger.logs.warn).toEqual([ | ||||||
|         [`The basePath "${fs.resolve(projectDirectory, 'sub-folder/dist-2')}" computed from baseUrl "${projectDirectory}" and path mapping "sub-folder/dist-2" does not exist in the file-system.\n` + |         [`The basePath "${ | ||||||
|  |              fs.resolve(projectDirectory, 'sub-folder/dist-2')}" computed from baseUrl "${ | ||||||
|  |              projectDirectory}" and path mapping "sub-folder/dist-2" does not exist in the file-system.\n` +
 | ||||||
|          `It will not be scanned for entry-points.`], |          `It will not be scanned for entry-points.`], | ||||||
|         [`The basePath "${fs.resolve(projectDirectory, 'libs')}" computed from baseUrl "${projectDirectory}" and path mapping "libs/*" does not exist in the file-system.\n` + |         [`The basePath "${fs.resolve(projectDirectory, 'libs')}" computed from baseUrl "${ | ||||||
|  |              projectDirectory}" and path mapping "libs/*" does not exist in the file-system.\n` +
 | ||||||
|          `It will not be scanned for entry-points.`], |          `It will not be scanned for entry-points.`], | ||||||
|       ]); |       ]); | ||||||
|     }); |     }); | ||||||
|  | |||||||
| @ -51,7 +51,7 @@ describe('ClusterExecutor', () => { | |||||||
|     describe('(on cluster master)', () => { |     describe('(on cluster master)', () => { | ||||||
|       beforeEach(() => runAsClusterMaster(true)); |       beforeEach(() => runAsClusterMaster(true)); | ||||||
| 
 | 
 | ||||||
|       it('should log debug info about the executor', async() => { |       it('should log debug info about the executor', async () => { | ||||||
|         const anyFn: () => any = () => undefined; |         const anyFn: () => any = () => undefined; | ||||||
|         await executor.execute(anyFn, anyFn); |         await executor.execute(anyFn, anyFn); | ||||||
| 
 | 
 | ||||||
| @ -60,7 +60,7 @@ describe('ClusterExecutor', () => { | |||||||
|         ]); |         ]); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should delegate to `ClusterMaster#run()`', async() => { |       it('should delegate to `ClusterMaster#run()`', async () => { | ||||||
|         const analyzeEntryPointsSpy = jasmine.createSpy('analyzeEntryPoints'); |         const analyzeEntryPointsSpy = jasmine.createSpy('analyzeEntryPoints'); | ||||||
|         const createCompilerFnSpy = jasmine.createSpy('createCompilerFn'); |         const createCompilerFnSpy = jasmine.createSpy('createCompilerFn'); | ||||||
| 
 | 
 | ||||||
| @ -75,13 +75,13 @@ describe('ClusterExecutor', () => { | |||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should call LockFile.write() and LockFile.remove() if master runner completes successfully', |       it('should call LockFile.write() and LockFile.remove() if master runner completes successfully', | ||||||
|          async() => { |          async () => { | ||||||
|            const anyFn: () => any = () => undefined; |            const anyFn: () => any = () => undefined; | ||||||
|            await executor.execute(anyFn, anyFn); |            await executor.execute(anyFn, anyFn); | ||||||
|            expect(lockFileLog).toEqual(['write()', 'remove()']); |            expect(lockFileLog).toEqual(['write()', 'remove()']); | ||||||
|          }); |          }); | ||||||
| 
 | 
 | ||||||
|       it('should call LockFile.write() and LockFile.remove() if master runner fails', async() => { |       it('should call LockFile.write() and LockFile.remove() if master runner fails', async () => { | ||||||
|         const anyFn: () => any = () => undefined; |         const anyFn: () => any = () => undefined; | ||||||
|         masterRunSpy.and.returnValue(Promise.reject(new Error('master runner error'))); |         masterRunSpy.and.returnValue(Promise.reject(new Error('master runner error'))); | ||||||
|         let error = ''; |         let error = ''; | ||||||
| @ -94,7 +94,7 @@ describe('ClusterExecutor', () => { | |||||||
|         expect(lockFileLog).toEqual(['write()', 'remove()']); |         expect(lockFileLog).toEqual(['write()', 'remove()']); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should not call master runner if LockFile.write() fails', async() => { |       it('should not call master runner if LockFile.write() fails', async () => { | ||||||
|         const anyFn: () => any = () => undefined; |         const anyFn: () => any = () => undefined; | ||||||
|         spyOn(mockLockFile, 'write').and.callFake(() => { |         spyOn(mockLockFile, 'write').and.callFake(() => { | ||||||
|           lockFileLog.push('write()'); |           lockFileLog.push('write()'); | ||||||
| @ -114,7 +114,7 @@ describe('ClusterExecutor', () => { | |||||||
|         expect(masterRunSpy).not.toHaveBeenCalled(); |         expect(masterRunSpy).not.toHaveBeenCalled(); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should fail if LockFile.remove() fails', async() => { |       it('should fail if LockFile.remove() fails', async () => { | ||||||
|         const anyFn: () => any = () => undefined; |         const anyFn: () => any = () => undefined; | ||||||
|         spyOn(mockLockFile, 'remove').and.callFake(() => { |         spyOn(mockLockFile, 'remove').and.callFake(() => { | ||||||
|           lockFileLog.push('remove()'); |           lockFileLog.push('remove()'); | ||||||
| @ -139,14 +139,14 @@ describe('ClusterExecutor', () => { | |||||||
|     describe('(on cluster worker)', () => { |     describe('(on cluster worker)', () => { | ||||||
|       beforeEach(() => runAsClusterMaster(false)); |       beforeEach(() => runAsClusterMaster(false)); | ||||||
| 
 | 
 | ||||||
|       it('should not log debug info about the executor', async() => { |       it('should not log debug info about the executor', async () => { | ||||||
|         const anyFn: () => any = () => undefined; |         const anyFn: () => any = () => undefined; | ||||||
|         await executor.execute(anyFn, anyFn); |         await executor.execute(anyFn, anyFn); | ||||||
| 
 | 
 | ||||||
|         expect(mockLogger.logs.debug).toEqual([]); |         expect(mockLogger.logs.debug).toEqual([]); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should delegate to `ClusterWorker#run()`', async() => { |       it('should delegate to `ClusterWorker#run()`', async () => { | ||||||
|         const analyzeEntryPointsSpy = jasmine.createSpy('analyzeEntryPoints'); |         const analyzeEntryPointsSpy = jasmine.createSpy('analyzeEntryPoints'); | ||||||
|         const createCompilerFnSpy = jasmine.createSpy('createCompilerFn'); |         const createCompilerFnSpy = jasmine.createSpy('createCompilerFn'); | ||||||
| 
 | 
 | ||||||
| @ -160,7 +160,7 @@ describe('ClusterExecutor', () => { | |||||||
|         expect(createCompilerFnSpy).toHaveBeenCalledWith(jasmine.any(Function)); |         expect(createCompilerFnSpy).toHaveBeenCalledWith(jasmine.any(Function)); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should not call LockFile.write() or LockFile.remove()', async() => { |       it('should not call LockFile.write() or LockFile.remove()', async () => { | ||||||
|         const anyFn: () => any = () => undefined; |         const anyFn: () => any = () => undefined; | ||||||
|         await executor.execute(anyFn, anyFn); |         await executor.execute(anyFn, anyFn); | ||||||
|         expect(lockFileLog).toEqual([]); |         expect(lockFileLog).toEqual([]); | ||||||
|  | |||||||
| @ -39,8 +39,9 @@ runInEachFileSystem(() => { | |||||||
|           isMaster => describe(`(on cluster ${isMaster ? 'master' : 'worker'})`, () => { |           isMaster => describe(`(on cluster ${isMaster ? 'master' : 'worker'})`, () => { | ||||||
|             beforeEach(() => runAsClusterMaster(isMaster)); |             beforeEach(() => runAsClusterMaster(isMaster)); | ||||||
| 
 | 
 | ||||||
|             it('should return a `PackageJsonUpdate` instance', |             it('should return a `PackageJsonUpdate` instance', () => { | ||||||
|                () => { expect(updater.createUpdate()).toEqual(jasmine.any(PackageJsonUpdate)); }); |               expect(updater.createUpdate()).toEqual(jasmine.any(PackageJsonUpdate)); | ||||||
|  |             }); | ||||||
| 
 | 
 | ||||||
|             it('should wire up the `PackageJsonUpdate` with its `writeChanges()` method', () => { |             it('should wire up the `PackageJsonUpdate` with its `writeChanges()` method', () => { | ||||||
|               const writeChangesSpy = spyOn(updater, 'writeChanges'); |               const writeChangesSpy = spyOn(updater, 'writeChanges'); | ||||||
|  | |||||||
| @ -60,11 +60,9 @@ describe('ClusterWorker', () => { | |||||||
| 
 | 
 | ||||||
|         onTaskCompleted(null as any, TaskProcessingOutcome.Processed, null); |         onTaskCompleted(null as any, TaskProcessingOutcome.Processed, null); | ||||||
|         expect(processSendSpy).toHaveBeenCalledTimes(1); |         expect(processSendSpy).toHaveBeenCalledTimes(1); | ||||||
|         expect(processSendSpy).toHaveBeenCalledWith({ |         expect(processSendSpy) | ||||||
|           type: 'task-completed', |             .toHaveBeenCalledWith( | ||||||
|           outcome: TaskProcessingOutcome.Processed, |                 {type: 'task-completed', outcome: TaskProcessingOutcome.Processed, message: null}); | ||||||
|           message: null |  | ||||||
|         }); |  | ||||||
| 
 | 
 | ||||||
|         processSendSpy.calls.reset(); |         processSendSpy.calls.reset(); | ||||||
| 
 | 
 | ||||||
| @ -137,7 +135,9 @@ describe('ClusterWorker', () => { | |||||||
|         } as unknown as Task; |         } as unknown as Task; | ||||||
| 
 | 
 | ||||||
|         let err: string|Error; |         let err: string|Error; | ||||||
|         compileFnSpy.and.callFake(() => { throw err; }); |         compileFnSpy.and.callFake(() => { | ||||||
|  |           throw err; | ||||||
|  |         }); | ||||||
| 
 | 
 | ||||||
|         worker.run(); |         worker.run(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -14,8 +14,8 @@ import {EntryPoint} from '../../src/packages/entry_point'; | |||||||
|  * |  * | ||||||
|  * NOTE 1: The first task for each entry-point generates typings (which is similar to what happens |  * NOTE 1: The first task for each entry-point generates typings (which is similar to what happens | ||||||
|  *         in the actual code). |  *         in the actual code). | ||||||
|  * NOTE 2: The `computeTaskDependencies()` implementation relies on the fact that tasks are sorted in such |  * NOTE 2: The `computeTaskDependencies()` implementation relies on the fact that tasks are sorted | ||||||
|  *         a way that a task can only depend upon earlier tasks (i.e. dependencies always come |  * in such a way that a task can only depend upon earlier tasks (i.e. dependencies always come | ||||||
|  *         before dependents in the list of tasks). |  *         before dependents in the list of tasks). | ||||||
|  *         To preserve this attribute, you need to ensure that entry-points will only depend on |  *         To preserve this attribute, you need to ensure that entry-points will only depend on | ||||||
|  *         entry-points with a lower index. Take this into account when defining `entryPointDeps`. |  *         entry-points with a lower index. Take this into account when defining `entryPointDeps`. | ||||||
| @ -52,7 +52,7 @@ export function createTasksAndGraph( | |||||||
|     graph.addNode(entryPoint.path); |     graph.addNode(entryPoint.path); | ||||||
| 
 | 
 | ||||||
|     for (let tIdx = 0; tIdx < tasksPerEntryPointCount; tIdx++) { |     for (let tIdx = 0; tIdx < tasksPerEntryPointCount; tIdx++) { | ||||||
|       tasks.push({ entryPoint, formatProperty: `prop-${tIdx}`, processDts: tIdx === 0 } as Task); |       tasks.push({entryPoint, formatProperty: `prop-${tIdx}`, processDts: tIdx === 0} as Task); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -33,11 +33,13 @@ describe('SingleProcessExecutor', () => { | |||||||
|     executor = new SingleProcessExecutorSync(mockLogger, locker, createTaskCompletedCallback); |     executor = new SingleProcessExecutorSync(mockLogger, locker, createTaskCompletedCallback); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   const noTasks = () => ({ allTasksCompleted: true, getNextTask: () => null } as TaskQueue); |   const noTasks = () => ({allTasksCompleted: true, getNextTask: () => null} as TaskQueue); | ||||||
|   const oneTask = () => { |   const oneTask = () => { | ||||||
|     let tasksCount = 1; |     let tasksCount = 1; | ||||||
|     return <TaskQueue>{ |     return <TaskQueue>{ | ||||||
|       get allTasksCompleted() { return tasksCount === 0; }, |       get allTasksCompleted() { | ||||||
|  |         return tasksCount === 0; | ||||||
|  |       }, | ||||||
|       getNextTask() { |       getNextTask() { | ||||||
|         tasksCount--; |         tasksCount--; | ||||||
|         return {}; |         return {}; | ||||||
| @ -55,7 +57,9 @@ describe('SingleProcessExecutor', () => { | |||||||
|        }); |        }); | ||||||
| 
 | 
 | ||||||
|     it('should call LockFile.write() and LockFile.remove() if `analyzeEntryPoints` fails', () => { |     it('should call LockFile.write() and LockFile.remove() if `analyzeEntryPoints` fails', () => { | ||||||
|       const errorFn: () => never = () => { throw new Error('analyze error'); }; |       const errorFn: () => never = () => { | ||||||
|  |         throw new Error('analyze error'); | ||||||
|  |       }; | ||||||
|       const createCompileFn: () => any = () => undefined; |       const createCompileFn: () => any = () => undefined; | ||||||
|       let error: string = ''; |       let error: string = ''; | ||||||
|       try { |       try { | ||||||
| @ -68,7 +72,9 @@ describe('SingleProcessExecutor', () => { | |||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should call LockFile.write() and LockFile.remove() if `createCompileFn` fails', () => { |     it('should call LockFile.write() and LockFile.remove() if `createCompileFn` fails', () => { | ||||||
|       const createErrorCompileFn: () => any = () => { throw new Error('compile error'); }; |       const createErrorCompileFn: () => any = () => { | ||||||
|  |         throw new Error('compile error'); | ||||||
|  |       }; | ||||||
|       let error: string = ''; |       let error: string = ''; | ||||||
|       try { |       try { | ||||||
|         executor.execute(oneTask, createErrorCompileFn); |         executor.execute(oneTask, createErrorCompileFn); | ||||||
| @ -85,7 +91,9 @@ describe('SingleProcessExecutor', () => { | |||||||
|         throw new Error('LockFile.write() error'); |         throw new Error('LockFile.write() error'); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       const analyzeFn: () => any = () => { lockFileLog.push('analyzeFn'); }; |       const analyzeFn: () => any = () => { | ||||||
|  |         lockFileLog.push('analyzeFn'); | ||||||
|  |       }; | ||||||
|       const anyFn: () => any = () => undefined; |       const anyFn: () => any = () => undefined; | ||||||
|       executor = new SingleProcessExecutorSync(mockLogger, locker, createTaskCompletedCallback); |       executor = new SingleProcessExecutorSync(mockLogger, locker, createTaskCompletedCallback); | ||||||
|       let error = ''; |       let error = ''; | ||||||
|  | |||||||
| @ -77,9 +77,9 @@ describe('ParallelTaskQueue', () => { | |||||||
|     it('should be `true`, when there are no unprocess or in-progress tasks', () => { |     it('should be `true`, when there are no unprocess or in-progress tasks', () => { | ||||||
|       const {queue} = createQueue(3); |       const {queue} = createQueue(3); | ||||||
| 
 | 
 | ||||||
|       const task1 = queue.getNextTask() !; |       const task1 = queue.getNextTask()!; | ||||||
|       const task2 = queue.getNextTask() !; |       const task2 = queue.getNextTask()!; | ||||||
|       const task3 = queue.getNextTask() !; |       const task3 = queue.getNextTask()!; | ||||||
|       expect(queue.allTasksCompleted).toBe(false); |       expect(queue.allTasksCompleted).toBe(false); | ||||||
| 
 | 
 | ||||||
|       queue.markTaskCompleted(task1); |       queue.markTaskCompleted(task1); | ||||||
| @ -266,8 +266,8 @@ describe('ParallelTaskQueue', () => { | |||||||
|     it('should mark a task as completed', () => { |     it('should mark a task as completed', () => { | ||||||
|       const {queue} = createQueue(2); |       const {queue} = createQueue(2); | ||||||
| 
 | 
 | ||||||
|       const task1 = queue.getNextTask() !; |       const task1 = queue.getNextTask()!; | ||||||
|       const task2 = queue.getNextTask() !; |       const task2 = queue.getNextTask()!; | ||||||
|       expect(queue.allTasksCompleted).toBe(false); |       expect(queue.allTasksCompleted).toBe(false); | ||||||
| 
 | 
 | ||||||
|       queue.markTaskCompleted(task1); |       queue.markTaskCompleted(task1); | ||||||
| @ -327,7 +327,7 @@ describe('ParallelTaskQueue', () => { | |||||||
| 
 | 
 | ||||||
|       processNextTask(queue2); |       processNextTask(queue2); | ||||||
|       processNextTask(queue2); |       processNextTask(queue2); | ||||||
|       const task = queue2.getNextTask() !; |       const task = queue2.getNextTask()!; | ||||||
| 
 | 
 | ||||||
|       expect(queue2.toString()).toContain('  All tasks completed: false\n'); |       expect(queue2.toString()).toContain('  All tasks completed: false\n'); | ||||||
| 
 | 
 | ||||||
| @ -344,7 +344,7 @@ describe('ParallelTaskQueue', () => { | |||||||
|               '    - {entryPoint: entry-point-1, formatProperty: prop-0, processDts: true}\n' + |               '    - {entryPoint: entry-point-1, formatProperty: prop-0, processDts: true}\n' + | ||||||
|               '    - {entryPoint: entry-point-2, formatProperty: prop-0, processDts: true}\n'); |               '    - {entryPoint: entry-point-2, formatProperty: prop-0, processDts: true}\n'); | ||||||
| 
 | 
 | ||||||
|       const task1 = queue.getNextTask() !; |       const task1 = queue.getNextTask()!; | ||||||
|       expect(queue.toString()) |       expect(queue.toString()) | ||||||
|           .toContain( |           .toContain( | ||||||
|               '  Unprocessed tasks (2): \n' + |               '  Unprocessed tasks (2): \n' + | ||||||
| @ -352,7 +352,7 @@ describe('ParallelTaskQueue', () => { | |||||||
|               '    - {entryPoint: entry-point-2, formatProperty: prop-0, processDts: true}\n'); |               '    - {entryPoint: entry-point-2, formatProperty: prop-0, processDts: true}\n'); | ||||||
| 
 | 
 | ||||||
|       queue.markTaskCompleted(task1); |       queue.markTaskCompleted(task1); | ||||||
|       const task2 = queue.getNextTask() !; |       const task2 = queue.getNextTask()!; | ||||||
|       expect(queue.toString()) |       expect(queue.toString()) | ||||||
|           .toContain( |           .toContain( | ||||||
|               '  Unprocessed tasks (1): \n' + |               '  Unprocessed tasks (1): \n' + | ||||||
| @ -367,14 +367,14 @@ describe('ParallelTaskQueue', () => { | |||||||
|       const {queue} = createQueue(3); |       const {queue} = createQueue(3); | ||||||
|       expect(queue.toString()).toContain('  In-progress tasks (0): \n'); |       expect(queue.toString()).toContain('  In-progress tasks (0): \n'); | ||||||
| 
 | 
 | ||||||
|       const task1 = queue.getNextTask() !; |       const task1 = queue.getNextTask()!; | ||||||
|       expect(queue.toString()) |       expect(queue.toString()) | ||||||
|           .toContain( |           .toContain( | ||||||
|               '  In-progress tasks (1): \n' + |               '  In-progress tasks (1): \n' + | ||||||
|               '    - {entryPoint: entry-point-0, formatProperty: prop-0, processDts: true}\n'); |               '    - {entryPoint: entry-point-0, formatProperty: prop-0, processDts: true}\n'); | ||||||
| 
 | 
 | ||||||
|       queue.markTaskCompleted(task1); |       queue.markTaskCompleted(task1); | ||||||
|       const task2 = queue.getNextTask() !; |       const task2 = queue.getNextTask()!; | ||||||
|       expect(queue.toString()) |       expect(queue.toString()) | ||||||
|           .toContain( |           .toContain( | ||||||
|               '  In-progress tasks (1): \n' + |               '  In-progress tasks (1): \n' + | ||||||
|  | |||||||
| @ -30,12 +30,10 @@ describe('SerialTaskQueue', () => { | |||||||
|     const tasks: PartiallyOrderedTasks = [] as any; |     const tasks: PartiallyOrderedTasks = [] as any; | ||||||
|     const graph = new DepGraph<EntryPoint>(); |     const graph = new DepGraph<EntryPoint>(); | ||||||
|     for (let i = 0; i < taskCount; i++) { |     for (let i = 0; i < taskCount; i++) { | ||||||
|       const entryPoint = { |       const entryPoint = {name: `entry-point-${i}`, path: `/path/to/entry/point/${i}`} as | ||||||
|         name: `entry-point-${i}`, |           EntryPoint; | ||||||
|         path: `/path/to/entry/point/${i}` |  | ||||||
|       } as EntryPoint; |  | ||||||
|       tasks.push( |       tasks.push( | ||||||
|           { entryPoint: entryPoint, formatProperty: `prop-${i}`, processDts: i % 2 === 0 } as Task); |           {entryPoint: entryPoint, formatProperty: `prop-${i}`, processDts: i % 2 === 0} as Task); | ||||||
|       graph.addNode(entryPoint.path); |       graph.addNode(entryPoint.path); | ||||||
|     } |     } | ||||||
|     const dependencies = computeTaskDependencies(tasks, graph); |     const dependencies = computeTaskDependencies(tasks, graph); | ||||||
| @ -140,7 +138,7 @@ describe('SerialTaskQueue', () => { | |||||||
|   describe('markTaskCompleted()', () => { |   describe('markTaskCompleted()', () => { | ||||||
|     it('should mark a task as completed, so that the next task can be picked', () => { |     it('should mark a task as completed, so that the next task can be picked', () => { | ||||||
|       const {queue} = createQueue(3); |       const {queue} = createQueue(3); | ||||||
|       const task = queue.getNextTask() !; |       const task = queue.getNextTask()!; | ||||||
| 
 | 
 | ||||||
|       expect(() => queue.getNextTask()).toThrow(); |       expect(() => queue.getNextTask()).toThrow(); | ||||||
| 
 | 
 | ||||||
| @ -174,7 +172,7 @@ describe('SerialTaskQueue', () => { | |||||||
| 
 | 
 | ||||||
|       processNextTask(queue2); |       processNextTask(queue2); | ||||||
|       processNextTask(queue2); |       processNextTask(queue2); | ||||||
|       const task = queue2.getNextTask() !; |       const task = queue2.getNextTask()!; | ||||||
| 
 | 
 | ||||||
|       expect(queue2.toString()).toContain('  All tasks completed: false\n'); |       expect(queue2.toString()).toContain('  All tasks completed: false\n'); | ||||||
| 
 | 
 | ||||||
| @ -191,7 +189,7 @@ describe('SerialTaskQueue', () => { | |||||||
|               '    - {entryPoint: entry-point-1, formatProperty: prop-1, processDts: false}\n' + |               '    - {entryPoint: entry-point-1, formatProperty: prop-1, processDts: false}\n' + | ||||||
|               '    - {entryPoint: entry-point-2, formatProperty: prop-2, processDts: true}\n'); |               '    - {entryPoint: entry-point-2, formatProperty: prop-2, processDts: true}\n'); | ||||||
| 
 | 
 | ||||||
|       const task1 = queue.getNextTask() !; |       const task1 = queue.getNextTask()!; | ||||||
|       expect(queue.toString()) |       expect(queue.toString()) | ||||||
|           .toContain( |           .toContain( | ||||||
|               '  Unprocessed tasks (2): \n' + |               '  Unprocessed tasks (2): \n' + | ||||||
| @ -199,7 +197,7 @@ describe('SerialTaskQueue', () => { | |||||||
|               '    - {entryPoint: entry-point-2, formatProperty: prop-2, processDts: true}\n'); |               '    - {entryPoint: entry-point-2, formatProperty: prop-2, processDts: true}\n'); | ||||||
| 
 | 
 | ||||||
|       queue.markTaskCompleted(task1); |       queue.markTaskCompleted(task1); | ||||||
|       const task2 = queue.getNextTask() !; |       const task2 = queue.getNextTask()!; | ||||||
|       expect(queue.toString()) |       expect(queue.toString()) | ||||||
|           .toContain( |           .toContain( | ||||||
|               '  Unprocessed tasks (1): \n' + |               '  Unprocessed tasks (1): \n' + | ||||||
| @ -214,14 +212,14 @@ describe('SerialTaskQueue', () => { | |||||||
|       const {queue} = createQueue(3); |       const {queue} = createQueue(3); | ||||||
|       expect(queue.toString()).toContain('  In-progress tasks (0): '); |       expect(queue.toString()).toContain('  In-progress tasks (0): '); | ||||||
| 
 | 
 | ||||||
|       const task1 = queue.getNextTask() !; |       const task1 = queue.getNextTask()!; | ||||||
|       expect(queue.toString()) |       expect(queue.toString()) | ||||||
|           .toContain( |           .toContain( | ||||||
|               '  In-progress tasks (1): \n' + |               '  In-progress tasks (1): \n' + | ||||||
|               '    - {entryPoint: entry-point-0, formatProperty: prop-0, processDts: true}'); |               '    - {entryPoint: entry-point-0, formatProperty: prop-0, processDts: true}'); | ||||||
| 
 | 
 | ||||||
|       queue.markTaskCompleted(task1); |       queue.markTaskCompleted(task1); | ||||||
|       const task2 = queue.getNextTask() !; |       const task2 = queue.getNextTask()!; | ||||||
|       expect(queue.toString()) |       expect(queue.toString()) | ||||||
|           .toContain( |           .toContain( | ||||||
|               '  In-progress tasks (1): \n' + |               '  In-progress tasks (1): \n' + | ||||||
| @ -253,7 +251,7 @@ describe('SerialTaskQueue', () => { | |||||||
|               '  In-progress tasks (0): '); |               '  In-progress tasks (0): '); | ||||||
| 
 | 
 | ||||||
|       processNextTask(queue2); |       processNextTask(queue2); | ||||||
|       const task = queue2.getNextTask() !; |       const task = queue2.getNextTask()!; | ||||||
|       expect(queue2.toString()) |       expect(queue2.toString()) | ||||||
|           .toBe( |           .toBe( | ||||||
|               'SerialTaskQueue\n' + |               'SerialTaskQueue\n' + | ||||||
|  | |||||||
| @ -15,10 +15,14 @@ export class MockLockFile implements LockFile { | |||||||
|   constructor( |   constructor( | ||||||
|       fs: FileSystem, private log: string[] = [], public path = fs.resolve('/lockfile'), |       fs: FileSystem, private log: string[] = [], public path = fs.resolve('/lockfile'), | ||||||
|       private pid = '1234') {} |       private pid = '1234') {} | ||||||
|   write() { this.log.push('write()'); } |   write() { | ||||||
|  |     this.log.push('write()'); | ||||||
|  |   } | ||||||
|   read(): string { |   read(): string { | ||||||
|     this.log.push('read()'); |     this.log.push('read()'); | ||||||
|     return this.pid; |     return this.pid; | ||||||
|   } |   } | ||||||
|   remove() { this.log.push('remove()'); } |   remove() { | ||||||
|  |     this.log.push('remove()'); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| import {LogLevel, Logger} from '../../src/logging/logger'; | import {Logger, LogLevel} from '../../src/logging/logger'; | ||||||
| 
 | 
 | ||||||
| export class MockLogger implements Logger { | export class MockLogger implements Logger { | ||||||
|   constructor(public level = LogLevel.info) {} |   constructor(public level = LogLevel.info) {} | ||||||
| @ -17,8 +17,16 @@ export class MockLogger implements Logger { | |||||||
|     warn: [], |     warn: [], | ||||||
|     error: [], |     error: [], | ||||||
|   }; |   }; | ||||||
|   debug(...args: string[]) { this.logs.debug.push(args); } |   debug(...args: string[]) { | ||||||
|   info(...args: string[]) { this.logs.info.push(args); } |     this.logs.debug.push(args); | ||||||
|   warn(...args: string[]) { this.logs.warn.push(args); } |   } | ||||||
|   error(...args: string[]) { this.logs.error.push(args); } |   info(...args: string[]) { | ||||||
|  |     this.logs.info.push(args); | ||||||
|  |   } | ||||||
|  |   warn(...args: string[]) { | ||||||
|  |     this.logs.warn.push(args); | ||||||
|  |   } | ||||||
|  |   error(...args: string[]) { | ||||||
|  |     this.logs.error.push(args); | ||||||
|  |   } | ||||||
| } | } | ||||||
| @ -7,7 +7,7 @@ | |||||||
|  */ |  */ | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| 
 | 
 | ||||||
| import {AbsoluteFsPath, NgtscCompilerHost, absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath, getFileSystem, NgtscCompilerHost} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile} from '../../../src/ngtsc/file_system/testing'; | import {TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {BundleProgram, makeBundleProgram} from '../../src/packages/bundle_program'; | import {BundleProgram, makeBundleProgram} from '../../src/packages/bundle_program'; | ||||||
| import {NgccEntryPointConfig} from '../../src/packages/configuration'; | import {NgccEntryPointConfig} from '../../src/packages/configuration'; | ||||||
| @ -49,7 +49,12 @@ export function makeTestEntryPointBundle( | |||||||
|   return { |   return { | ||||||
|     entryPoint, |     entryPoint, | ||||||
|     format, |     format, | ||||||
|     rootDirs: [absoluteFrom('/')], src, dts, isCore, isFlatCore, enableI18nLegacyMessageIdFormat |     rootDirs: [absoluteFrom('/')], | ||||||
|  |     src, | ||||||
|  |     dts, | ||||||
|  |     isCore, | ||||||
|  |     isFlatCore, | ||||||
|  |     enableI18nLegacyMessageIdFormat | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; | import {isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; | ||||||
| import {getDeclaration} from '../../../src/ngtsc/testing'; | import {getDeclaration} from '../../../src/ngtsc/testing'; | ||||||
| import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; | import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; | ||||||
| @ -90,15 +90,15 @@ exports.AliasedDirective$1 = AliasedDirective$1; | |||||||
|         const classNode = getDeclaration( |         const classNode = getDeclaration( | ||||||
|             bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', |             bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', | ||||||
|             isNamedVariableDeclaration); |             isNamedVariableDeclaration); | ||||||
|         const decorators = host.getDecoratorsOfDeclaration(classNode) !; |         const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|         expect(decorators.length).toEqual(1); |         expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|         const decorator = decorators[0]; |         const decorator = decorators[0]; | ||||||
|         expect(decorator.name).toEqual('Directive'); |         expect(decorator.name).toEqual('Directive'); | ||||||
|         expect(decorator.identifier !.getText()).toEqual('core.Directive'); |         expect(decorator.identifier!.getText()).toEqual('core.Directive'); | ||||||
|         expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); |         expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); | ||||||
|         expect(decorator.args !.map(arg => arg.getText())).toEqual([ |         expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|           '{ selector: \'[someDirective]\' }', |           '{ selector: \'[someDirective]\' }', | ||||||
|         ]); |         ]); | ||||||
|       }); |       }); | ||||||
| @ -111,15 +111,15 @@ exports.AliasedDirective$1 = AliasedDirective$1; | |||||||
|         const classNode = getDeclaration( |         const classNode = getDeclaration( | ||||||
|             bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'AliasedDirective$1', |             bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'AliasedDirective$1', | ||||||
|             isNamedVariableDeclaration); |             isNamedVariableDeclaration); | ||||||
|         const decorators = host.getDecoratorsOfDeclaration(classNode) !; |         const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|         expect(decorators.length).toEqual(1); |         expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|         const decorator = decorators[0]; |         const decorator = decorators[0]; | ||||||
|         expect(decorator.name).toEqual('Directive'); |         expect(decorator.name).toEqual('Directive'); | ||||||
|         expect(decorator.identifier !.getText()).toEqual('core.Directive'); |         expect(decorator.identifier!.getText()).toEqual('core.Directive'); | ||||||
|         expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); |         expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); | ||||||
|         expect(decorator.args !.map(arg => arg.getText())).toEqual([ |         expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|           '{ selector: \'[someDirective]\' }', |           '{ selector: \'[someDirective]\' }', | ||||||
|         ]); |         ]); | ||||||
|       }); |       }); | ||||||
|  | |||||||
| @ -9,7 +9,7 @@ | |||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| 
 | 
 | ||||||
| import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {ClassMemberKind, Import, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; | import {ClassMemberKind, Import, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; | ||||||
| import {getDeclaration} from '../../../src/ngtsc/testing'; | import {getDeclaration} from '../../../src/ngtsc/testing'; | ||||||
| import {loadFakeCore, loadTestFiles, loadTsLib} from '../../../test/helpers'; | import {loadFakeCore, loadTestFiles, loadTsLib} from '../../../test/helpers'; | ||||||
| @ -168,16 +168,16 @@ runInEachFileSystem(() => { | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/some_directive.js'), 'SomeDirective', |                 bundle.program, _('/some_directive.js'), 'SomeDirective', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const decorators = host.getDecoratorsOfDeclaration(classNode) !; |             const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|             expect(decorators).toBeDefined(); |             expect(decorators).toBeDefined(); | ||||||
|             expect(decorators.length).toEqual(1); |             expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|             const decorator = decorators[0]; |             const decorator = decorators[0]; | ||||||
|             expect(decorator.name).toEqual('Directive'); |             expect(decorator.name).toEqual('Directive'); | ||||||
|             expect(decorator.identifier !.getText()).toEqual('Directive'); |             expect(decorator.identifier!.getText()).toEqual('Directive'); | ||||||
|             expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); |             expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); | ||||||
|             expect(decorator.args !.map(arg => arg.getText())).toEqual([ |             expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|               '{ selector: \'[someDirective]\' }', |               '{ selector: \'[someDirective]\' }', | ||||||
|             ]); |             ]); | ||||||
|           }); |           }); | ||||||
| @ -189,16 +189,16 @@ runInEachFileSystem(() => { | |||||||
|                const classNode = getDeclaration( |                const classNode = getDeclaration( | ||||||
|                    bundle.program, _('/some_directive_ctor_parameters.js'), 'SomeDirective', |                    bundle.program, _('/some_directive_ctor_parameters.js'), 'SomeDirective', | ||||||
|                    isNamedVariableDeclaration); |                    isNamedVariableDeclaration); | ||||||
|                const decorators = host.getDecoratorsOfDeclaration(classNode) !; |                const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|                expect(decorators).toBeDefined(); |                expect(decorators).toBeDefined(); | ||||||
|                expect(decorators.length).toEqual(1); |                expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|                const decorator = decorators[0]; |                const decorator = decorators[0]; | ||||||
|                expect(decorator.name).toEqual('Directive'); |                expect(decorator.name).toEqual('Directive'); | ||||||
|                expect(decorator.identifier !.getText()).toEqual('Directive'); |                expect(decorator.identifier!.getText()).toEqual('Directive'); | ||||||
|                expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); |                expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); | ||||||
|                expect(decorator.args !.map(arg => arg.getText())).toEqual([ |                expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|                  '{ selector: \'[someDirective]\' }', |                  '{ selector: \'[someDirective]\' }', | ||||||
|                ]); |                ]); | ||||||
|              }); |              }); | ||||||
| @ -210,16 +210,16 @@ runInEachFileSystem(() => { | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/node_modules/@angular/core/some_directive.js'), 'SomeDirective', |                 bundle.program, _('/node_modules/@angular/core/some_directive.js'), 'SomeDirective', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const decorators = host.getDecoratorsOfDeclaration(classNode) !; |             const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|             expect(decorators).toBeDefined(); |             expect(decorators).toBeDefined(); | ||||||
|             expect(decorators.length).toEqual(1); |             expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|             const decorator = decorators[0]; |             const decorator = decorators[0]; | ||||||
|             expect(decorator.name).toEqual('Directive'); |             expect(decorator.name).toEqual('Directive'); | ||||||
|             expect(decorator.identifier !.getText()).toEqual('Directive'); |             expect(decorator.identifier!.getText()).toEqual('Directive'); | ||||||
|             expect(decorator.import).toEqual({name: 'Directive', from: './directives'}); |             expect(decorator.import).toEqual({name: 'Directive', from: './directives'}); | ||||||
|             expect(decorator.args !.map(arg => arg.getText())).toEqual([ |             expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|               '{ selector: \'[someDirective]\' }', |               '{ selector: \'[someDirective]\' }', | ||||||
|             ]); |             ]); | ||||||
|           }); |           }); | ||||||
| @ -234,15 +234,15 @@ runInEachFileSystem(() => { | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const members = host.getMembersOfClass(classNode); |             const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|             const input1 = members.find(member => member.name === 'input1') !; |             const input1 = members.find(member => member.name === 'input1')!; | ||||||
|             expect(input1.kind).toEqual(ClassMemberKind.Property); |             expect(input1.kind).toEqual(ClassMemberKind.Property); | ||||||
|             expect(input1.isStatic).toEqual(false); |             expect(input1.isStatic).toEqual(false); | ||||||
|             expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); |             expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); | ||||||
| 
 | 
 | ||||||
|             const input2 = members.find(member => member.name === 'input2') !; |             const input2 = members.find(member => member.name === 'input2')!; | ||||||
|             expect(input2.kind).toEqual(ClassMemberKind.Property); |             expect(input2.kind).toEqual(ClassMemberKind.Property); | ||||||
|             expect(input2.isStatic).toEqual(false); |             expect(input2.isStatic).toEqual(false); | ||||||
|             expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); |             expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should find decorated members on a class when mixing `ctorParameters` and `__decorate`', |           it('should find decorated members on a class when mixing `ctorParameters` and `__decorate`', | ||||||
| @ -254,10 +254,10 @@ runInEachFileSystem(() => { | |||||||
|                    isNamedVariableDeclaration); |                    isNamedVariableDeclaration); | ||||||
|                const members = host.getMembersOfClass(classNode); |                const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|                const input1 = members.find(member => member.name === 'input1') !; |                const input1 = members.find(member => member.name === 'input1')!; | ||||||
|                expect(input1.kind).toEqual(ClassMemberKind.Property); |                expect(input1.kind).toEqual(ClassMemberKind.Property); | ||||||
|                expect(input1.isStatic).toEqual(false); |                expect(input1.isStatic).toEqual(false); | ||||||
|                expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); |                expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); | ||||||
|              }); |              }); | ||||||
| 
 | 
 | ||||||
|           it('should find non decorated properties on a class', () => { |           it('should find non decorated properties on a class', () => { | ||||||
| @ -268,11 +268,11 @@ runInEachFileSystem(() => { | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const members = host.getMembersOfClass(classNode); |             const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|             const instanceProperty = members.find(member => member.name === 'instanceProperty') !; |             const instanceProperty = members.find(member => member.name === 'instanceProperty')!; | ||||||
|             expect(instanceProperty.kind).toEqual(ClassMemberKind.Property); |             expect(instanceProperty.kind).toEqual(ClassMemberKind.Property); | ||||||
|             expect(instanceProperty.isStatic).toEqual(false); |             expect(instanceProperty.isStatic).toEqual(false); | ||||||
|             expect(ts.isBinaryExpression(instanceProperty.implementation !)).toEqual(true); |             expect(ts.isBinaryExpression(instanceProperty.implementation!)).toEqual(true); | ||||||
|             expect(instanceProperty.value !.getText()).toEqual(`'instance'`); |             expect(instanceProperty.value!.getText()).toEqual(`'instance'`); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should find static methods on a class', () => { |           it('should find static methods on a class', () => { | ||||||
| @ -283,10 +283,10 @@ runInEachFileSystem(() => { | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const members = host.getMembersOfClass(classNode); |             const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|             const staticMethod = members.find(member => member.name === 'staticMethod') !; |             const staticMethod = members.find(member => member.name === 'staticMethod')!; | ||||||
|             expect(staticMethod.kind).toEqual(ClassMemberKind.Method); |             expect(staticMethod.kind).toEqual(ClassMemberKind.Method); | ||||||
|             expect(staticMethod.isStatic).toEqual(true); |             expect(staticMethod.isStatic).toEqual(true); | ||||||
|             expect(ts.isMethodDeclaration(staticMethod.implementation !)).toEqual(true); |             expect(ts.isMethodDeclaration(staticMethod.implementation!)).toEqual(true); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should find static properties on a class', () => { |           it('should find static properties on a class', () => { | ||||||
| @ -297,11 +297,11 @@ runInEachFileSystem(() => { | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
| 
 | 
 | ||||||
|             const members = host.getMembersOfClass(classNode); |             const members = host.getMembersOfClass(classNode); | ||||||
|             const staticProperty = members.find(member => member.name === 'staticProperty') !; |             const staticProperty = members.find(member => member.name === 'staticProperty')!; | ||||||
|             expect(staticProperty.kind).toEqual(ClassMemberKind.Property); |             expect(staticProperty.kind).toEqual(ClassMemberKind.Property); | ||||||
|             expect(staticProperty.isStatic).toEqual(true); |             expect(staticProperty.isStatic).toEqual(true); | ||||||
|             expect(ts.isPropertyAccessExpression(staticProperty.implementation !)).toEqual(true); |             expect(ts.isPropertyAccessExpression(staticProperty.implementation!)).toEqual(true); | ||||||
|             expect(staticProperty.value !.getText()).toEqual(`'static'`); |             expect(staticProperty.value!.getText()).toEqual(`'static'`); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should find static properties on a class that has an intermediate variable assignment', |           it('should find static properties on a class that has an intermediate variable assignment', | ||||||
| @ -313,11 +313,11 @@ runInEachFileSystem(() => { | |||||||
|                    isNamedVariableDeclaration); |                    isNamedVariableDeclaration); | ||||||
| 
 | 
 | ||||||
|                const members = host.getMembersOfClass(classNode); |                const members = host.getMembersOfClass(classNode); | ||||||
|                const staticProperty = members.find(member => member.name === 'staticProperty') !; |                const staticProperty = members.find(member => member.name === 'staticProperty')!; | ||||||
|                expect(staticProperty.kind).toEqual(ClassMemberKind.Property); |                expect(staticProperty.kind).toEqual(ClassMemberKind.Property); | ||||||
|                expect(staticProperty.isStatic).toEqual(true); |                expect(staticProperty.isStatic).toEqual(true); | ||||||
|                expect(ts.isPropertyAccessExpression(staticProperty.implementation !)).toEqual(true); |                expect(ts.isPropertyAccessExpression(staticProperty.implementation!)).toEqual(true); | ||||||
|                expect(staticProperty.value !.getText()).toEqual(`'static'`); |                expect(staticProperty.value!.getText()).toEqual(`'static'`); | ||||||
|              }); |              }); | ||||||
| 
 | 
 | ||||||
|           it('should support decorators being used inside @angular/core', () => { |           it('should support decorators being used inside @angular/core', () => { | ||||||
| @ -329,10 +329,10 @@ runInEachFileSystem(() => { | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const members = host.getMembersOfClass(classNode); |             const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|             const input1 = members.find(member => member.name === 'input1') !; |             const input1 = members.find(member => member.name === 'input1')!; | ||||||
|             expect(input1.kind).toEqual(ClassMemberKind.Property); |             expect(input1.kind).toEqual(ClassMemberKind.Property); | ||||||
|             expect(input1.isStatic).toEqual(false); |             expect(input1.isStatic).toEqual(false); | ||||||
|             expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); |             expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); | ||||||
|           }); |           }); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -346,10 +346,10 @@ runInEachFileSystem(() => { | |||||||
|             const parameters = host.getConstructorParameters(classNode); |             const parameters = host.getConstructorParameters(classNode); | ||||||
| 
 | 
 | ||||||
|             expect(parameters).toBeDefined(); |             expect(parameters).toBeDefined(); | ||||||
|             expect(parameters !.map(parameter => parameter.name)).toEqual([ |             expect(parameters!.map(parameter => parameter.name)).toEqual([ | ||||||
|               '_viewContainer', '_template', 'injected' |               '_viewContainer', '_template', 'injected' | ||||||
|             ]); |             ]); | ||||||
|             expectTypeValueReferencesForParameters(parameters !, [ |             expectTypeValueReferencesForParameters(parameters!, [ | ||||||
|               'ViewContainerRef', |               'ViewContainerRef', | ||||||
|               'TemplateRef', |               'TemplateRef', | ||||||
|               'String', |               'String', | ||||||
| @ -366,20 +366,20 @@ runInEachFileSystem(() => { | |||||||
|                const parameters = host.getConstructorParameters(classNode); |                const parameters = host.getConstructorParameters(classNode); | ||||||
| 
 | 
 | ||||||
|                expect(parameters).toBeDefined(); |                expect(parameters).toBeDefined(); | ||||||
|                expect(parameters !.map(parameter => parameter.name)).toEqual([ |                expect(parameters!.map(parameter => parameter.name)).toEqual([ | ||||||
|                  '_viewContainer', '_template', 'injected' |                  '_viewContainer', '_template', 'injected' | ||||||
|                ]); |                ]); | ||||||
|                expectTypeValueReferencesForParameters(parameters !, [ |                expectTypeValueReferencesForParameters(parameters!, [ | ||||||
|                  'ViewContainerRef', |                  'ViewContainerRef', | ||||||
|                  'TemplateRef', |                  'TemplateRef', | ||||||
|                  null, |                  null, | ||||||
|                ]); |                ]); | ||||||
| 
 | 
 | ||||||
|                const decorators = parameters ![2].decorators !; |                const decorators = parameters![2].decorators!; | ||||||
|                expect(decorators.length).toEqual(1); |                expect(decorators.length).toEqual(1); | ||||||
|                expect(decorators[0].name).toBe('Inject'); |                expect(decorators[0].name).toBe('Inject'); | ||||||
|                expect(decorators[0].import !.from).toBe('@angular/core'); |                expect(decorators[0].import!.from).toBe('@angular/core'); | ||||||
|                expect(decorators[0].import !.name).toBe('Inject'); |                expect(decorators[0].import!.name).toBe('Inject'); | ||||||
|              }); |              }); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -390,8 +390,8 @@ runInEachFileSystem(() => { | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/some_directive.js'), 'SomeDirective', |                 bundle.program, _('/some_directive.js'), 'SomeDirective', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const ctrDecorators = host.getConstructorParameters(classNode) !; |             const ctrDecorators = host.getConstructorParameters(classNode)!; | ||||||
|             const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference !as{ |             const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference! as { | ||||||
|                                                    local: true, |                                                    local: true, | ||||||
|                                                    expression: ts.Identifier, |                                                    expression: ts.Identifier, | ||||||
|                                                    defaultImportStatement: null, |                                                    defaultImportStatement: null, | ||||||
| @ -401,8 +401,8 @@ runInEachFileSystem(() => { | |||||||
|                 bundle.program, _('/some_directive.js'), 'ViewContainerRef', ts.isClassDeclaration); |                 bundle.program, _('/some_directive.js'), 'ViewContainerRef', ts.isClassDeclaration); | ||||||
|             const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef); |             const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef); | ||||||
|             expect(actualDeclaration).not.toBe(null); |             expect(actualDeclaration).not.toBe(null); | ||||||
|             expect(actualDeclaration !.node).toBe(expectedDeclarationNode); |             expect(actualDeclaration!.node).toBe(expectedDeclarationNode); | ||||||
|             expect(actualDeclaration !.viaModule).toBe(null); |             expect(actualDeclaration!.viaModule).toBe(null); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should return the declaration of an externally defined identifier', () => { |           it('should return the declaration of an externally defined identifier', () => { | ||||||
| @ -411,8 +411,8 @@ runInEachFileSystem(() => { | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/some_directive.js'), 'SomeDirective', |                 bundle.program, _('/some_directive.js'), 'SomeDirective', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const classDecorators = host.getDecoratorsOfDeclaration(classNode) !; |             const classDecorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
|             const decoratorNode = classDecorators[0].node !; |             const decoratorNode = classDecorators[0].node!; | ||||||
|             const identifierOfDirective = |             const identifierOfDirective = | ||||||
|                 ts.isCallExpression(decoratorNode) && ts.isIdentifier(decoratorNode.expression) ? |                 ts.isCallExpression(decoratorNode) && ts.isIdentifier(decoratorNode.expression) ? | ||||||
|                 decoratorNode.expression : |                 decoratorNode.expression : | ||||||
| @ -421,10 +421,10 @@ runInEachFileSystem(() => { | |||||||
|             const expectedDeclarationNode = getDeclaration( |             const expectedDeclarationNode = getDeclaration( | ||||||
|                 bundle.program, _('/node_modules/@angular/core/index.d.ts'), 'Directive', |                 bundle.program, _('/node_modules/@angular/core/index.d.ts'), 'Directive', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective !); |             const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective!); | ||||||
|             expect(actualDeclaration).not.toBe(null); |             expect(actualDeclaration).not.toBe(null); | ||||||
|             expect(actualDeclaration !.node).toBe(expectedDeclarationNode); |             expect(actualDeclaration!.node).toBe(expectedDeclarationNode); | ||||||
|             expect(actualDeclaration !.viaModule).toBe('@angular/core'); |             expect(actualDeclaration!.viaModule).toBe('@angular/core'); | ||||||
|           }); |           }); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -435,13 +435,13 @@ runInEachFileSystem(() => { | |||||||
|             const ngModuleRef = findVariableDeclaration( |             const ngModuleRef = findVariableDeclaration( | ||||||
|                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1'); |                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1'); | ||||||
| 
 | 
 | ||||||
|             const value = host.getVariableValue(ngModuleRef !); |             const value = host.getVariableValue(ngModuleRef!); | ||||||
|             expect(value).not.toBe(null); |             expect(value).not.toBe(null); | ||||||
|             if (!value || !ts.isClassExpression(value)) { |             if (!value || !ts.isClassExpression(value)) { | ||||||
|               throw new Error( |               throw new Error( | ||||||
|                   `Expected value to be a class expression: ${value && value.getText()}.`); |                   `Expected value to be a class expression: ${value && value.getText()}.`); | ||||||
|             } |             } | ||||||
|             expect(value.name !.text).toBe('HttpClientXsrfModule'); |             expect(value.name!.text).toBe('HttpClientXsrfModule'); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should return null if the variable has no assignment', () => { |           it('should return null if the variable has no assignment', () => { | ||||||
| @ -449,7 +449,7 @@ runInEachFileSystem(() => { | |||||||
|             const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); |             const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); | ||||||
|             const missingValue = findVariableDeclaration( |             const missingValue = findVariableDeclaration( | ||||||
|                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'missingValue'); |                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'missingValue'); | ||||||
|             const value = host.getVariableValue(missingValue !); |             const value = host.getVariableValue(missingValue!); | ||||||
|             expect(value).toBe(null); |             expect(value).toBe(null); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
| @ -458,7 +458,7 @@ runInEachFileSystem(() => { | |||||||
|             const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); |             const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); | ||||||
|             const nonDecoratedVar = findVariableDeclaration( |             const nonDecoratedVar = findVariableDeclaration( | ||||||
|                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'nonDecoratedVar'); |                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'nonDecoratedVar'); | ||||||
|             const value = host.getVariableValue(nonDecoratedVar !); |             const value = host.getVariableValue(nonDecoratedVar!); | ||||||
|             expect(value).toBe(null); |             expect(value).toBe(null); | ||||||
|           }); |           }); | ||||||
|         }); |         }); | ||||||
| @ -468,7 +468,7 @@ runInEachFileSystem(() => { | |||||||
|             const bundle = makeTestBundleProgram(_('/ngmodule.js')); |             const bundle = makeTestBundleProgram(_('/ngmodule.js')); | ||||||
|             const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); |             const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); | ||||||
|             const classSymbol = |             const classSymbol = | ||||||
|                 host.findClassSymbols(bundle.program.getSourceFile(_('/ngmodule.js')) !)[0]; |                 host.findClassSymbols(bundle.program.getSourceFile(_('/ngmodule.js'))!)[0]; | ||||||
|             const endOfClass = host.getEndOfClass(classSymbol); |             const endOfClass = host.getEndOfClass(classSymbol); | ||||||
|             expect(endOfClass.getText()) |             expect(endOfClass.getText()) | ||||||
|                 .toMatch( |                 .toMatch( | ||||||
| @ -479,7 +479,7 @@ runInEachFileSystem(() => { | |||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     function findVariableDeclaration( |     function findVariableDeclaration( | ||||||
|         node: ts.Node | undefined, variableName: string): ts.VariableDeclaration|undefined { |         node: ts.Node|undefined, variableName: string): ts.VariableDeclaration|undefined { | ||||||
|       if (!node) { |       if (!node) { | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ | |||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| 
 | 
 | ||||||
| import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {ClassMemberKind, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; | import {ClassMemberKind, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; | ||||||
| import {getDeclaration} from '../../../src/ngtsc/testing'; | import {getDeclaration} from '../../../src/ngtsc/testing'; | ||||||
| import {loadFakeCore, loadTestFiles, loadTsLib} from '../../../test/helpers'; | import {loadFakeCore, loadTestFiles, loadTsLib} from '../../../test/helpers'; | ||||||
| @ -227,19 +227,18 @@ export { AliasedDirective$1 }; | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/some_directive.js'), 'SomeDirective', |                 bundle.program, _('/some_directive.js'), 'SomeDirective', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const decorators = host.getDecoratorsOfDeclaration(classNode) !; |             const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|             expect(decorators).toBeDefined(); |             expect(decorators).toBeDefined(); | ||||||
|             expect(decorators.length).toEqual(1); |             expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|             const decorator = decorators[0]; |             const decorator = decorators[0]; | ||||||
|             expect(decorator.name).toEqual('Directive'); |             expect(decorator.name).toEqual('Directive'); | ||||||
|             expect(decorator.identifier !.getText()).toEqual('Directive'); |             expect(decorator.identifier!.getText()).toEqual('Directive'); | ||||||
|             expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); |             expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); | ||||||
|             expect(decorator.args !.map(arg => arg.getText())).toEqual([ |             expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|               '{ selector: \'[someDirective]\' }', |               '{ selector: \'[someDirective]\' }', | ||||||
|             ]); |             ]); | ||||||
| 
 |  | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should find the decorators on a minified class', () => { |           it('should find the decorators on a minified class', () => { | ||||||
| @ -248,19 +247,18 @@ export { AliasedDirective$1 }; | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/some_minified_directive.js'), 'SomeDirective', |                 bundle.program, _('/some_minified_directive.js'), 'SomeDirective', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const decorators = host.getDecoratorsOfDeclaration(classNode) !; |             const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|             expect(decorators).toBeDefined(); |             expect(decorators).toBeDefined(); | ||||||
|             expect(decorators.length).toEqual(1); |             expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|             const decorator = decorators[0]; |             const decorator = decorators[0]; | ||||||
|             expect(decorator.name).toEqual('Directive'); |             expect(decorator.name).toEqual('Directive'); | ||||||
|             expect(decorator.identifier !.getText()).toEqual('Directive'); |             expect(decorator.identifier!.getText()).toEqual('Directive'); | ||||||
|             expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); |             expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); | ||||||
|             expect(decorator.args !.map(arg => arg.getText())).toEqual([ |             expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|               '{ selector: \'[someDirective]\' }', |               '{ selector: \'[someDirective]\' }', | ||||||
|             ]); |             ]); | ||||||
| 
 |  | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should find the decorators on an aliased class', () => { |           it('should find the decorators on an aliased class', () => { | ||||||
| @ -269,16 +267,16 @@ export { AliasedDirective$1 }; | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/some_aliased_directive.js'), 'AliasedDirective$1', |                 bundle.program, _('/some_aliased_directive.js'), 'AliasedDirective$1', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const decorators = host.getDecoratorsOfDeclaration(classNode) !; |             const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|             expect(decorators).toBeDefined(); |             expect(decorators).toBeDefined(); | ||||||
|             expect(decorators.length).toEqual(1); |             expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|             const decorator = decorators[0]; |             const decorator = decorators[0]; | ||||||
|             expect(decorator.name).toEqual('Directive'); |             expect(decorator.name).toEqual('Directive'); | ||||||
|             expect(decorator.identifier !.getText()).toEqual('Directive'); |             expect(decorator.identifier!.getText()).toEqual('Directive'); | ||||||
|             expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); |             expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); | ||||||
|             expect(decorator.args !.map(arg => arg.getText())).toEqual([ |             expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|               '{ selector: \'[someDirective]\' }', |               '{ selector: \'[someDirective]\' }', | ||||||
|             ]); |             ]); | ||||||
|           }); |           }); | ||||||
| @ -290,16 +288,16 @@ export { AliasedDirective$1 }; | |||||||
|                const classNode = getDeclaration( |                const classNode = getDeclaration( | ||||||
|                    bundle.program, _('/some_directive_ctor_parameters.js'), 'SomeDirective', |                    bundle.program, _('/some_directive_ctor_parameters.js'), 'SomeDirective', | ||||||
|                    isNamedVariableDeclaration); |                    isNamedVariableDeclaration); | ||||||
|                const decorators = host.getDecoratorsOfDeclaration(classNode) !; |                const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|                expect(decorators).toBeDefined(); |                expect(decorators).toBeDefined(); | ||||||
|                expect(decorators.length).toEqual(1); |                expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|                const decorator = decorators[0]; |                const decorator = decorators[0]; | ||||||
|                expect(decorator.name).toEqual('Directive'); |                expect(decorator.name).toEqual('Directive'); | ||||||
|                expect(decorator.identifier !.getText()).toEqual('Directive'); |                expect(decorator.identifier!.getText()).toEqual('Directive'); | ||||||
|                expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); |                expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); | ||||||
|                expect(decorator.args !.map(arg => arg.getText())).toEqual([ |                expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|                  '{ selector: \'[someDirective]\' }', |                  '{ selector: \'[someDirective]\' }', | ||||||
|                ]); |                ]); | ||||||
|              }); |              }); | ||||||
| @ -311,16 +309,16 @@ export { AliasedDirective$1 }; | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/node_modules/@angular/core/some_directive.js'), 'SomeDirective', |                 bundle.program, _('/node_modules/@angular/core/some_directive.js'), 'SomeDirective', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const decorators = host.getDecoratorsOfDeclaration(classNode) !; |             const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|             expect(decorators).toBeDefined(); |             expect(decorators).toBeDefined(); | ||||||
|             expect(decorators.length).toEqual(1); |             expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|             const decorator = decorators[0]; |             const decorator = decorators[0]; | ||||||
|             expect(decorator.name).toEqual('Directive'); |             expect(decorator.name).toEqual('Directive'); | ||||||
|             expect(decorator.identifier !.getText()).toEqual('Directive'); |             expect(decorator.identifier!.getText()).toEqual('Directive'); | ||||||
|             expect(decorator.import).toEqual({name: 'Directive', from: './directives'}); |             expect(decorator.import).toEqual({name: 'Directive', from: './directives'}); | ||||||
|             expect(decorator.args !.map(arg => arg.getText())).toEqual([ |             expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|               '{ selector: \'[someDirective]\' }', |               '{ selector: \'[someDirective]\' }', | ||||||
|             ]); |             ]); | ||||||
|           }); |           }); | ||||||
| @ -333,13 +331,12 @@ export { AliasedDirective$1 }; | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/some_minified_directive.js'), 'SomeDirective', |                 bundle.program, _('/some_minified_directive.js'), 'SomeDirective', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const innerNode = |             const innerNode = getIifeBody(classNode)!.statements.find(isNamedFunctionDeclaration)!; | ||||||
|                 getIifeBody(classNode) !.statements.find(isNamedFunctionDeclaration) !; |  | ||||||
|             const classSymbol = host.getClassSymbol(classNode); |             const classSymbol = host.getClassSymbol(classNode); | ||||||
| 
 | 
 | ||||||
|             expect(classSymbol).toBeDefined(); |             expect(classSymbol).toBeDefined(); | ||||||
|             expect(classSymbol !.declaration.valueDeclaration).toBe(classNode); |             expect(classSymbol!.declaration.valueDeclaration).toBe(classNode); | ||||||
|             expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); |             expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); | ||||||
|           }); |           }); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -352,15 +349,15 @@ export { AliasedDirective$1 }; | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const members = host.getMembersOfClass(classNode); |             const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|             const input1 = members.find(member => member.name === 'input1') !; |             const input1 = members.find(member => member.name === 'input1')!; | ||||||
|             expect(input1.kind).toEqual(ClassMemberKind.Property); |             expect(input1.kind).toEqual(ClassMemberKind.Property); | ||||||
|             expect(input1.isStatic).toEqual(false); |             expect(input1.isStatic).toEqual(false); | ||||||
|             expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); |             expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); | ||||||
| 
 | 
 | ||||||
|             const input2 = members.find(member => member.name === 'input2') !; |             const input2 = members.find(member => member.name === 'input2')!; | ||||||
|             expect(input2.kind).toEqual(ClassMemberKind.Property); |             expect(input2.kind).toEqual(ClassMemberKind.Property); | ||||||
|             expect(input2.isStatic).toEqual(false); |             expect(input2.isStatic).toEqual(false); | ||||||
|             expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); |             expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should find decorated members on a class when mixing `ctorParameters` and `__decorate`', |           it('should find decorated members on a class when mixing `ctorParameters` and `__decorate`', | ||||||
| @ -372,10 +369,10 @@ export { AliasedDirective$1 }; | |||||||
|                    isNamedVariableDeclaration); |                    isNamedVariableDeclaration); | ||||||
|                const members = host.getMembersOfClass(classNode); |                const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|                const input1 = members.find(member => member.name === 'input1') !; |                const input1 = members.find(member => member.name === 'input1')!; | ||||||
|                expect(input1.kind).toEqual(ClassMemberKind.Property); |                expect(input1.kind).toEqual(ClassMemberKind.Property); | ||||||
|                expect(input1.isStatic).toEqual(false); |                expect(input1.isStatic).toEqual(false); | ||||||
|                expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); |                expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); | ||||||
|              }); |              }); | ||||||
| 
 | 
 | ||||||
|           it('should find non decorated properties on a class', () => { |           it('should find non decorated properties on a class', () => { | ||||||
| @ -386,11 +383,11 @@ export { AliasedDirective$1 }; | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const members = host.getMembersOfClass(classNode); |             const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|             const instanceProperty = members.find(member => member.name === 'instanceProperty') !; |             const instanceProperty = members.find(member => member.name === 'instanceProperty')!; | ||||||
|             expect(instanceProperty.kind).toEqual(ClassMemberKind.Property); |             expect(instanceProperty.kind).toEqual(ClassMemberKind.Property); | ||||||
|             expect(instanceProperty.isStatic).toEqual(false); |             expect(instanceProperty.isStatic).toEqual(false); | ||||||
|             expect(ts.isBinaryExpression(instanceProperty.implementation !)).toEqual(true); |             expect(ts.isBinaryExpression(instanceProperty.implementation!)).toEqual(true); | ||||||
|             expect(instanceProperty.value !.getText()).toEqual(`'instance'`); |             expect(instanceProperty.value!.getText()).toEqual(`'instance'`); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should find static methods on a class', () => { |           it('should find static methods on a class', () => { | ||||||
| @ -401,10 +398,10 @@ export { AliasedDirective$1 }; | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const members = host.getMembersOfClass(classNode); |             const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|             const staticMethod = members.find(member => member.name === 'staticMethod') !; |             const staticMethod = members.find(member => member.name === 'staticMethod')!; | ||||||
|             expect(staticMethod.kind).toEqual(ClassMemberKind.Method); |             expect(staticMethod.kind).toEqual(ClassMemberKind.Method); | ||||||
|             expect(staticMethod.isStatic).toEqual(true); |             expect(staticMethod.isStatic).toEqual(true); | ||||||
|             expect(ts.isFunctionExpression(staticMethod.implementation !)).toEqual(true); |             expect(ts.isFunctionExpression(staticMethod.implementation!)).toEqual(true); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should find static properties on a class', () => { |           it('should find static properties on a class', () => { | ||||||
| @ -415,11 +412,11 @@ export { AliasedDirective$1 }; | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const members = host.getMembersOfClass(classNode); |             const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|             const staticProperty = members.find(member => member.name === 'staticProperty') !; |             const staticProperty = members.find(member => member.name === 'staticProperty')!; | ||||||
|             expect(staticProperty.kind).toEqual(ClassMemberKind.Property); |             expect(staticProperty.kind).toEqual(ClassMemberKind.Property); | ||||||
|             expect(staticProperty.isStatic).toEqual(true); |             expect(staticProperty.isStatic).toEqual(true); | ||||||
|             expect(ts.isPropertyAccessExpression(staticProperty.implementation !)).toEqual(true); |             expect(ts.isPropertyAccessExpression(staticProperty.implementation!)).toEqual(true); | ||||||
|             expect(staticProperty.value !.getText()).toEqual(`'static'`); |             expect(staticProperty.value!.getText()).toEqual(`'static'`); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should support decorators being used inside @angular/core', () => { |           it('should support decorators being used inside @angular/core', () => { | ||||||
| @ -431,10 +428,10 @@ export { AliasedDirective$1 }; | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const members = host.getMembersOfClass(classNode); |             const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|             const input1 = members.find(member => member.name === 'input1') !; |             const input1 = members.find(member => member.name === 'input1')!; | ||||||
|             expect(input1.kind).toEqual(ClassMemberKind.Property); |             expect(input1.kind).toEqual(ClassMemberKind.Property); | ||||||
|             expect(input1.isStatic).toEqual(false); |             expect(input1.isStatic).toEqual(false); | ||||||
|             expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); |             expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); | ||||||
|           }); |           }); | ||||||
|         }); |         }); | ||||||
|         describe('getConstructorParameters', () => { |         describe('getConstructorParameters', () => { | ||||||
| @ -447,10 +444,10 @@ export { AliasedDirective$1 }; | |||||||
|             const parameters = host.getConstructorParameters(classNode); |             const parameters = host.getConstructorParameters(classNode); | ||||||
| 
 | 
 | ||||||
|             expect(parameters).toBeDefined(); |             expect(parameters).toBeDefined(); | ||||||
|             expect(parameters !.map(parameter => parameter.name)).toEqual([ |             expect(parameters!.map(parameter => parameter.name)).toEqual([ | ||||||
|               '_viewContainer', '_template', 'injected' |               '_viewContainer', '_template', 'injected' | ||||||
|             ]); |             ]); | ||||||
|             expectTypeValueReferencesForParameters(parameters !, [ |             expectTypeValueReferencesForParameters(parameters!, [ | ||||||
|               'ViewContainerRef', |               'ViewContainerRef', | ||||||
|               'TemplateRef', |               'TemplateRef', | ||||||
|               'String', |               'String', | ||||||
| @ -467,10 +464,10 @@ export { AliasedDirective$1 }; | |||||||
|                const parameters = host.getConstructorParameters(classNode); |                const parameters = host.getConstructorParameters(classNode); | ||||||
| 
 | 
 | ||||||
|                expect(parameters).toBeDefined(); |                expect(parameters).toBeDefined(); | ||||||
|                expect(parameters !.map(parameter => parameter.name)).toEqual([ |                expect(parameters!.map(parameter => parameter.name)).toEqual([ | ||||||
|                  '_viewContainer', '_template', 'injected' |                  '_viewContainer', '_template', 'injected' | ||||||
|                ]); |                ]); | ||||||
|                expectTypeValueReferencesForParameters(parameters !, [ |                expectTypeValueReferencesForParameters(parameters!, [ | ||||||
|                  'ViewContainerRef', |                  'ViewContainerRef', | ||||||
|                  'TemplateRef', |                  'TemplateRef', | ||||||
|                  null, |                  null, | ||||||
| @ -485,7 +482,7 @@ export { AliasedDirective$1 }; | |||||||
|                   bundle.program, _('/some_directive.js'), 'SomeDirective', |                   bundle.program, _('/some_directive.js'), 'SomeDirective', | ||||||
|                   isNamedVariableDeclaration); |                   isNamedVariableDeclaration); | ||||||
|               const parameters = host.getConstructorParameters(classNode); |               const parameters = host.getConstructorParameters(classNode); | ||||||
|               const decorators = parameters ![2].decorators !; |               const decorators = parameters![2].decorators!; | ||||||
| 
 | 
 | ||||||
|               expect(decorators.length).toEqual(1); |               expect(decorators.length).toEqual(1); | ||||||
|               expect(decorators[0].import).toEqual({name: 'Inject', from: '@angular/core'}); |               expect(decorators[0].import).toEqual({name: 'Inject', from: '@angular/core'}); | ||||||
| @ -522,7 +519,7 @@ export { AliasedDirective$1 }; | |||||||
|             const ngModuleDecorators = ngModuleClasses.map(s => host.getDecoratorsOfSymbol(s)); |             const ngModuleDecorators = ngModuleClasses.map(s => host.getDecoratorsOfSymbol(s)); | ||||||
| 
 | 
 | ||||||
|             expect(ngModuleClasses.length).toEqual(1); |             expect(ngModuleClasses.length).toEqual(1); | ||||||
|             expect(ngModuleDecorators[0] !.map(d => d.name)).toEqual(['NgModule']); |             expect(ngModuleDecorators[0]!.map(d => d.name)).toEqual(['NgModule']); | ||||||
| 
 | 
 | ||||||
|             const someDirectiveFile = getSourceFileOrError(bundle.program, _('/some_directive.js')); |             const someDirectiveFile = getSourceFileOrError(bundle.program, _('/some_directive.js')); | ||||||
|             const someDirectiveClasses = host.findClassSymbols(someDirectiveFile); |             const someDirectiveClasses = host.findClassSymbols(someDirectiveFile); | ||||||
| @ -532,7 +529,7 @@ export { AliasedDirective$1 }; | |||||||
|             expect(someDirectiveDecorators.length).toEqual(3); |             expect(someDirectiveDecorators.length).toEqual(3); | ||||||
|             expect(someDirectiveDecorators[0]).toBe(null); |             expect(someDirectiveDecorators[0]).toBe(null); | ||||||
|             expect(someDirectiveDecorators[1]).toBe(null); |             expect(someDirectiveDecorators[1]).toBe(null); | ||||||
|             expect(someDirectiveDecorators[2] !.map(d => d.name)).toEqual(['Directive']); |             expect(someDirectiveDecorators[2]!.map(d => d.name)).toEqual(['Directive']); | ||||||
|           }); |           }); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -543,8 +540,8 @@ export { AliasedDirective$1 }; | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/some_directive.js'), 'SomeDirective', |                 bundle.program, _('/some_directive.js'), 'SomeDirective', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const ctrDecorators = host.getConstructorParameters(classNode) !; |             const ctrDecorators = host.getConstructorParameters(classNode)!; | ||||||
|             const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference !as{ |             const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference! as { | ||||||
|                                                    local: true, |                                                    local: true, | ||||||
|                                                    expression: ts.Identifier, |                                                    expression: ts.Identifier, | ||||||
|                                                    defaultImportStatement: null, |                                                    defaultImportStatement: null, | ||||||
| @ -555,8 +552,8 @@ export { AliasedDirective$1 }; | |||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef); |             const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef); | ||||||
|             expect(actualDeclaration).not.toBe(null); |             expect(actualDeclaration).not.toBe(null); | ||||||
|             expect(actualDeclaration !.node).toBe(expectedDeclarationNode); |             expect(actualDeclaration!.node).toBe(expectedDeclarationNode); | ||||||
|             expect(actualDeclaration !.viaModule).toBe(null); |             expect(actualDeclaration!.viaModule).toBe(null); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should return the declaration of an externally defined identifier', () => { |           it('should return the declaration of an externally defined identifier', () => { | ||||||
| @ -565,8 +562,8 @@ export { AliasedDirective$1 }; | |||||||
|             const classNode = getDeclaration( |             const classNode = getDeclaration( | ||||||
|                 bundle.program, _('/some_directive.js'), 'SomeDirective', |                 bundle.program, _('/some_directive.js'), 'SomeDirective', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const classDecorators = host.getDecoratorsOfDeclaration(classNode) !; |             const classDecorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
|             const decoratorNode = classDecorators[0].node !; |             const decoratorNode = classDecorators[0].node!; | ||||||
| 
 | 
 | ||||||
|             const identifierOfDirective = |             const identifierOfDirective = | ||||||
|                 ts.isCallExpression(decoratorNode) && ts.isIdentifier(decoratorNode.expression) ? |                 ts.isCallExpression(decoratorNode) && ts.isIdentifier(decoratorNode.expression) ? | ||||||
| @ -576,10 +573,10 @@ export { AliasedDirective$1 }; | |||||||
|             const expectedDeclarationNode = getDeclaration( |             const expectedDeclarationNode = getDeclaration( | ||||||
|                 bundle.program, _('/node_modules/@angular/core/index.d.ts'), 'Directive', |                 bundle.program, _('/node_modules/@angular/core/index.d.ts'), 'Directive', | ||||||
|                 isNamedVariableDeclaration); |                 isNamedVariableDeclaration); | ||||||
|             const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective !); |             const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective!); | ||||||
|             expect(actualDeclaration).not.toBe(null); |             expect(actualDeclaration).not.toBe(null); | ||||||
|             expect(actualDeclaration !.node).toBe(expectedDeclarationNode); |             expect(actualDeclaration!.node).toBe(expectedDeclarationNode); | ||||||
|             expect(actualDeclaration !.viaModule).toBe('@angular/core'); |             expect(actualDeclaration!.viaModule).toBe('@angular/core'); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|           it('should find the "actual" declaration of an aliased variable identifier', () => { |           it('should find the "actual" declaration of an aliased variable identifier', () => { | ||||||
| @ -589,9 +586,9 @@ export { AliasedDirective$1 }; | |||||||
|                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1', |                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1', | ||||||
|                 isNgModulePropertyAssignment); |                 isNgModulePropertyAssignment); | ||||||
| 
 | 
 | ||||||
|             const declaration = host.getDeclarationOfIdentifier(ngModuleRef !); |             const declaration = host.getDeclarationOfIdentifier(ngModuleRef!); | ||||||
|             expect(declaration).not.toBe(null); |             expect(declaration).not.toBe(null); | ||||||
|             expect(declaration !.node !.getText()).toContain('function HttpClientXsrfModule()'); |             expect(declaration!.node!.getText()).toContain('function HttpClientXsrfModule()'); | ||||||
|           }); |           }); | ||||||
|         }); |         }); | ||||||
|         describe('getVariableValue', () => { |         describe('getVariableValue', () => { | ||||||
| @ -601,7 +598,7 @@ export { AliasedDirective$1 }; | |||||||
|             const ngModuleRef = findVariableDeclaration( |             const ngModuleRef = findVariableDeclaration( | ||||||
|                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1'); |                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1'); | ||||||
| 
 | 
 | ||||||
|             const value = host.getVariableValue(ngModuleRef !); |             const value = host.getVariableValue(ngModuleRef!); | ||||||
|             expect(value).not.toBe(null); |             expect(value).not.toBe(null); | ||||||
|             if (!value || !ts.isFunctionDeclaration(value.parent)) { |             if (!value || !ts.isFunctionDeclaration(value.parent)) { | ||||||
|               throw new Error( |               throw new Error( | ||||||
| @ -615,7 +612,7 @@ export { AliasedDirective$1 }; | |||||||
|             const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); |             const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); | ||||||
|             const missingValue = findVariableDeclaration( |             const missingValue = findVariableDeclaration( | ||||||
|                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'missingValue'); |                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'missingValue'); | ||||||
|             const value = host.getVariableValue(missingValue !); |             const value = host.getVariableValue(missingValue!); | ||||||
|             expect(value).toBe(null); |             expect(value).toBe(null); | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
| @ -624,7 +621,7 @@ export { AliasedDirective$1 }; | |||||||
|             const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); |             const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); | ||||||
|             const nonDecoratedVar = findVariableDeclaration( |             const nonDecoratedVar = findVariableDeclaration( | ||||||
|                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'nonDecoratedVar'); |                 getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'nonDecoratedVar'); | ||||||
|             const value = host.getVariableValue(nonDecoratedVar !); |             const value = host.getVariableValue(nonDecoratedVar!); | ||||||
|             expect(value).toBe(null); |             expect(value).toBe(null); | ||||||
|           }); |           }); | ||||||
|         }); |         }); | ||||||
| @ -634,7 +631,7 @@ export { AliasedDirective$1 }; | |||||||
|             const bundle = makeTestBundleProgram(_('/ngmodule.js')); |             const bundle = makeTestBundleProgram(_('/ngmodule.js')); | ||||||
|             const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); |             const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); | ||||||
|             const classSymbol = |             const classSymbol = | ||||||
|                 host.findClassSymbols(bundle.program.getSourceFile(_('/ngmodule.js')) !)[0]; |                 host.findClassSymbols(bundle.program.getSourceFile(_('/ngmodule.js'))!)[0]; | ||||||
|             const endOfClass = host.getEndOfClass(classSymbol); |             const endOfClass = host.getEndOfClass(classSymbol); | ||||||
|             expect(endOfClass.getText()) |             expect(endOfClass.getText()) | ||||||
|                 .toMatch( |                 .toMatch( | ||||||
| @ -644,7 +641,7 @@ export { AliasedDirective$1 }; | |||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       function findVariableDeclaration( |       function findVariableDeclaration( | ||||||
|           node: ts.Node | undefined, variableName: string): ts.VariableDeclaration|undefined { |           node: ts.Node|undefined, variableName: string): ts.VariableDeclaration|undefined { | ||||||
|         if (!node) { |         if (!node) { | ||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
| @ -656,7 +653,7 @@ export { AliasedDirective$1 }; | |||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     function findIdentifier( |     function findIdentifier( | ||||||
|         node: ts.Node | undefined, identifierName: string, |         node: ts.Node|undefined, identifierName: string, | ||||||
|         requireFn: (node: ts.Identifier) => boolean): ts.Identifier|undefined { |         requireFn: (node: ts.Identifier) => boolean): ts.Identifier|undefined { | ||||||
|       if (!node) { |       if (!node) { | ||||||
|         return undefined; |         return undefined; | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| import {absoluteFrom} from '../../../src/ngtsc/file_system'; | import {absoluteFrom} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {ClassMemberKind, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; | import {ClassMemberKind, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; | ||||||
| import {getDeclaration} from '../../../src/ngtsc/testing'; | import {getDeclaration} from '../../../src/ngtsc/testing'; | ||||||
| import {loadTestFiles} from '../../../test/helpers'; | import {loadTestFiles} from '../../../test/helpers'; | ||||||
| @ -81,16 +81,16 @@ runInEachFileSystem(() => { | |||||||
|         const host = new UmdReflectionHost(new MockLogger(), false, bundle); |         const host = new UmdReflectionHost(new MockLogger(), false, bundle); | ||||||
|         const classNode = getDeclaration( |         const classNode = getDeclaration( | ||||||
|             bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); |             bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); | ||||||
|         const decorators = host.getDecoratorsOfDeclaration(classNode) !; |         const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|         expect(decorators).toBeDefined(); |         expect(decorators).toBeDefined(); | ||||||
|         expect(decorators.length).toEqual(1); |         expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|         const decorator = decorators[0]; |         const decorator = decorators[0]; | ||||||
|         expect(decorator.name).toEqual('Directive'); |         expect(decorator.name).toEqual('Directive'); | ||||||
|         expect(decorator.identifier !.getText()).toEqual('core.Directive'); |         expect(decorator.identifier!.getText()).toEqual('core.Directive'); | ||||||
|         expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); |         expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); | ||||||
|         expect(decorator.args !.map(arg => arg.getText())).toEqual([ |         expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|           '{ selector: \'[someDirective]\' }', |           '{ selector: \'[someDirective]\' }', | ||||||
|         ]); |         ]); | ||||||
|       }); |       }); | ||||||
| @ -102,16 +102,16 @@ runInEachFileSystem(() => { | |||||||
|         const classNode = getDeclaration( |         const classNode = getDeclaration( | ||||||
|             bundle.program, SOME_DIRECTIVE_FILE.name, 'AliasedDirective$1', |             bundle.program, SOME_DIRECTIVE_FILE.name, 'AliasedDirective$1', | ||||||
|             isNamedVariableDeclaration); |             isNamedVariableDeclaration); | ||||||
|         const decorators = host.getDecoratorsOfDeclaration(classNode) !; |         const decorators = host.getDecoratorsOfDeclaration(classNode)!; | ||||||
| 
 | 
 | ||||||
|         expect(decorators).toBeDefined(); |         expect(decorators).toBeDefined(); | ||||||
|         expect(decorators.length).toEqual(1); |         expect(decorators.length).toEqual(1); | ||||||
| 
 | 
 | ||||||
|         const decorator = decorators[0]; |         const decorator = decorators[0]; | ||||||
|         expect(decorator.name).toEqual('Directive'); |         expect(decorator.name).toEqual('Directive'); | ||||||
|         expect(decorator.identifier !.getText()).toEqual('core.Directive'); |         expect(decorator.identifier!.getText()).toEqual('core.Directive'); | ||||||
|         expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); |         expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); | ||||||
|         expect(decorator.args !.map(arg => arg.getText())).toEqual([ |         expect(decorator.args!.map(arg => arg.getText())).toEqual([ | ||||||
|           '{ selector: \'[someDirective]\' }', |           '{ selector: \'[someDirective]\' }', | ||||||
|         ]); |         ]); | ||||||
|       }); |       }); | ||||||
| @ -126,15 +126,15 @@ runInEachFileSystem(() => { | |||||||
|             bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); |             bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); | ||||||
|         const members = host.getMembersOfClass(classNode); |         const members = host.getMembersOfClass(classNode); | ||||||
| 
 | 
 | ||||||
|         const input1 = members.find(member => member.name === 'input1') !; |         const input1 = members.find(member => member.name === 'input1')!; | ||||||
|         expect(input1.kind).toEqual(ClassMemberKind.Property); |         expect(input1.kind).toEqual(ClassMemberKind.Property); | ||||||
|         expect(input1.isStatic).toEqual(false); |         expect(input1.isStatic).toEqual(false); | ||||||
|         expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); |         expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); | ||||||
| 
 | 
 | ||||||
|         const input2 = members.find(member => member.name === 'input2') !; |         const input2 = members.find(member => member.name === 'input2')!; | ||||||
|         expect(input2.kind).toEqual(ClassMemberKind.Property); |         expect(input2.kind).toEqual(ClassMemberKind.Property); | ||||||
|         expect(input2.isStatic).toEqual(false); |         expect(input2.isStatic).toEqual(false); | ||||||
|         expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); |         expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       describe('getConstructorParameters', () => { |       describe('getConstructorParameters', () => { | ||||||
| @ -148,10 +148,10 @@ runInEachFileSystem(() => { | |||||||
|           const parameters = host.getConstructorParameters(classNode); |           const parameters = host.getConstructorParameters(classNode); | ||||||
| 
 | 
 | ||||||
|           expect(parameters).toBeDefined(); |           expect(parameters).toBeDefined(); | ||||||
|           expect(parameters !.map(parameter => parameter.name)).toEqual([ |           expect(parameters!.map(parameter => parameter.name)).toEqual([ | ||||||
|             '_viewContainer', '_template', 'injected' |             '_viewContainer', '_template', 'injected' | ||||||
|           ]); |           ]); | ||||||
|           expectTypeValueReferencesForParameters(parameters !, [ |           expectTypeValueReferencesForParameters(parameters!, [ | ||||||
|             'ViewContainerRef', |             'ViewContainerRef', | ||||||
|             'TemplateRef', |             'TemplateRef', | ||||||
|             null, |             null, | ||||||
|  | |||||||
| @ -14,9 +14,8 @@ import {CtorParameter} from '../../../src/ngtsc/reflection'; | |||||||
|  * names. |  * names. | ||||||
|  */ |  */ | ||||||
| export function expectTypeValueReferencesForParameters( | export function expectTypeValueReferencesForParameters( | ||||||
|     parameters: CtorParameter[], expectedParams: (string | null)[], |     parameters: CtorParameter[], expectedParams: (string|null)[], fromModule: string|null = null) { | ||||||
|     fromModule: string | null = null) { |   parameters!.forEach((param, idx) => { | ||||||
|   parameters !.forEach((param, idx) => { |  | ||||||
|     const expected = expectedParams[idx]; |     const expected = expectedParams[idx]; | ||||||
|     if (expected !== null) { |     if (expected !== null) { | ||||||
|       if (param.typeValueReference === null) { |       if (param.typeValueReference === null) { | ||||||
| @ -32,7 +31,7 @@ export function expectTypeValueReferencesForParameters( | |||||||
|           expect(param.typeValueReference.expression.text).toEqual(expected); |           expect(param.typeValueReference.expression.text).toEqual(expected); | ||||||
|         } |         } | ||||||
|       } else if (param.typeValueReference !== null) { |       } else if (param.typeValueReference !== null) { | ||||||
|         expect(param.typeValueReference.moduleName).toBe(fromModule !); |         expect(param.typeValueReference.moduleName).toBe(fromModule!); | ||||||
|         expect(param.typeValueReference.name).toBe(expected); |         expect(param.typeValueReference.name).toBe(expected); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -8,8 +8,9 @@ | |||||||
| 
 | 
 | ||||||
| /// <reference types="node" />
 | /// <reference types="node" />
 | ||||||
| import * as os from 'os'; | import * as os from 'os'; | ||||||
| import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, join} from '../../../src/ngtsc/file_system'; | 
 | ||||||
| import {Folder, MockFileSystem, TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, join} from '../../../src/ngtsc/file_system'; | ||||||
|  | import {Folder, MockFileSystem, runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {loadStandardTestFiles, loadTestFiles} from '../../../test/helpers'; | import {loadStandardTestFiles, loadTestFiles} from '../../../test/helpers'; | ||||||
| import {getLockFilePath} from '../../src/locking/lock_file'; | import {getLockFilePath} from '../../src/locking/lock_file'; | ||||||
| import {mainNgcc} from '../../src/main'; | import {mainNgcc} from '../../src/main'; | ||||||
| @ -19,6 +20,7 @@ import {EntryPointManifestFile} from '../../src/packages/entry_point_manifest'; | |||||||
| import {Transformer} from '../../src/packages/transformer'; | import {Transformer} from '../../src/packages/transformer'; | ||||||
| import {DirectPackageJsonUpdater, PackageJsonUpdater} from '../../src/writing/package_json_updater'; | import {DirectPackageJsonUpdater, PackageJsonUpdater} from '../../src/writing/package_json_updater'; | ||||||
| import {MockLogger} from '../helpers/mock_logger'; | import {MockLogger} from '../helpers/mock_logger'; | ||||||
|  | 
 | ||||||
| import {compileIntoApf, compileIntoFlatEs5Package} from './util'; | import {compileIntoApf, compileIntoFlatEs5Package} from './util'; | ||||||
| 
 | 
 | ||||||
| const testFiles = loadStandardTestFiles({fakeCore: false, rxjs: true}); | const testFiles = loadStandardTestFiles({fakeCore: false, rxjs: true}); | ||||||
| @ -145,7 +147,8 @@ runInEachFileSystem(() => { | |||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     ['esm5', 'esm2015'].forEach(target => { |     ['esm5', 'esm2015'].forEach(target => { | ||||||
|       it(`should be able to process spread operator inside objects for ${target} format (imported helpers)`, |       it(`should be able to process spread operator inside objects for ${ | ||||||
|  |              target} format (imported helpers)`,
 | ||||||
|          () => { |          () => { | ||||||
|            compileIntoApf( |            compileIntoApf( | ||||||
|                'test-package', { |                'test-package', { | ||||||
| @ -184,7 +187,8 @@ runInEachFileSystem(() => { | |||||||
|            expect(jsContents).toContain('ngcc0.ɵɵclassProp("a", true)("b", true)("c", false)'); |            expect(jsContents).toContain('ngcc0.ɵɵclassProp("a", true)("b", true)("c", false)'); | ||||||
|          }); |          }); | ||||||
| 
 | 
 | ||||||
|       it(`should be able to process emitted spread operator inside objects for ${target} format (emitted helpers)`, |       it(`should be able to process emitted spread operator inside objects for ${ | ||||||
|  |              target} format (emitted helpers)`,
 | ||||||
|          () => { |          () => { | ||||||
|            compileIntoApf( |            compileIntoApf( | ||||||
|                'test-package', { |                'test-package', { | ||||||
| @ -326,7 +330,7 @@ runInEachFileSystem(() => { | |||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       const before = fs.readFile(_(`/node_modules/test-package/index.js`)); |       const before = fs.readFile(_(`/node_modules/test-package/index.js`)); | ||||||
|       const originalProp = /ɵprov[^;]+/.exec(before) ![0]; |       const originalProp = /ɵprov[^;]+/.exec(before)![0]; | ||||||
|       mainNgcc({ |       mainNgcc({ | ||||||
|         basePath: '/node_modules', |         basePath: '/node_modules', | ||||||
|         targetEntryPointPath: 'test-package', |         targetEntryPointPath: 'test-package', | ||||||
| @ -496,7 +500,7 @@ runInEachFileSystem(() => { | |||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     describe('in async mode', () => { |     describe('in async mode', () => { | ||||||
|       it('should run ngcc without errors for fesm2015', async() => { |       it('should run ngcc without errors for fesm2015', async () => { | ||||||
|         const promise = mainNgcc({ |         const promise = mainNgcc({ | ||||||
|           basePath: '/node_modules', |           basePath: '/node_modules', | ||||||
|           propertiesToConsider: ['fesm2015'], |           propertiesToConsider: ['fesm2015'], | ||||||
| @ -507,7 +511,7 @@ runInEachFileSystem(() => { | |||||||
|         await promise; |         await promise; | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should reject, if some of the entry-points are unprocessable', async() => { |       it('should reject, if some of the entry-points are unprocessable', async () => { | ||||||
|         const createEntryPoint = (name: string, prop: EntryPointJsonProperty): TestFile[] => { |         const createEntryPoint = (name: string, prop: EntryPointJsonProperty): TestFile[] => { | ||||||
|           return [ |           return [ | ||||||
|             { |             { | ||||||
| @ -541,7 +545,7 @@ runInEachFileSystem(() => { | |||||||
|                 `  - ${_('/dist/unprocessable-3')}`))); |                 `  - ${_('/dist/unprocessable-3')}`))); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should reject, if an error happens during processing', async() => { |       it('should reject, if an error happens during processing', async () => { | ||||||
|         spyOn(Transformer.prototype, 'transform').and.throwError('Test error.'); |         spyOn(Transformer.prototype, 'transform').and.throwError('Test error.'); | ||||||
| 
 | 
 | ||||||
|         const promise = mainNgcc({ |         const promise = mainNgcc({ | ||||||
| @ -651,7 +655,8 @@ runInEachFileSystem(() => { | |||||||
|           markPropertiesAsProcessed('@angular/common/http/testing', SUPPORTED_FORMAT_PROPERTIES); |           markPropertiesAsProcessed('@angular/common/http/testing', SUPPORTED_FORMAT_PROPERTIES); | ||||||
|           mainNgcc({ |           mainNgcc({ | ||||||
|             basePath: '/node_modules', |             basePath: '/node_modules', | ||||||
|             targetEntryPointPath: '@angular/common/http/testing', logger, |             targetEntryPointPath: '@angular/common/http/testing', | ||||||
|  |             logger, | ||||||
|           }); |           }); | ||||||
|           expect(logger.logs.debug).toContain([ |           expect(logger.logs.debug).toContain([ | ||||||
|             'The target entry-point has already been processed' |             'The target entry-point has already been processed' | ||||||
| @ -665,7 +670,8 @@ runInEachFileSystem(() => { | |||||||
|              mainNgcc({ |              mainNgcc({ | ||||||
|                basePath: '/node_modules', |                basePath: '/node_modules', | ||||||
|                targetEntryPointPath: '@angular/common/http/testing', |                targetEntryPointPath: '@angular/common/http/testing', | ||||||
|                propertiesToConsider: ['fesm2015', 'esm5', 'esm2015'], logger, |                propertiesToConsider: ['fesm2015', 'esm5', 'esm2015'], | ||||||
|  |                logger, | ||||||
|              }); |              }); | ||||||
|              expect(logger.logs.debug).not.toContain([ |              expect(logger.logs.debug).not.toContain([ | ||||||
|                'The target entry-point has already been processed' |                'The target entry-point has already been processed' | ||||||
| @ -682,7 +688,8 @@ runInEachFileSystem(() => { | |||||||
|                basePath: '/node_modules', |                basePath: '/node_modules', | ||||||
|                targetEntryPointPath: '@angular/common/http/testing', |                targetEntryPointPath: '@angular/common/http/testing', | ||||||
|                propertiesToConsider: ['esm5', 'esm2015'], |                propertiesToConsider: ['esm5', 'esm2015'], | ||||||
|                compileAllFormats: false, logger, |                compileAllFormats: false, | ||||||
|  |                logger, | ||||||
|              }); |              }); | ||||||
| 
 | 
 | ||||||
|              expect(logger.logs.debug).not.toContain([ |              expect(logger.logs.debug).not.toContain([ | ||||||
| @ -699,7 +706,8 @@ runInEachFileSystem(() => { | |||||||
|                targetEntryPointPath: '@angular/common/http/testing', |                targetEntryPointPath: '@angular/common/http/testing', | ||||||
|                // Simulate a property that does not exist on the package.json and will be ignored.
 |                // Simulate a property that does not exist on the package.json and will be ignored.
 | ||||||
|                propertiesToConsider: ['missing', 'esm2015', 'esm5'], |                propertiesToConsider: ['missing', 'esm2015', 'esm5'], | ||||||
|                compileAllFormats: false, logger, |                compileAllFormats: false, | ||||||
|  |                logger, | ||||||
|              }); |              }); | ||||||
| 
 | 
 | ||||||
|              expect(logger.logs.debug).toContain([ |              expect(logger.logs.debug).toContain([ | ||||||
| @ -717,7 +725,8 @@ runInEachFileSystem(() => { | |||||||
|              targetEntryPointPath: '@angular/common/http/testing', |              targetEntryPointPath: '@angular/common/http/testing', | ||||||
|              // Simulate a property that does not exist on the package.json and will be ignored.
 |              // Simulate a property that does not exist on the package.json and will be ignored.
 | ||||||
|              propertiesToConsider: ['missing', 'esm2015', 'esm5'], |              propertiesToConsider: ['missing', 'esm2015', 'esm5'], | ||||||
|              compileAllFormats: false, logger, |              compileAllFormats: false, | ||||||
|  |              logger, | ||||||
|            }); |            }); | ||||||
| 
 | 
 | ||||||
|            expect(logger.logs.debug).toContain([ |            expect(logger.logs.debug).toContain([ | ||||||
| @ -752,7 +761,7 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|       // Now hack the files to look like it was processed by an outdated version of ngcc
 |       // Now hack the files to look like it was processed by an outdated version of ngcc
 | ||||||
|       const packageJson = loadPackage('test-package', _('/node_modules')); |       const packageJson = loadPackage('test-package', _('/node_modules')); | ||||||
|       packageJson.__processed_by_ivy_ngcc__ !.typings = '8.0.0'; |       packageJson.__processed_by_ivy_ngcc__!.typings = '8.0.0'; | ||||||
|       packageJson.main_ivy_ngcc = '__ivy_ngcc__/main.js'; |       packageJson.main_ivy_ngcc = '__ivy_ngcc__/main.js'; | ||||||
|       fs.writeFile(_('/node_modules/test-package/package.json'), JSON.stringify(packageJson)); |       fs.writeFile(_('/node_modules/test-package/package.json'), JSON.stringify(packageJson)); | ||||||
|       fs.writeFile(_('/node_modules/test-package/x.js'), 'processed content'); |       fs.writeFile(_('/node_modules/test-package/x.js'), 'processed content'); | ||||||
| @ -838,7 +847,8 @@ runInEachFileSystem(() => { | |||||||
|            // `fesm2015` and `es2015` map to the same file: `./fesm2015/common.js`
 |            // `fesm2015` and `es2015` map to the same file: `./fesm2015/common.js`
 | ||||||
|            mainNgcc({ |            mainNgcc({ | ||||||
|              basePath: '/node_modules/@angular/common', |              basePath: '/node_modules/@angular/common', | ||||||
|              propertiesToConsider: ['fesm2015'], logger, |              propertiesToConsider: ['fesm2015'], | ||||||
|  |              logger, | ||||||
|            }); |            }); | ||||||
| 
 | 
 | ||||||
|            expect(logs).not.toContain(['Skipping @angular/common : es2015 (already compiled).']); |            expect(logs).not.toContain(['Skipping @angular/common : es2015 (already compiled).']); | ||||||
| @ -851,7 +861,8 @@ runInEachFileSystem(() => { | |||||||
|            // Now, compiling `es2015` should be a no-op.
 |            // Now, compiling `es2015` should be a no-op.
 | ||||||
|            mainNgcc({ |            mainNgcc({ | ||||||
|              basePath: '/node_modules/@angular/common', |              basePath: '/node_modules/@angular/common', | ||||||
|              propertiesToConsider: ['es2015'], logger, |              propertiesToConsider: ['es2015'], | ||||||
|  |              logger, | ||||||
|            }); |            }); | ||||||
| 
 | 
 | ||||||
|            expect(logs).toContain(['Skipping @angular/common : es2015 (already compiled).']); |            expect(logs).toContain(['Skipping @angular/common : es2015 (already compiled).']); | ||||||
| @ -997,21 +1008,21 @@ runInEachFileSystem(() => { | |||||||
|            expectNotToHaveProp(pkg, 'esm5_ivy_ngcc'); |            expectNotToHaveProp(pkg, 'esm5_ivy_ngcc'); | ||||||
|            expectToHaveProp(pkg, 'fesm2015_ivy_ngcc'); |            expectToHaveProp(pkg, 'fesm2015_ivy_ngcc'); | ||||||
|            expectNotToHaveProp(pkg, 'fesm5_ivy_ngcc'); |            expectNotToHaveProp(pkg, 'fesm5_ivy_ngcc'); | ||||||
|            expectToHaveProp(pkg.__processed_by_ivy_ngcc__ !, 'fesm2015'); |            expectToHaveProp(pkg.__processed_by_ivy_ngcc__!, 'fesm2015'); | ||||||
| 
 | 
 | ||||||
|            // Process `fesm5` and update `package.json`.
 |            // Process `fesm5` and update `package.json`.
 | ||||||
|            pkg = processFormatAndUpdatePackageJson('fesm5'); |            pkg = processFormatAndUpdatePackageJson('fesm5'); | ||||||
|            expectNotToHaveProp(pkg, 'esm5_ivy_ngcc'); |            expectNotToHaveProp(pkg, 'esm5_ivy_ngcc'); | ||||||
|            expectToHaveProp(pkg, 'fesm2015_ivy_ngcc'); |            expectToHaveProp(pkg, 'fesm2015_ivy_ngcc'); | ||||||
|            expectToHaveProp(pkg, 'fesm5_ivy_ngcc'); |            expectToHaveProp(pkg, 'fesm5_ivy_ngcc'); | ||||||
|            expectToHaveProp(pkg.__processed_by_ivy_ngcc__ !, 'fesm5'); |            expectToHaveProp(pkg.__processed_by_ivy_ngcc__!, 'fesm5'); | ||||||
| 
 | 
 | ||||||
|            // Process `esm5` and update `package.json`.
 |            // Process `esm5` and update `package.json`.
 | ||||||
|            pkg = processFormatAndUpdatePackageJson('esm5'); |            pkg = processFormatAndUpdatePackageJson('esm5'); | ||||||
|            expectToHaveProp(pkg, 'esm5_ivy_ngcc'); |            expectToHaveProp(pkg, 'esm5_ivy_ngcc'); | ||||||
|            expectToHaveProp(pkg, 'fesm2015_ivy_ngcc'); |            expectToHaveProp(pkg, 'fesm2015_ivy_ngcc'); | ||||||
|            expectToHaveProp(pkg, 'fesm5_ivy_ngcc'); |            expectToHaveProp(pkg, 'fesm5_ivy_ngcc'); | ||||||
|            expectToHaveProp(pkg.__processed_by_ivy_ngcc__ !, 'esm5'); |            expectToHaveProp(pkg.__processed_by_ivy_ngcc__!, 'esm5'); | ||||||
| 
 | 
 | ||||||
|            // Ensure the properties are in deterministic order (regardless of processing order).
 |            // Ensure the properties are in deterministic order (regardless of processing order).
 | ||||||
|            const pkgKeys = stringifyKeys(pkg); |            const pkgKeys = stringifyKeys(pkg); | ||||||
| @ -1026,7 +1037,7 @@ runInEachFileSystem(() => { | |||||||
|            // For example:
 |            // For example:
 | ||||||
|            // - `fesm2015` <=> `es2015`
 |            // - `fesm2015` <=> `es2015`
 | ||||||
|            // - `fesm5` <=> `module`
 |            // - `fesm5` <=> `module`
 | ||||||
|            expect(stringifyKeys(pkg.__processed_by_ivy_ngcc__ !)) |            expect(stringifyKeys(pkg.__processed_by_ivy_ngcc__!)) | ||||||
|                .toBe('|es2015|esm5|fesm2015|fesm5|module|typings|'); |                .toBe('|es2015|esm5|fesm2015|fesm5|module|typings|'); | ||||||
| 
 | 
 | ||||||
|            // Helpers
 |            // Helpers
 | ||||||
| @ -1034,7 +1045,8 @@ runInEachFileSystem(() => { | |||||||
|              expect(obj.hasOwnProperty(prop)) |              expect(obj.hasOwnProperty(prop)) | ||||||
|                  .toBe( |                  .toBe( | ||||||
|                      false, |                      false, | ||||||
|                      `Expected object not to have property '${prop}': ${JSON.stringify(obj, null, 2)}`); |                      `Expected object not to have property '${prop}': ${ | ||||||
|  |                          JSON.stringify(obj, null, 2)}`);
 | ||||||
|            } |            } | ||||||
| 
 | 
 | ||||||
|            function expectToHaveProp(obj: object, prop: string) { |            function expectToHaveProp(obj: object, prop: string) { | ||||||
| @ -1053,7 +1065,9 @@ runInEachFileSystem(() => { | |||||||
|              return loadPackage('@angular/core'); |              return loadPackage('@angular/core'); | ||||||
|            } |            } | ||||||
| 
 | 
 | ||||||
|            function stringifyKeys(obj: object) { return `|${Object.keys(obj).join('|')}|`; } |            function stringifyKeys(obj: object) { | ||||||
|  |              return `|${Object.keys(obj).join('|')}|`; | ||||||
|  |            } | ||||||
|          }); |          }); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
| @ -1206,7 +1220,8 @@ runInEachFileSystem(() => { | |||||||
|            mainNgcc({ |            mainNgcc({ | ||||||
|              basePath: '/node_modules', |              basePath: '/node_modules', | ||||||
|              propertiesToConsider: ['es2015'], |              propertiesToConsider: ['es2015'], | ||||||
|              errorOnFailedEntryPoint: false, logger, |              errorOnFailedEntryPoint: false, | ||||||
|  |              logger, | ||||||
|            }); |            }); | ||||||
|            expect(logger.logs.error.length).toEqual(1); |            expect(logger.logs.error.length).toEqual(1); | ||||||
|            const message = logger.logs.error[0][0]; |            const message = logger.logs.error[0][0]; | ||||||
| @ -1236,7 +1251,8 @@ runInEachFileSystem(() => { | |||||||
|         const logger = new MockLogger(); |         const logger = new MockLogger(); | ||||||
|         mainNgcc({ |         mainNgcc({ | ||||||
|           basePath: '/node_modules', |           basePath: '/node_modules', | ||||||
|           propertiesToConsider: ['esm2015'], logger, |           propertiesToConsider: ['esm2015'], | ||||||
|  |           logger, | ||||||
|         }); |         }); | ||||||
|         expect(logger.logs.info).toContain(['Compiling @angular/common/http : esm2015 as esm2015']); |         expect(logger.logs.info).toContain(['Compiling @angular/common/http : esm2015 as esm2015']); | ||||||
|       }); |       }); | ||||||
| @ -1281,7 +1297,8 @@ runInEachFileSystem(() => { | |||||||
|         mainNgcc({ |         mainNgcc({ | ||||||
|           basePath: '/dist', |           basePath: '/dist', | ||||||
|           propertiesToConsider: ['es2015'], |           propertiesToConsider: ['es2015'], | ||||||
|           tsConfigPath: _('/tsconfig.app.json'), logger |           tsConfigPath: _('/tsconfig.app.json'), | ||||||
|  |           logger | ||||||
|         }); |         }); | ||||||
|         expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({ |         expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({ | ||||||
|           es2015: '0.0.0-PLACEHOLDER', |           es2015: '0.0.0-PLACEHOLDER', | ||||||
| @ -1316,7 +1333,8 @@ runInEachFileSystem(() => { | |||||||
|            mainNgcc({ |            mainNgcc({ | ||||||
|              basePath: '/node_modules', |              basePath: '/node_modules', | ||||||
|              propertiesToConsider: ['es2015'], |              propertiesToConsider: ['es2015'], | ||||||
|              pathMappings: {paths: {'*': ['dist/*']}, baseUrl: '/'}, logger |              pathMappings: {paths: {'*': ['dist/*']}, baseUrl: '/'}, | ||||||
|  |              logger | ||||||
|            }); |            }); | ||||||
|            expect(loadPackage('@angular/core').__processed_by_ivy_ngcc__).toEqual({ |            expect(loadPackage('@angular/core').__processed_by_ivy_ngcc__).toEqual({ | ||||||
|              es2015: '0.0.0-PLACEHOLDER', |              es2015: '0.0.0-PLACEHOLDER', | ||||||
| @ -1356,7 +1374,8 @@ runInEachFileSystem(() => { | |||||||
|            mainNgcc({ |            mainNgcc({ | ||||||
|              basePath: '/dist', |              basePath: '/dist', | ||||||
|              propertiesToConsider: ['es2015'], |              propertiesToConsider: ['es2015'], | ||||||
|              tsConfigPath: null, logger, |              tsConfigPath: null, | ||||||
|  |              logger, | ||||||
|            }); |            }); | ||||||
|            expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({ |            expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({ | ||||||
|              es2015: '0.0.0-PLACEHOLDER', |              es2015: '0.0.0-PLACEHOLDER', | ||||||
| @ -1821,7 +1840,7 @@ runInEachFileSystem(() => { | |||||||
|         expect(jsContents).toContain('exports.ɵngExportɵFooModuleɵFoo = ɵngcc1.Foo;'); |         expect(jsContents).toContain('exports.ɵngExportɵFooModuleɵFoo = ɵngcc1.Foo;'); | ||||||
|         expect(dtsContents) |         expect(dtsContents) | ||||||
|             .toContain(`export {Foo as ɵngExportɵFooModuleɵFoo} from './directive';`); |             .toContain(`export {Foo as ɵngExportɵFooModuleɵFoo} from './directive';`); | ||||||
|         expect(dtsContents.match(/ɵngExportɵFooModuleɵFoo/g) !.length).toBe(1); |         expect(dtsContents.match(/ɵngExportɵFooModuleɵFoo/g)!.length).toBe(1); | ||||||
|         expect(dtsContents).not.toContain(`ɵngExportɵFooModuleɵLocalDir`); |         expect(dtsContents).not.toContain(`ɵngExportɵFooModuleɵLocalDir`); | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|  | |||||||
| @ -234,11 +234,21 @@ class MockCompilerHost implements ts.CompilerHost { | |||||||
|     this.fs.writeFile(this.fs.resolve(fileName), data); |     this.fs.writeFile(this.fs.resolve(fileName), data); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   getCurrentDirectory(): string { return this.fs.pwd(); } |   getCurrentDirectory(): string { | ||||||
|   getCanonicalFileName(fileName: string): string { return fileName; } |     return this.fs.pwd(); | ||||||
|   useCaseSensitiveFileNames(): boolean { return true; } |   } | ||||||
|   getNewLine(): string { return '\n'; } |   getCanonicalFileName(fileName: string): string { | ||||||
|   fileExists(fileName: string): boolean { return this.fs.exists(this.fs.resolve(fileName)); } |     return fileName; | ||||||
|  |   } | ||||||
|  |   useCaseSensitiveFileNames(): boolean { | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |   getNewLine(): string { | ||||||
|  |     return '\n'; | ||||||
|  |   } | ||||||
|  |   fileExists(fileName: string): boolean { | ||||||
|  |     return this.fs.exists(this.fs.resolve(fileName)); | ||||||
|  |   } | ||||||
|   readFile(fileName: string): string|undefined { |   readFile(fileName: string): string|undefined { | ||||||
|     const abs = this.fs.resolve(fileName); |     const abs = this.fs.resolve(fileName); | ||||||
|     return this.fs.exists(abs) ? this.fs.readFile(abs) : undefined; |     return this.fs.exists(abs) ? this.fs.readFile(abs) : undefined; | ||||||
|  | |||||||
| @ -14,13 +14,13 @@ import {MockLogger} from '../helpers/mock_logger'; | |||||||
| runInEachFileSystem(() => { | runInEachFileSystem(() => { | ||||||
|   describe('AsyncLocker', () => { |   describe('AsyncLocker', () => { | ||||||
|     describe('lock()', () => { |     describe('lock()', () => { | ||||||
|       it('should guard the `fn()` with calls to `write()` and `remove()`', async() => { |       it('should guard the `fn()` with calls to `write()` and `remove()`', async () => { | ||||||
|         const fs = getFileSystem(); |         const fs = getFileSystem(); | ||||||
|         const log: string[] = []; |         const log: string[] = []; | ||||||
|         const lockFile = new MockLockFile(fs, log); |         const lockFile = new MockLockFile(fs, log); | ||||||
|         const locker = new AsyncLocker(lockFile, new MockLogger(), 100, 10); |         const locker = new AsyncLocker(lockFile, new MockLogger(), 100, 10); | ||||||
| 
 | 
 | ||||||
|         await locker.lock(async() => { |         await locker.lock(async () => { | ||||||
|           log.push('fn() - before'); |           log.push('fn() - before'); | ||||||
|           // This promise forces node to do a tick in this function, ensuring that we are truly
 |           // This promise forces node to do a tick in this function, ensuring that we are truly
 | ||||||
|           // testing an async scenario.
 |           // testing an async scenario.
 | ||||||
| @ -31,7 +31,7 @@ runInEachFileSystem(() => { | |||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should guard the `fn()` with calls to `write()` and `remove()`, even if it throws', |       it('should guard the `fn()` with calls to `write()` and `remove()`, even if it throws', | ||||||
|          async() => { |          async () => { | ||||||
|            let error: string = ''; |            let error: string = ''; | ||||||
|            const fs = getFileSystem(); |            const fs = getFileSystem(); | ||||||
|            const log: string[] = []; |            const log: string[] = []; | ||||||
| @ -39,7 +39,7 @@ runInEachFileSystem(() => { | |||||||
|            const locker = new AsyncLocker(lockFile, new MockLogger(), 100, 10); |            const locker = new AsyncLocker(lockFile, new MockLogger(), 100, 10); | ||||||
| 
 | 
 | ||||||
|            try { |            try { | ||||||
|              await locker.lock(async() => { |              await locker.lock(async () => { | ||||||
|                log.push('fn()'); |                log.push('fn()'); | ||||||
|                throw new Error('ERROR'); |                throw new Error('ERROR'); | ||||||
|              }); |              }); | ||||||
| @ -50,7 +50,7 @@ runInEachFileSystem(() => { | |||||||
|            expect(log).toEqual(['write()', 'fn()', 'remove()']); |            expect(log).toEqual(['write()', 'fn()', 'remove()']); | ||||||
|          }); |          }); | ||||||
| 
 | 
 | ||||||
|       it('should retry if another process is locking', async() => { |       it('should retry if another process is locking', async () => { | ||||||
|         const fs = getFileSystem(); |         const fs = getFileSystem(); | ||||||
|         const log: string[] = []; |         const log: string[] = []; | ||||||
|         const lockFile = new MockLockFile(fs, log); |         const lockFile = new MockLockFile(fs, log); | ||||||
| @ -69,7 +69,7 @@ runInEachFileSystem(() => { | |||||||
|           return lockFileContents; |           return lockFileContents; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         const promise = locker.lock(async() => log.push('fn()')); |         const promise = locker.lock(async () => log.push('fn()')); | ||||||
|         // The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
 |         // The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
 | ||||||
|         expect(log).toEqual(['write()', 'read() => 188']); |         expect(log).toEqual(['write()', 'read() => 188']); | ||||||
|         expect(logger.logs.info).toEqual([[ |         expect(logger.logs.info).toEqual([[ | ||||||
| @ -83,7 +83,7 @@ runInEachFileSystem(() => { | |||||||
|         expect(log).toEqual(['write()', 'read() => 188', 'write()', 'fn()', 'remove()']); |         expect(log).toEqual(['write()', 'read() => 188', 'write()', 'fn()', 'remove()']); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should extend the retry timeout if the other process locking the file changes', async() => { |       it('should extend the retry timeout if the other process locking the file changes', async () => { | ||||||
|         const fs = getFileSystem(); |         const fs = getFileSystem(); | ||||||
|         const log: string[] = []; |         const log: string[] = []; | ||||||
|         const lockFile = new MockLockFile(fs, log); |         const lockFile = new MockLockFile(fs, log); | ||||||
| @ -102,7 +102,7 @@ runInEachFileSystem(() => { | |||||||
|           return lockFileContents; |           return lockFileContents; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         const promise = locker.lock(async() => log.push('fn()')); |         const promise = locker.lock(async () => log.push('fn()')); | ||||||
|         // The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
 |         // The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
 | ||||||
|         expect(log).toEqual(['write()', 'read() => 188']); |         expect(log).toEqual(['write()', 'read() => 188']); | ||||||
|         expect(logger.logs.info).toEqual([[ |         expect(logger.logs.info).toEqual([[ | ||||||
| @ -132,7 +132,7 @@ runInEachFileSystem(() => { | |||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should error if another process does not release the lock-file before this times out', |       it('should error if another process does not release the lock-file before this times out', | ||||||
|          async() => { |          async () => { | ||||||
|            const fs = getFileSystem(); |            const fs = getFileSystem(); | ||||||
|            const log: string[] = []; |            const log: string[] = []; | ||||||
|            const lockFile = new MockLockFile(fs, log); |            const lockFile = new MockLockFile(fs, log); | ||||||
| @ -151,7 +151,7 @@ runInEachFileSystem(() => { | |||||||
|              return lockFileContents; |              return lockFileContents; | ||||||
|            }); |            }); | ||||||
| 
 | 
 | ||||||
|            const promise = locker.lock(async() => log.push('fn()')); |            const promise = locker.lock(async () => log.push('fn()')); | ||||||
| 
 | 
 | ||||||
|            // The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
 |            // The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
 | ||||||
|            expect(log).toEqual(['write()', 'read() => 188']); |            expect(log).toEqual(['write()', 'read() => 188']); | ||||||
| @ -159,10 +159,11 @@ runInEachFileSystem(() => { | |||||||
|            let error: Error; |            let error: Error; | ||||||
|            await promise.catch(e => error = e); |            await promise.catch(e => error = e); | ||||||
|            expect(log).toEqual(['write()', 'read() => 188', 'write()', 'read() => 188']); |            expect(log).toEqual(['write()', 'read() => 188', 'write()', 'read() => 188']); | ||||||
|            expect(error !.message) |            expect(error!.message) | ||||||
|                .toEqual( |                .toEqual( | ||||||
|                    `Timed out waiting 0.2s for another ngcc process, with id 188, to complete.\n` + |                    `Timed out waiting 0.2s for another ngcc process, with id 188, to complete.\n` + | ||||||
|                    `(If you are sure no ngcc process is running then you should delete the lock-file at ${lockFile.path}.)`); |                    `(If you are sure no ngcc process is running then you should delete the lock-file at ${ | ||||||
|  |                        lockFile.path}.)`);
 | ||||||
|          }); |          }); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -23,7 +23,7 @@ runInEachFileSystem(() => { | |||||||
|     class LockFileUnderTest extends LockFileWithChildProcess { |     class LockFileUnderTest extends LockFileWithChildProcess { | ||||||
|       // Note that log is initialized in the `createUnlocker()` function that is called from
 |       // Note that log is initialized in the `createUnlocker()` function that is called from
 | ||||||
|       // super(), so we can't initialize it here.
 |       // super(), so we can't initialize it here.
 | ||||||
|       log !: string[]; |       log!: string[]; | ||||||
|       constructor(fs: FileSystem) { |       constructor(fs: FileSystem) { | ||||||
|         super(fs, new MockLogger()); |         super(fs, new MockLogger()); | ||||||
|         fs.ensureDir(fs.dirname(this.path)); |         fs.ensureDir(fs.dirname(this.path)); | ||||||
| @ -47,7 +47,11 @@ runInEachFileSystem(() => { | |||||||
|         const log = this.log; |         const log = this.log; | ||||||
|         // Normally this would fork a child process and return it.
 |         // Normally this would fork a child process and return it.
 | ||||||
|         // But we don't want to do that in these tests.
 |         // But we don't want to do that in these tests.
 | ||||||
|         return <any>{disconnect() { log.push('unlocker.disconnect()'); }}; |         return <any>{ | ||||||
|  |           disconnect() { | ||||||
|  |             log.push('unlocker.disconnect()'); | ||||||
|  |           } | ||||||
|  |         }; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ | |||||||
|  * Use of this source code is governed by an MIT-style license that can be |  * Use of this source code is governed by an MIT-style license that can be | ||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem} from '../../../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem} from '../../../../src/ngtsc/file_system'; | ||||||
| import {runInEachFileSystem} from '../../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem} from '../../../../src/ngtsc/file_system/testing'; | ||||||
| import {removeLockFile} from '../../../src/locking/lock_file_with_child_process/util'; | import {removeLockFile} from '../../../src/locking/lock_file_with_child_process/util'; | ||||||
| import {MockLogger} from '../../helpers/mock_logger'; | import {MockLogger} from '../../helpers/mock_logger'; | ||||||
| @ -24,8 +24,9 @@ runInEachFileSystem(() => { | |||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     describe('removeLockFile()', () => { |     describe('removeLockFile()', () => { | ||||||
|       it('should do nothing if there is no file to remove', |       it('should do nothing if there is no file to remove', () => { | ||||||
|          () => { removeLockFile(fs, logger, absoluteFrom('/lockfile/path'), '1234'); }); |         removeLockFile(fs, logger, absoluteFrom('/lockfile/path'), '1234'); | ||||||
|  |       }); | ||||||
| 
 | 
 | ||||||
|       it('should do nothing if the pid does not match', () => { |       it('should do nothing if the pid does not match', () => { | ||||||
|         fs.writeFile(lockFilePath, '888'); |         fs.writeFile(lockFilePath, '888'); | ||||||
|  | |||||||
| @ -50,7 +50,9 @@ runInEachFileSystem(() => { | |||||||
|         const lockFile = new MockLockFile(fs, log); |         const lockFile = new MockLockFile(fs, log); | ||||||
|         const locker = new SyncLocker(lockFile); |         const locker = new SyncLocker(lockFile); | ||||||
| 
 | 
 | ||||||
|         spyOn(lockFile, 'write').and.callFake(() => { throw {code: 'EEXIST'}; }); |         spyOn(lockFile, 'write').and.callFake(() => { | ||||||
|  |           throw {code: 'EEXIST'}; | ||||||
|  |         }); | ||||||
|         spyOn(lockFile, 'read').and.returnValue('188'); |         spyOn(lockFile, 'read').and.returnValue('188'); | ||||||
| 
 | 
 | ||||||
|         expect(() => locker.lock(() => {})) |         expect(() => locker.lock(() => {})) | ||||||
| @ -58,7 +60,8 @@ runInEachFileSystem(() => { | |||||||
|                 `ngcc is already running at process with id 188.\n` + |                 `ngcc is already running at process with id 188.\n` + | ||||||
|                 `If you are running multiple builds in parallel then you should pre-process your node_modules via the command line ngcc tool before starting the builds;\n` + |                 `If you are running multiple builds in parallel then you should pre-process your node_modules via the command line ngcc tool before starting the builds;\n` + | ||||||
|                 `See https://v9.angular.io/guide/ivy#speeding-up-ngcc-compilation.\n` + |                 `See https://v9.angular.io/guide/ivy#speeding-up-ngcc-compilation.\n` + | ||||||
|                 `(If you are sure no ngcc process is running then you should delete the lock-file at ${lockFile.path}.)`); |                 `(If you are sure no ngcc process is running then you should delete the lock-file at ${ | ||||||
|  |                     lockFile.path}.)`);
 | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  | |||||||
| @ -7,14 +7,14 @@ | |||||||
|  */ |  */ | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| 
 | 
 | ||||||
| import {AbsoluteFsPath, absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, AbsoluteFsPath, getFileSystem} from '../../../src/ngtsc/file_system'; | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; | import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; | ||||||
| import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer'; | import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer'; | ||||||
| import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry'; | import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry'; | ||||||
| import {DecorationAnalyses} from '../../src/analysis/types'; | import {DecorationAnalyses} from '../../src/analysis/types'; | ||||||
| import {Esm2015ReflectionHost} from '../../src/host/esm2015_host'; | import {Esm2015ReflectionHost} from '../../src/host/esm2015_host'; | ||||||
| import {MissingInjectableMigration, getAngularCoreDecoratorName} from '../../src/migrations/missing_injectable_migration'; | import {getAngularCoreDecoratorName, MissingInjectableMigration} from '../../src/migrations/missing_injectable_migration'; | ||||||
| import {MockLogger} from '../helpers/mock_logger'; | import {MockLogger} from '../helpers/mock_logger'; | ||||||
| import {getRootFiles, makeTestEntryPointBundle} from '../helpers/utils'; | import {getRootFiles, makeTestEntryPointBundle} from '../helpers/utils'; | ||||||
| 
 | 
 | ||||||
| @ -58,7 +58,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|            }]); |            }]); | ||||||
| 
 | 
 | ||||||
|            const index = program.getSourceFile(INDEX_FILENAME) !; |            const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|            expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true); |            expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true); | ||||||
|            expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true); |            expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true); | ||||||
|            expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(false); |            expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(false); | ||||||
| @ -66,7 +66,7 @@ runInEachFileSystem(() => { | |||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     function runTests( |     function runTests( | ||||||
|         type: 'NgModule' | 'Directive' | 'Component', propName: 'providers' | 'viewProviders') { |         type: 'NgModule'|'Directive'|'Component', propName: 'providers'|'viewProviders') { | ||||||
|       const args = type === 'Component' ? 'template: "", ' : ''; |       const args = type === 'Component' ? 'template: "", ' : ''; | ||||||
| 
 | 
 | ||||||
|       it(`should migrate type provider in ${type}`, () => { |       it(`should migrate type provider in ${type}`, () => { | ||||||
| @ -85,7 +85,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'OtherService')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'OtherService')).toBe(false); | ||||||
|       }); |       }); | ||||||
| @ -106,12 +106,12 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'OtherService')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'OtherService')).toBe(false); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it(`should migrate object literal provider with forwardRef in ${type}`, async() => { |       it(`should migrate object literal provider with forwardRef in ${type}`, async () => { | ||||||
|         const {program, analysis} = setUpAndAnalyzeProgram([{ |         const {program, analysis} = setUpAndAnalyzeProgram([{ | ||||||
|           name: INDEX_FILENAME, |           name: INDEX_FILENAME, | ||||||
|           contents: ` |           contents: ` | ||||||
| @ -121,12 +121,13 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|             export class TestClass {} |             export class TestClass {} | ||||||
|             TestClass.decorators = [ |             TestClass.decorators = [ | ||||||
|               { type: ${type}, args: [{${args}${propName}: [{provide: forwardRef(() => MyService) }]}] } |               { type: ${type}, args: [{${args}${ | ||||||
|  |               propName}: [{provide: forwardRef(() => MyService) }]}] } | ||||||
|             ]; |             ]; | ||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -140,12 +141,13 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|             export class TestClass {} |             export class TestClass {} | ||||||
|             TestClass.decorators = [ |             TestClass.decorators = [ | ||||||
|               { type: ${type}, args: [{${args}${propName}: [{provide: MyService, useValue: null }]}] } |               { type: ${type}, args: [{${args}${ | ||||||
|  |               propName}: [{provide: MyService, useValue: null }]}] } | ||||||
|             ]; |             ]; | ||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -159,12 +161,13 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|             export class TestClass {} |             export class TestClass {} | ||||||
|             TestClass.decorators = [ |             TestClass.decorators = [ | ||||||
|               { type: ${type}, args: [{${args}${propName}: [{provide: MyService, useFactory: () => null }]}] } |               { type: ${type}, args: [{${args}${ | ||||||
|  |               propName}: [{provide: MyService, useFactory: () => null }]}] } | ||||||
|             ]; |             ]; | ||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -189,7 +192,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyToken')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'MyToken')).toBe(false); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyTokenAlias')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'MyTokenAlias')).toBe(false); | ||||||
| @ -206,12 +209,13 @@ runInEachFileSystem(() => { | |||||||
| 
 | 
 | ||||||
|             export class TestClass {} |             export class TestClass {} | ||||||
|             TestClass.decorators = [ |             TestClass.decorators = [ | ||||||
|               { type: ${type}, args: [{${args}${propName}: [{provide: MyToken, useClass: MyService}]}] } |               { type: ${type}, args: [{${args}${ | ||||||
|  |               propName}: [{provide: MyToken, useClass: MyService}]}] } | ||||||
|             ]; |             ]; | ||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyToken')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'MyToken')).toBe(false); | ||||||
|       }); |       }); | ||||||
| @ -234,7 +238,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(getInjectableDecorators(index, analysis, 'MyService').length).toBe(1); |         expect(getInjectableDecorators(index, analysis, 'MyService').length).toBe(1); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -256,7 +260,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -278,7 +282,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -300,7 +304,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -320,7 +324,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true); | ||||||
|       }); |       }); | ||||||
| @ -348,7 +352,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(true); | ||||||
| @ -381,7 +385,7 @@ runInEachFileSystem(() => { | |||||||
|          `,
 |          `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(true); | ||||||
| @ -407,7 +411,7 @@ runInEachFileSystem(() => { | |||||||
|           ` |           ` | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true); | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(false); | ||||||
| @ -434,7 +438,7 @@ runInEachFileSystem(() => { | |||||||
|           ` |           ` | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(getInjectableDecorators(index, analysis, 'ServiceA').length).toBe(1); |         expect(getInjectableDecorators(index, analysis, 'ServiceA').length).toBe(1); | ||||||
|         expect(getInjectableDecorators(index, analysis, 'ServiceB').length).toBe(1); |         expect(getInjectableDecorators(index, analysis, 'ServiceB').length).toBe(1); | ||||||
|       }); |       }); | ||||||
| @ -454,7 +458,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(false); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -481,7 +485,7 @@ runInEachFileSystem(() => { | |||||||
|           } |           } | ||||||
|         ]); |         ]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(SERVICE_FILENAME) !; |         const index = program.getSourceFile(SERVICE_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -508,7 +512,7 @@ runInEachFileSystem(() => { | |||||||
|           } |           } | ||||||
|         ]); |         ]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(SERVICE_FILENAME) !; |         const index = program.getSourceFile(SERVICE_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -527,7 +531,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
| @ -546,7 +550,7 @@ runInEachFileSystem(() => { | |||||||
|           `,
 |           `,
 | ||||||
|         }]); |         }]); | ||||||
| 
 | 
 | ||||||
|         const index = program.getSourceFile(INDEX_FILENAME) !; |         const index = program.getSourceFile(INDEX_FILENAME)!; | ||||||
|         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); |         expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false); | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -6,8 +6,9 @@ | |||||||
|  * found in the LICENSE file at https://angular.io/license
 |  * found in the LICENSE file at https://angular.io/license
 | ||||||
|  */ |  */ | ||||||
| import * as ts from 'typescript'; | import * as ts from 'typescript'; | ||||||
| import {AbsoluteFsPath, absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system'; | 
 | ||||||
| import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {absoluteFrom, AbsoluteFsPath, getFileSystem} from '../../../src/ngtsc/file_system'; | ||||||
|  | import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; | import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; | ||||||
| import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer'; | import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer'; | ||||||
| import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry'; | import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry'; | ||||||
| @ -34,7 +35,7 @@ runInEachFileSystem(() => { | |||||||
|       ` |       ` | ||||||
|       }]); |       }]); | ||||||
|       expect(errors).toEqual([]); |       expect(errors).toEqual([]); | ||||||
|       const file = analysis.get(program.getSourceFile(INDEX_FILENAME) !); |       const file = analysis.get(program.getSourceFile(INDEX_FILENAME)!); | ||||||
|       expect(file).toBeUndefined(); |       expect(file).toBeUndefined(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
| @ -56,7 +57,7 @@ runInEachFileSystem(() => { | |||||||
|       ` |       ` | ||||||
|       }]); |       }]); | ||||||
|       expect(errors).toEqual([]); |       expect(errors).toEqual([]); | ||||||
|       const file = analysis.get(program.getSourceFile(INDEX_FILENAME) !) !; |       const file = analysis.get(program.getSourceFile(INDEX_FILENAME)!)!; | ||||||
|       expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined(); |       expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined(); | ||||||
|       expect(file.compiledClasses.find(c => c.name === 'BaseClass')).toBeUndefined(); |       expect(file.compiledClasses.find(c => c.name === 'BaseClass')).toBeUndefined(); | ||||||
|     }); |     }); | ||||||
| @ -81,15 +82,15 @@ runInEachFileSystem(() => { | |||||||
|       ` |       ` | ||||||
|          }]); |          }]); | ||||||
|          expect(errors).toEqual([]); |          expect(errors).toEqual([]); | ||||||
|          const file = analysis.get(program.getSourceFile(INDEX_FILENAME) !) !; |          const file = analysis.get(program.getSourceFile(INDEX_FILENAME)!)!; | ||||||
|          expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined(); |          expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined(); | ||||||
|          const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass') !; |          const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass')!; | ||||||
|          expect(baseClass.decorators !.length).toEqual(1); |          expect(baseClass.decorators!.length).toEqual(1); | ||||||
|          const decorator = baseClass.decorators ![0]; |          const decorator = baseClass.decorators![0]; | ||||||
|          expect(decorator.name).toEqual('Directive'); |          expect(decorator.name).toEqual('Directive'); | ||||||
|          expect(decorator.identifier).toBeNull('The decorator must be synthesized'); |          expect(decorator.identifier).toBeNull('The decorator must be synthesized'); | ||||||
|          expect(decorator.import).toEqual({from: '@angular/core', name: 'Directive'}); |          expect(decorator.import).toEqual({from: '@angular/core', name: 'Directive'}); | ||||||
|          expect(decorator.args !.length).toEqual(0); |          expect(decorator.args!.length).toEqual(0); | ||||||
|        }); |        }); | ||||||
| 
 | 
 | ||||||
|     it('should not add a decorator to a base class that is already decorated', () => { |     it('should not add a decorator to a base class that is already decorated', () => { | ||||||
| @ -114,11 +115,11 @@ runInEachFileSystem(() => { | |||||||
|       ` |       ` | ||||||
|       }]); |       }]); | ||||||
|       expect(errors).toEqual([]); |       expect(errors).toEqual([]); | ||||||
|       const file = analysis.get(program.getSourceFile(INDEX_FILENAME) !) !; |       const file = analysis.get(program.getSourceFile(INDEX_FILENAME)!)!; | ||||||
|       expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined(); |       expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined(); | ||||||
|       const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass') !; |       const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass')!; | ||||||
|       expect(baseClass.decorators !.length).toEqual(1); |       expect(baseClass.decorators!.length).toEqual(1); | ||||||
|       const decorator = baseClass.decorators ![0]; |       const decorator = baseClass.decorators![0]; | ||||||
|       expect(decorator.name).toEqual('Directive'); |       expect(decorator.name).toEqual('Directive'); | ||||||
|       expect(decorator.identifier).not.toBeNull('The decorator must not be synthesized'); |       expect(decorator.identifier).not.toBeNull('The decorator must not be synthesized'); | ||||||
|     }); |     }); | ||||||
| @ -145,25 +146,25 @@ runInEachFileSystem(() => { | |||||||
|       ` |       ` | ||||||
|          }]); |          }]); | ||||||
|          expect(errors).toEqual([]); |          expect(errors).toEqual([]); | ||||||
|          const file = analysis.get(program.getSourceFile(INDEX_FILENAME) !) !; |          const file = analysis.get(program.getSourceFile(INDEX_FILENAME)!)!; | ||||||
|          expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined(); |          expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined(); | ||||||
|          expect(file.compiledClasses.find(c => c.name === 'RealBaseClass')).toBeUndefined(); |          expect(file.compiledClasses.find(c => c.name === 'RealBaseClass')).toBeUndefined(); | ||||||
| 
 | 
 | ||||||
|          const intermediateClass = file.compiledClasses.find(c => c.name === 'IntermediateClass') !; |          const intermediateClass = file.compiledClasses.find(c => c.name === 'IntermediateClass')!; | ||||||
|          expect(intermediateClass.decorators !.length).toEqual(1); |          expect(intermediateClass.decorators!.length).toEqual(1); | ||||||
|          const intermediateDecorator = intermediateClass.decorators ![0]; |          const intermediateDecorator = intermediateClass.decorators![0]; | ||||||
|          expect(intermediateDecorator.name).toEqual('Directive'); |          expect(intermediateDecorator.name).toEqual('Directive'); | ||||||
|          expect(intermediateDecorator.identifier).toBeNull('The decorator must be synthesized'); |          expect(intermediateDecorator.identifier).toBeNull('The decorator must be synthesized'); | ||||||
|          expect(intermediateDecorator.import).toEqual({from: '@angular/core', name: 'Directive'}); |          expect(intermediateDecorator.import).toEqual({from: '@angular/core', name: 'Directive'}); | ||||||
|          expect(intermediateDecorator.args !.length).toEqual(0); |          expect(intermediateDecorator.args!.length).toEqual(0); | ||||||
| 
 | 
 | ||||||
|          const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass') !; |          const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass')!; | ||||||
|          expect(baseClass.decorators !.length).toEqual(1); |          expect(baseClass.decorators!.length).toEqual(1); | ||||||
|          const baseDecorator = baseClass.decorators ![0]; |          const baseDecorator = baseClass.decorators![0]; | ||||||
|          expect(baseDecorator.name).toEqual('Directive'); |          expect(baseDecorator.name).toEqual('Directive'); | ||||||
|          expect(baseDecorator.identifier).toBeNull('The decorator must be synthesized'); |          expect(baseDecorator.identifier).toBeNull('The decorator must be synthesized'); | ||||||
|          expect(baseDecorator.import).toEqual({from: '@angular/core', name: 'Directive'}); |          expect(baseDecorator.import).toEqual({from: '@angular/core', name: 'Directive'}); | ||||||
|          expect(baseDecorator.args !.length).toEqual(0); |          expect(baseDecorator.args!.length).toEqual(0); | ||||||
|        }); |        }); | ||||||
| 
 | 
 | ||||||
|     it('should handle the base class being in a different file (same package) as the derived class', |     it('should handle the base class being in a different file (same package) as the derived class', | ||||||
| @ -195,14 +196,14 @@ runInEachFileSystem(() => { | |||||||
|            } |            } | ||||||
|          ]); |          ]); | ||||||
|          expect(errors).toEqual([]); |          expect(errors).toEqual([]); | ||||||
|          const file = analysis.get(program.getSourceFile(BASE_FILENAME) !) !; |          const file = analysis.get(program.getSourceFile(BASE_FILENAME)!)!; | ||||||
|          const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass') !; |          const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass')!; | ||||||
|          expect(baseClass.decorators !.length).toEqual(1); |          expect(baseClass.decorators!.length).toEqual(1); | ||||||
|          const decorator = baseClass.decorators ![0]; |          const decorator = baseClass.decorators![0]; | ||||||
|          expect(decorator.name).toEqual('Directive'); |          expect(decorator.name).toEqual('Directive'); | ||||||
|          expect(decorator.identifier).toBeNull('The decorator must be synthesized'); |          expect(decorator.identifier).toBeNull('The decorator must be synthesized'); | ||||||
|          expect(decorator.import).toEqual({from: '@angular/core', name: 'Directive'}); |          expect(decorator.import).toEqual({from: '@angular/core', name: 'Directive'}); | ||||||
|          expect(decorator.args !.length).toEqual(0); |          expect(decorator.args!.length).toEqual(0); | ||||||
|        }); |        }); | ||||||
| 
 | 
 | ||||||
|     it('should skip the base class if it is in a different package from the derived class', () => { |     it('should skip the base class if it is in a different package from the derived class', () => { | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ | |||||||
| import {absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system'; | import {absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system'; | ||||||
| import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; | ||||||
| import {loadTestFiles} from '../../../test/helpers'; | import {loadTestFiles} from '../../../test/helpers'; | ||||||
| import {NGCC_VERSION, cleanPackageJson, hasBeenProcessed, markAsProcessed, needsCleaning} from '../../src/packages/build_marker'; | import {cleanPackageJson, hasBeenProcessed, markAsProcessed, needsCleaning, NGCC_VERSION} from '../../src/packages/build_marker'; | ||||||
| import {EntryPointPackageJson} from '../../src/packages/entry_point'; | import {EntryPointPackageJson} from '../../src/packages/entry_point'; | ||||||
| import {DirectPackageJsonUpdater} from '../../src/writing/package_json_updater'; | import {DirectPackageJsonUpdater} from '../../src/writing/package_json_updater'; | ||||||
| 
 | 
 | ||||||
| @ -192,8 +192,9 @@ runInEachFileSystem(() => { | |||||||
|             .toBe(false); |             .toBe(false); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should return false if no markers exist', |       it('should return false if no markers exist', () => { | ||||||
|          () => { expect(hasBeenProcessed({name: 'test'}, 'module')).toBe(false); }); |         expect(hasBeenProcessed({name: 'test'}, 'module')).toBe(false); | ||||||
|  |       }); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     describe('needsCleaning()', () => { |     describe('needsCleaning()', () => { | ||||||
|  | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user