Changing front

This commit is contained in:
2023-01-16 17:49:38 +01:00
parent 0b8a93b256
commit 4fe4be7730
48586 changed files with 4725790 additions and 17464 deletions
+21
View File
@@ -0,0 +1,21 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc" />
import { AsyncNgccOptions, SyncNgccOptions } from './src/ngcc_options';
export { ConsoleLogger, Logger, LogLevel } from '../src/ngtsc/logging';
export { AsyncNgccOptions, clearTsConfigCache, NgccOptions, SyncNgccOptions } from './src/ngcc_options';
export { PathMappings } from './src/path_mappings';
export declare function process<T extends AsyncNgccOptions | SyncNgccOptions>(options: T): T extends AsyncNgccOptions ? Promise<void> : void;
export declare const containingDirPath: string;
/**
* Absolute file path that points to the `ngcc` command line entry-point.
*
* This can be used by the Angular CLI to spawn a process running ngcc using
* command line options.
*/
export declare const ngccMainFilePath: string;
+3
View File
@@ -0,0 +1,3 @@
#!/usr/bin/env node
/// <amd-module name="@angular/compiler-cli/ngcc/main-ngcc" />
export {};
@@ -0,0 +1,81 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/analysis/decoration_analyzer" />
import ts from 'typescript';
import { ParsedConfiguration } from '../../..';
import { ReferencesRegistry, ResourceLoader } from '../../../src/ngtsc/annotations';
import { InjectableClassRegistry } from '../../../src/ngtsc/annotations/common';
import { CycleAnalyzer, ImportGraph } from '../../../src/ngtsc/cycles';
import { ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { ModuleResolver, PrivateExportAliasingHost, ReferenceEmitter } from '../../../src/ngtsc/imports';
import { SemanticSymbol } from '../../../src/ngtsc/incremental/semantic_graph';
import { CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, HostDirectivesResolver, LocalMetadataRegistry } from '../../../src/ngtsc/metadata';
import { PartialEvaluator } from '../../../src/ngtsc/partial_evaluator';
import { LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver, TypeCheckScopeRegistry } from '../../../src/ngtsc/scope';
import { DecoratorHandler } from '../../../src/ngtsc/transform';
import { NgccReflectionHost } from '../host/ngcc_host';
import { Migration } from '../migrations/migration';
import { EntryPointBundle } from '../packages/entry_point_bundle';
import { NgccTraitCompiler } from './ngcc_trait_compiler';
import { CompiledFile, DecorationAnalyses } from './types';
/**
* Simple class that resolves and loads files directly from the filesystem.
*/
declare class NgccResourceLoader implements ResourceLoader {
private fs;
constructor(fs: ReadonlyFileSystem);
canPreload: boolean;
canPreprocess: boolean;
preload(): undefined | Promise<void>;
preprocessInline(): Promise<string>;
load(url: string): string;
resolve(url: string, containingFile: string): string;
}
/**
* This Analyzer will analyze the files that have decorated classes that need to be transformed.
*/
export declare class DecorationAnalyzer {
private fs;
private bundle;
private reflectionHost;
private referencesRegistry;
private diagnosticHandler;
private tsConfig;
private program;
private options;
private host;
private typeChecker;
private rootDirs;
private packagePath;
private isCore;
private compilerOptions;
moduleResolver: ModuleResolver;
resourceManager: NgccResourceLoader;
metaRegistry: LocalMetadataRegistry;
dtsMetaReader: DtsMetadataReader;
fullMetaReader: CompoundMetadataReader;
refEmitter: ReferenceEmitter;
aliasingHost: PrivateExportAliasingHost | null;
dtsModuleScopeResolver: MetadataDtsModuleScopeResolver;
scopeRegistry: LocalModuleScopeRegistry;
fullRegistry: CompoundMetadataRegistry;
evaluator: PartialEvaluator;
importGraph: ImportGraph;
cycleAnalyzer: CycleAnalyzer;
injectableRegistry: InjectableClassRegistry;
hostDirectivesResolver: HostDirectivesResolver;
typeCheckScopeRegistry: TypeCheckScopeRegistry;
handlers: DecoratorHandler<unknown, unknown, SemanticSymbol | null, unknown>[];
compiler: NgccTraitCompiler;
migrations: Migration[];
constructor(fs: ReadonlyFileSystem, bundle: EntryPointBundle, reflectionHost: NgccReflectionHost, referencesRegistry: ReferencesRegistry, diagnosticHandler?: (error: ts.Diagnostic) => void, tsConfig?: ParsedConfiguration | null);
/**
* Analyze a program to find all the decorated files should be transformed.
*
* @returns a map of the source files to the analysis for those files.
*/
analyzeProgram(): DecorationAnalyses;
protected applyMigrations(): void;
protected reportDiagnostics(): void;
protected compileFile(sourceFile: ts.SourceFile): CompiledFile;
private getReexportsForSourceFile;
}
export {};
+23
View File
@@ -0,0 +1,23 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/analysis/migration_host" />
import { AbsoluteFsPath } from '../../../src/ngtsc/file_system';
import { MetadataReader } from '../../../src/ngtsc/metadata';
import { PartialEvaluator } from '../../../src/ngtsc/partial_evaluator';
import { ClassDeclaration, Decorator } from '../../../src/ngtsc/reflection';
import { HandlerFlags } from '../../../src/ngtsc/transform';
import { NgccReflectionHost } from '../host/ngcc_host';
import { MigrationHost } from '../migrations/migration';
import { NgccTraitCompiler } from './ngcc_trait_compiler';
/**
* The standard implementation of `MigrationHost`, which is created by the `DecorationAnalyzer`.
*/
export declare class DefaultMigrationHost implements MigrationHost {
readonly reflectionHost: NgccReflectionHost;
readonly metadata: MetadataReader;
readonly evaluator: PartialEvaluator;
private compiler;
private entryPointPath;
constructor(reflectionHost: NgccReflectionHost, metadata: MetadataReader, evaluator: PartialEvaluator, compiler: NgccTraitCompiler, entryPointPath: AbsoluteFsPath);
injectSyntheticDecorator(clazz: ClassDeclaration, decorator: Decorator, flags?: HandlerFlags): void;
getAllDecorators(clazz: ClassDeclaration): Decorator[] | null;
isInScope(clazz: ClassDeclaration): boolean;
}
@@ -0,0 +1,62 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/analysis/module_with_providers_analyzer" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { ReferencesRegistry } from '../../../src/ngtsc/annotations';
import { Reference } from '../../../src/ngtsc/imports';
import { ClassDeclaration, DeclarationNode } from '../../../src/ngtsc/reflection';
import { NgccReflectionHost } from '../host/ngcc_host';
/**
* A structure returned from `getModuleWithProvidersFunctions()` that describes functions
* that return ModuleWithProviders objects.
*/
export interface ModuleWithProvidersInfo {
/**
* The name of the declared function.
*/
name: string;
/**
* The declaration of the function that returns the `ModuleWithProviders` object.
*/
declaration: ts.SignatureDeclaration;
/**
* Declaration of the containing class (if this is a method)
*/
container: DeclarationNode | null;
/**
* The declaration of the class that the `ngModule` property on the `ModuleWithProviders` object
* refers to.
*/
ngModule: Reference<ClassDeclaration>;
}
export declare type ModuleWithProvidersAnalyses = Map<ts.SourceFile, ModuleWithProvidersInfo[]>;
export declare const ModuleWithProvidersAnalyses: MapConstructor;
export declare class ModuleWithProvidersAnalyzer {
private host;
private typeChecker;
private referencesRegistry;
private processDts;
private evaluator;
constructor(host: NgccReflectionHost, typeChecker: ts.TypeChecker, referencesRegistry: ReferencesRegistry, processDts: boolean);
analyzeProgram(program: ts.Program): ModuleWithProvidersAnalyses;
private getRootFiles;
private getModuleWithProvidersFunctions;
/**
* Parse a function/method node (or its implementation), to see if it returns a
* `ModuleWithProviders` object.
* @param name The name of the function.
* @param node the node to check - this could be a function, a method or a variable declaration.
* @param implementation the actual function expression if `node` is a variable declaration.
* @param container the class that contains the function, if it is a method.
* @returns info about the function if it does return a `ModuleWithProviders` object; `null`
* otherwise.
*/
private parseForModuleWithProviders;
private getDtsModuleWithProvidersFunction;
private resolveNgModuleReference;
}
@@ -0,0 +1,35 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/analysis/ngcc_references_registry" />
import ts from 'typescript';
import { ReferencesRegistry } from '../../../src/ngtsc/annotations';
import { Reference } from '../../../src/ngtsc/imports';
import { Declaration, DeclarationNode, ReflectionHost } from '../../../src/ngtsc/reflection';
/**
* This is a place for DecoratorHandlers to register references that they
* find in their analysis of the code.
*
* This registry is used to ensure that these references are publicly exported
* from libraries that are compiled by ngcc.
*/
export declare class NgccReferencesRegistry implements ReferencesRegistry {
private host;
private map;
constructor(host: ReflectionHost);
/**
* Register one or more references in the registry.
* Only `ResolveReference` references are stored. Other types are ignored.
* @param references A collection of references to register.
*/
add(source: DeclarationNode, ...references: Reference<DeclarationNode>[]): void;
/**
* Create and return a mapping for the registered resolved references.
* @returns A map of reference identifiers to reference declarations.
*/
getDeclarationMap(): Map<ts.Identifier, Declaration>;
}
@@ -0,0 +1,43 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/analysis/ngcc_trait_compiler" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { SemanticSymbol } from '../../../src/ngtsc/incremental/semantic_graph';
import { ClassDeclaration, Decorator } from '../../../src/ngtsc/reflection';
import { DecoratorHandler, HandlerFlags, Trait, TraitCompiler } from '../../../src/ngtsc/transform';
import { NgccReflectionHost } from '../host/ngcc_host';
/**
* Specializes the `TraitCompiler` for ngcc purposes. Mainly, this includes an alternative way of
* scanning for classes to compile using the reflection host's `findClassSymbols`, together with
* support to inject synthetic decorators into the compilation for ad-hoc migrations that ngcc
* performs.
*/
export declare class NgccTraitCompiler extends TraitCompiler {
private ngccReflector;
constructor(handlers: DecoratorHandler<unknown, unknown, SemanticSymbol | null, unknown>[], ngccReflector: NgccReflectionHost);
get analyzedFiles(): ts.SourceFile[];
/**
* Analyzes the source file in search for classes to process. For any class that is found in the
* file, a `ClassRecord` is created and the source file is included in the `analyzedFiles` array.
*/
analyzeFile(sf: ts.SourceFile): void;
/**
* Associate a new synthesized decorator, which did not appear in the original source, with a
* given class.
* @param clazz the class to receive the new decorator.
* @param decorator the decorator to inject.
* @param flags optional bitwise flag to influence the compilation of the decorator.
*/
injectSyntheticDecorator(clazz: ClassDeclaration, decorator: Decorator, flags?: HandlerFlags): Trait<unknown, unknown, SemanticSymbol | null, unknown>[];
/**
* Returns all decorators that have been recognized for the provided class, including any
* synthetically injected decorators.
* @param clazz the declaration for which the decorators are returned.
*/
getAllDecorators(clazz: ClassDeclaration): Decorator[] | null;
}
@@ -0,0 +1,30 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/analysis/private_declarations_analyzer" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { AbsoluteFsPath } from '../../../src/ngtsc/file_system';
import { NgccReflectionHost } from '../host/ngcc_host';
import { NgccReferencesRegistry } from './ngcc_references_registry';
export interface ExportInfo {
identifier: string;
from: AbsoluteFsPath;
dtsFrom?: AbsoluteFsPath | null;
}
export declare type PrivateDeclarationsAnalyses = ExportInfo[];
/**
* This class will analyze a program to find all the declared classes
* (i.e. on an NgModule) that are not publicly exported via an entry-point.
*/
export declare class PrivateDeclarationsAnalyzer {
private host;
private referencesRegistry;
constructor(host: NgccReflectionHost, referencesRegistry: NgccReferencesRegistry);
analyzeProgram(program: ts.Program): PrivateDeclarationsAnalyses;
private getRootFiles;
private getPrivateDeclarations;
}
+30
View File
@@ -0,0 +1,30 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/analysis/types" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { ConstantPool } from '@angular/compiler';
import ts from 'typescript';
import { Reexport } from '../../../src/ngtsc/imports';
import { ClassDeclaration, Decorator } from '../../../src/ngtsc/reflection';
import { CompileResult } from '../../../src/ngtsc/transform';
export interface CompiledClass {
name: string;
decorators: Decorator[] | null;
declaration: ClassDeclaration;
compilation: CompileResult[];
}
export interface CompiledFile {
compiledClasses: CompiledClass[];
sourceFile: ts.SourceFile;
constantPool: ConstantPool;
/**
* Any re-exports which should be added next to this class, both in .js and (if possible) .d.ts.
*/
reexports: Reexport[];
}
export declare type DecorationAnalyses = Map<ts.SourceFile, CompiledFile>;
export declare const DecorationAnalyses: MapConstructor;
+12
View File
@@ -0,0 +1,12 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/analysis/util" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath } from '../../../src/ngtsc/file_system';
import { DependencyTracker } from '../../../src/ngtsc/incremental/api';
export declare function isWithinPackage(packagePath: AbsoluteFsPath, filePath: AbsoluteFsPath): boolean;
export declare const NOOP_DEPENDENCY_TRACKER: DependencyTracker;
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env node
/// <amd-module name="@angular/compiler-cli/ngcc/src/command_line_options" />
import { NgccOptions } from './ngcc_options';
export declare function parseCommandLineOptions(args: string[]): NgccOptions;
+10
View File
@@ -0,0 +1,10 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/constants" />
export declare const IMPORT_PREFIX = "\u0275ngcc";
export declare const NGCC_TIMED_OUT_EXIT_CODE = 177;
@@ -0,0 +1,21 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/dependencies/commonjs_dependency_host" />
import { AbsoluteFsPath } from '../../../src/ngtsc/file_system';
import { DependencyHostBase } from './dependency_host';
/**
* Helper functions for computing dependencies.
*/
export declare class CommonJsDependencyHost extends DependencyHostBase {
protected canSkipFile(fileContents: string): boolean;
protected extractImports(file: AbsoluteFsPath, fileContents: string): Set<string>;
}
/**
* Check whether a source file needs to be parsed for imports.
* This is a performance short-circuit, which saves us from creating
* a TypeScript AST unnecessarily.
*
* @param source The content of the source file to check.
*
* @returns false if there are definitely no require calls
* in this file, true otherwise.
*/
export declare function hasRequireCalls(source: string): boolean;
@@ -0,0 +1,78 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/dependencies/dependency_host" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, PathSegment, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { EntryPoint } from '../packages/entry_point';
import { ModuleResolver } from './module_resolver';
export interface DependencyHost {
collectDependencies(entryPointPath: AbsoluteFsPath, { dependencies, missing, deepImports }: DependencyInfo): void;
}
export interface DependencyInfo {
dependencies: Set<AbsoluteFsPath>;
missing: Set<AbsoluteFsPath | PathSegment>;
deepImports: Set<AbsoluteFsPath>;
}
export interface EntryPointWithDependencies {
entryPoint: EntryPoint;
depInfo: DependencyInfo;
}
export declare function createDependencyInfo(): DependencyInfo;
export declare abstract class DependencyHostBase implements DependencyHost {
protected fs: ReadonlyFileSystem;
protected moduleResolver: ModuleResolver;
constructor(fs: ReadonlyFileSystem, moduleResolver: ModuleResolver);
/**
* Find all the dependencies for the entry-point at the given path.
*
* @param entryPointPath The absolute path to the JavaScript file that represents an entry-point.
* @param dependencyInfo An object containing information about the dependencies of the
* entry-point, including those that were missing or deep imports into other entry-points. The
* sets in this object will be updated with new information about the entry-point's dependencies.
*/
collectDependencies(entryPointPath: AbsoluteFsPath, { dependencies, missing, deepImports }: DependencyInfo): void;
/**
* Find all the dependencies for the provided paths.
*
* @param files The list of absolute paths of JavaScript files to scan for dependencies.
* @param dependencyInfo An object containing information about the dependencies of the
* entry-point, including those that were missing or deep imports into other entry-points. The
* sets in this object will be updated with new information about the entry-point's dependencies.
*/
collectDependenciesInFiles(files: AbsoluteFsPath[], { dependencies, missing, deepImports }: DependencyInfo): void;
/**
* Compute the dependencies of the given file.
*
* @param file An absolute path to the file whose dependencies we want to get.
* @param dependencies A set that will have the absolute paths of resolved entry points added to
* it.
* @param missing A set that will have the dependencies that could not be found added to it.
* @param deepImports A set that will have the import paths that exist but cannot be mapped to
* entry-points, i.e. deep-imports.
* @param alreadySeen A set that is used to track internal dependencies to prevent getting stuck
* in a circular dependency loop.
*/
protected recursivelyCollectDependencies(file: AbsoluteFsPath, dependencies: Set<AbsoluteFsPath>, missing: Set<string>, deepImports: Set<string>, alreadySeen: Set<AbsoluteFsPath>): void;
protected abstract canSkipFile(fileContents: string): boolean;
protected abstract extractImports(file: AbsoluteFsPath, fileContents: string): Set<string>;
/**
* Resolve the given `importPath` from `file` and add it to the appropriate set.
*
* If the import is local to this package then follow it by calling
* `recursivelyCollectDependencies()`.
*
* @returns `true` if the import was resolved (to an entry-point, a local import, or a
* deep-import), `false` otherwise.
*/
protected processImport(importPath: string, file: AbsoluteFsPath, dependencies: Set<AbsoluteFsPath>, missing: Set<string>, deepImports: Set<string>, alreadySeen: Set<AbsoluteFsPath>): boolean;
/**
* Processes the file if it has not already been seen. This will also recursively process
* all files that are imported from the file, while taking the set of already seen files
* into account.
*/
protected processFile(file: AbsoluteFsPath, dependencies: Set<AbsoluteFsPath>, missing: Set<string>, deepImports: Set<string>, alreadySeen: Set<AbsoluteFsPath>): void;
}
@@ -0,0 +1,103 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/dependencies/dependency_resolver" />
import { DepGraph } from 'dependency-graph';
import { ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { NgccConfiguration } from '../packages/configuration';
import { EntryPoint, EntryPointFormat } from '../packages/entry_point';
import { PartiallyOrderedList } from '../utils';
import { DependencyHost, EntryPointWithDependencies } from './dependency_host';
/**
* Holds information about entry points that are removed because
* they have dependencies that are missing (directly or transitively).
*
* This might not be an error, because such an entry point might not actually be used
* in the application. If it is used then the `ngc` application compilation would
* fail also, so we don't need ngcc to catch this.
*
* For example, consider an application that uses the `@angular/router` package.
* This package includes an entry-point called `@angular/router/upgrade`, which has a dependency
* on the `@angular/upgrade` package.
* If the application never uses code from `@angular/router/upgrade` then there is no need for
* `@angular/upgrade` to be installed.
* In this case the ngcc tool should just ignore the `@angular/router/upgrade` end-point.
*/
export interface InvalidEntryPoint {
entryPoint: EntryPoint;
missingDependencies: string[];
}
/**
* Holds information about dependencies of an entry-point that do not need to be processed
* by the ngcc tool.
*
* For example, the `rxjs` package does not contain any Angular decorators that need to be
* compiled and so this can be safely ignored by ngcc.
*/
export interface IgnoredDependency {
entryPoint: EntryPoint;
dependencyPath: string;
}
export interface DependencyDiagnostics {
invalidEntryPoints: InvalidEntryPoint[];
ignoredDependencies: IgnoredDependency[];
}
/**
* Represents a partially ordered list of entry-points.
*
* The entry-points' order/precedence is such that dependent entry-points always come later than
* their dependencies in the list.
*
* See `DependencyResolver#sortEntryPointsByDependency()`.
*/
export declare type PartiallyOrderedEntryPoints = PartiallyOrderedList<EntryPoint>;
/**
* A list of entry-points, sorted by their dependencies, and the dependency graph.
*
* The `entryPoints` array will be ordered so that no entry point depends upon an entry point that
* appears later in the array.
*
* Some entry points or their dependencies may have been ignored. These are captured for
* diagnostic purposes in `invalidEntryPoints` and `ignoredDependencies` respectively.
*/
export interface SortedEntryPointsInfo extends DependencyDiagnostics {
entryPoints: PartiallyOrderedEntryPoints;
graph: DepGraph<EntryPoint>;
}
/**
* A class that resolves dependencies between entry-points.
*/
export declare class DependencyResolver {
private fs;
private logger;
private config;
private hosts;
private typingsHost;
constructor(fs: ReadonlyFileSystem, logger: Logger, config: NgccConfiguration, hosts: Partial<Record<EntryPointFormat, DependencyHost>>, typingsHost: DependencyHost);
/**
* Sort the array of entry points so that the dependant entry points always come later than
* their dependencies in the array.
* @param entryPoints An array entry points to sort.
* @param target If provided, only return entry-points depended on by this entry-point.
* @returns the result of sorting the entry points by dependency.
*/
sortEntryPointsByDependency(entryPoints: EntryPointWithDependencies[], target?: EntryPoint): SortedEntryPointsInfo;
getEntryPointWithDependencies(entryPoint: EntryPoint): EntryPointWithDependencies;
/**
* Computes a dependency graph of the given entry-points.
*
* The graph only holds entry-points that ngcc cares about and whose dependencies
* (direct and transitive) all exist.
*/
private computeDependencyGraph;
private getEntryPointFormatInfo;
/**
* Filter out the deepImports that can be ignored, according to this entryPoint's config.
*/
private filterIgnorableDeepImports;
}
@@ -0,0 +1,21 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/dependencies/dts_dependency_host" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { PathMappings } from '../path_mappings';
import { EsmDependencyHost } from './esm_dependency_host';
/**
* Helper functions for computing dependencies via typings files.
*/
export declare class DtsDependencyHost extends EsmDependencyHost {
constructor(fs: ReadonlyFileSystem, pathMappings?: PathMappings);
/**
* Attempts to process the `importPath` directly and also inside `@types/...`.
*/
protected processImport(importPath: string, file: AbsoluteFsPath, dependencies: Set<AbsoluteFsPath>, missing: Set<string>, deepImports: Set<string>, alreadySeen: Set<AbsoluteFsPath>): boolean;
}
@@ -0,0 +1,94 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/dependencies/esm_dependency_host" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { DependencyHostBase } from './dependency_host';
import { ModuleResolver } from './module_resolver';
/**
* Helper functions for computing dependencies.
*/
export declare class EsmDependencyHost extends DependencyHostBase {
private scanImportExpressions;
constructor(fs: ReadonlyFileSystem, moduleResolver: ModuleResolver, scanImportExpressions?: boolean);
private scanner;
protected canSkipFile(fileContents: string): boolean;
/**
* Extract any import paths from imports found in the contents of this file.
*
* This implementation uses the TypeScript scanner, which tokenizes source code,
* to process the string. This is halfway between working with the string directly,
* which is too difficult due to corner cases, and parsing the string into a full
* TypeScript Abstract Syntax Tree (AST), which ends up doing more processing than
* is needed.
*
* The scanning is not trivial because we must hold state between each token since
* the context of the token affects how it should be scanned, and the scanner does
* not manage this for us.
*
* Specifically, backticked strings are particularly challenging since it is possible
* to recursively nest backticks and TypeScript expressions within each other.
*/
protected extractImports(file: AbsoluteFsPath, fileContents: string): Set<string>;
/**
* We have found an `import` token so now try to identify the import path.
*
* This method will use the current state of `this.scanner` to extract a string literal module
* specifier. It expects that the current state of the scanner is that an `import` token has just
* been scanned.
*
* The following forms of import are matched:
*
* * `import "module-specifier";`
* * `import("module-specifier")`
* * `import defaultBinding from "module-specifier";`
* * `import defaultBinding, * as identifier from "module-specifier";`
* * `import defaultBinding, {...} from "module-specifier";`
* * `import * as identifier from "module-specifier";`
* * `import {...} from "module-specifier";`
*
* @returns the import path or null if there is no import or it is not a string literal.
*/
protected extractImportPath(): string | null;
/**
* We have found an `export` token so now try to identify a re-export path.
*
* This method will use the current state of `this.scanner` to extract a string literal module
* specifier. It expects that the current state of the scanner is that an `export` token has
* just been scanned.
*
* There are three forms of re-export that are matched:
*
* * `export * from '...';
* * `export * as alias from '...';
* * `export {...} from '...';
*/
protected extractReexportPath(): string | null;
protected skipNamespacedClause(): ts.SyntaxKind | null;
protected skipNamedClause(): ts.SyntaxKind;
protected tryStringLiteral(): string | null;
}
/**
* Check whether a source file needs to be parsed for imports.
* This is a performance short-circuit, which saves us from creating
* a TypeScript AST unnecessarily.
*
* @param source The content of the source file to check.
*
* @returns false if there are definitely no import or re-export statements
* in this file, true otherwise.
*/
export declare function hasImportOrReexportStatements(source: string): boolean;
/**
* Check whether the given statement is an import with a string literal module specifier.
* @param stmt the statement node to check.
* @returns true if the statement is an import with a string literal module specifier.
*/
export declare function isStringImportOrReexport(stmt: ts.Statement): stmt is ts.ImportDeclaration & {
moduleSpecifier: ts.StringLiteral;
};
+135
View File
@@ -0,0 +1,135 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/dependencies/module_resolver" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { PathMappings } from '../path_mappings';
/**
* This is a very cut-down implementation of the TypeScript module resolution strategy.
*
* It is specific to the needs of ngcc and is not intended to be a drop-in replacement
* for the TS module resolver. It is used to compute the dependencies between entry-points
* that may be compiled by ngcc.
*
* The algorithm only finds `.js` files for internal/relative imports and paths to
* the folder containing the `package.json` of the entry-point for external imports.
*
* It can cope with nested `node_modules` folders and also supports `paths`/`baseUrl`
* configuration properties, as provided in a `ts.CompilerOptions` object.
*/
export declare class ModuleResolver {
private fs;
readonly relativeExtensions: string[];
private pathMappings;
constructor(fs: ReadonlyFileSystem, pathMappings?: PathMappings, relativeExtensions?: string[]);
/**
* Resolve an absolute path for the `moduleName` imported into a file at `fromPath`.
* @param moduleName The name of the import to resolve.
* @param fromPath The path to the file containing the import.
* @returns A path to the resolved module or null if missing.
* Specifically:
* * the absolute path to the package.json of an external module
* * a JavaScript file of an internal module
* * null if none exists.
*/
resolveModuleImport(moduleName: string, fromPath: AbsoluteFsPath): ResolvedModule | null;
/**
* Convert the `pathMappings` into a collection of `PathMapper` functions.
*/
private processPathMappings;
/**
* Try to resolve a module name, as a relative path, from the `fromPath`.
*
* As it is relative, it only looks for files that end in one of the `relativeExtensions`.
* For example: `${moduleName}.js` or `${moduleName}/index.js`.
* If neither of these files exist then the method returns `null`.
*/
private resolveAsRelativePath;
/**
* Try to resolve the `moduleName`, by applying the computed `pathMappings` and
* then trying to resolve the mapped path as a relative or external import.
*
* Whether the mapped path is relative is defined as it being "below the `fromPath`" and not
* containing `node_modules`.
*
* If the mapped path is not relative but does not resolve to an external entry-point, then we
* check whether it would have resolved to a relative path, in which case it is marked as a
* "deep-import".
*/
private resolveByPathMappings;
/**
* Try to resolve the `moduleName` as an external entry-point by searching the `node_modules`
* folders up the tree for a matching `.../node_modules/${moduleName}`.
*
* If a folder is found but the path is not considered an entry-point (see `isEntryPoint()`) then
* it is marked as a "deep-import".
*/
private resolveAsEntryPoint;
/**
* Can we consider the given path as an entry-point to a package?
*
* This is achieved by checking for the existence of `${modulePath}/package.json`.
* If there is no `package.json`, we check whether this is an APF v14+ secondary entry-point,
* which does not have its own `package.json` but has an `exports` entry in the package's primary
* `package.json`.
*/
private isEntryPoint;
/**
* Apply the `pathMappers` to the `moduleName` and return all the possible
* paths that match.
*
* The mapped path is computed for each template in `mapping.templates` by
* replacing the `matcher.prefix` and `matcher.postfix` strings in `path with the
* `template.prefix` and `template.postfix` strings.
*/
private findMappedPaths;
/**
* Attempt to find a mapped path for the given `path` and a `mapping`.
*
* The `path` matches the `mapping` if if it starts with `matcher.prefix` and ends with
* `matcher.postfix`.
*
* @returns the wildcard segment of a matched `path`, or `null` if no match.
*/
private matchMapping;
/**
* Compute the candidate paths from the given mapping's templates using the matched
* string.
*/
private computeMappedTemplates;
/**
* Search up the folder tree for the first folder that contains `package.json`
* or `null` if none is found.
*/
private findPackagePath;
}
/** The result of resolving an import to a module. */
export declare type ResolvedModule = ResolvedExternalModule | ResolvedRelativeModule | ResolvedDeepImport;
/**
* A module that is external to the package doing the importing.
* In this case we capture the folder containing the entry-point.
*/
export declare class ResolvedExternalModule {
entryPointPath: AbsoluteFsPath;
constructor(entryPointPath: AbsoluteFsPath);
}
/**
* A module that is relative to the module doing the importing, and so internal to the
* source module's package.
*/
export declare class ResolvedRelativeModule {
modulePath: AbsoluteFsPath;
constructor(modulePath: AbsoluteFsPath);
}
/**
* A module that is external to the package doing the importing but pointing to a
* module that is deep inside a package, rather than to an entry-point of the package.
*/
export declare class ResolvedDeepImport {
importPath: AbsoluteFsPath;
constructor(importPath: AbsoluteFsPath);
}
@@ -0,0 +1,10 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/dependencies/umd_dependency_host" />
import { AbsoluteFsPath } from '../../../src/ngtsc/file_system';
import { DependencyHostBase } from './dependency_host';
/**
* Helper functions for computing dependencies.
*/
export declare class UmdDependencyHost extends DependencyHostBase {
protected canSkipFile(fileContents: string): boolean;
protected extractImports(file: AbsoluteFsPath, fileContents: string): Set<string>;
}
@@ -0,0 +1,42 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/entry_point_finder/directory_walker_entry_point_finder" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { EntryPointWithDependencies } from '../dependencies/dependency_host';
import { DependencyResolver, SortedEntryPointsInfo } from '../dependencies/dependency_resolver';
import { EntryPointManifest } from '../packages/entry_point_manifest';
import { PathMappings } from '../path_mappings';
import { EntryPointCollector } from './entry_point_collector';
import { EntryPointFinder } from './interface';
/**
* An EntryPointFinder that searches for all entry-points that can be found given a `basePath` and
* `pathMappings`.
*/
export declare class DirectoryWalkerEntryPointFinder implements EntryPointFinder {
private logger;
private resolver;
private entryPointCollector;
private entryPointManifest;
private sourceDirectory;
private pathMappings;
private basePaths;
constructor(logger: Logger, resolver: DependencyResolver, entryPointCollector: EntryPointCollector, entryPointManifest: EntryPointManifest, sourceDirectory: AbsoluteFsPath, pathMappings: PathMappings | undefined);
/**
* Search the `sourceDirectory`, and sub-directories, using `pathMappings` as necessary, to find
* all package entry-points.
*/
findEntryPoints(): SortedEntryPointsInfo;
/**
* Search the `basePath` for possible Angular packages and entry-points.
*
* @param basePath The path at which to start the search.
* @returns an array of `EntryPoint`s that were found within `basePath`.
*/
walkBasePathForPackages(basePath: AbsoluteFsPath): EntryPointWithDependencies[];
}
@@ -0,0 +1,42 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/entry_point_finder/entry_point_collector" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { EntryPointWithDependencies } from '../dependencies/dependency_host';
import { DependencyResolver } from '../dependencies/dependency_resolver';
import { NgccConfiguration } from '../packages/configuration';
/**
* A class that traverses a file-tree, starting at a given path, looking for all entry-points,
* also capturing the dependencies of each entry-point that is found.
*/
export declare class EntryPointCollector {
private fs;
private config;
private logger;
private resolver;
constructor(fs: ReadonlyFileSystem, config: NgccConfiguration, logger: Logger, resolver: DependencyResolver);
/**
* Look for Angular packages that need to be compiled, starting at the source directory.
* The function will recurse into directories that start with `@...`, e.g. `@angular/...`.
*
* @param sourceDirectory An absolute path to the root directory where searching begins.
* @returns an array of `EntryPoint`s that were found within `sourceDirectory`.
*/
walkDirectoryForPackages(sourceDirectory: AbsoluteFsPath): EntryPointWithDependencies[];
/**
* Search the `directory` looking for any secondary entry-points for a package, adding any that
* are found to the `entryPoints` array.
*
* @param entryPoints An array where we will add any entry-points found in this directory.
* @param packagePath The absolute path to the package that may contain entry-points.
* @param directory The current directory being searched.
* @param paths The paths contained in the current `directory`.
*/
private collectSecondaryEntryPoints;
}
@@ -0,0 +1,15 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/entry_point_finder/interface" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { SortedEntryPointsInfo } from '../dependencies/dependency_resolver';
export interface EntryPointFinder {
/**
* Search for Angular package entry-points.
*/
findEntryPoints(): SortedEntryPointsInfo;
}
@@ -0,0 +1,62 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/entry_point_finder/program_based_entry_point_finder" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { ParsedConfiguration } from '../../../src/perform_compile';
import { EntryPointWithDependencies } from '../dependencies/dependency_host';
import { DependencyResolver } from '../dependencies/dependency_resolver';
import { NgccConfiguration } from '../packages/configuration';
import { EntryPointManifest } from '../packages/entry_point_manifest';
import { EntryPointCollector } from './entry_point_collector';
import { TracingEntryPointFinder } from './tracing_entry_point_finder';
/**
* An EntryPointFinder that starts from the files in the program defined by the given tsconfig.json
* and only returns entry-points that are dependencies of these files.
*
* This is faster than searching the entire file-system for all the entry-points,
* and is used primarily by the CLI integration.
*/
export declare class ProgramBasedEntryPointFinder extends TracingEntryPointFinder {
private entryPointCollector;
private entryPointManifest;
private tsConfig;
private entryPointsWithDependencies;
constructor(fs: ReadonlyFileSystem, config: NgccConfiguration, logger: Logger, resolver: DependencyResolver, entryPointCollector: EntryPointCollector, entryPointManifest: EntryPointManifest, basePath: AbsoluteFsPath, tsConfig: ParsedConfiguration, projectPath: AbsoluteFsPath);
/**
* Return an array containing the external import paths that were extracted from the source-files
* of the program defined by the tsconfig.json.
*/
protected getInitialEntryPointPaths(): AbsoluteFsPath[];
/**
* For the given `entryPointPath`, compute, or retrieve, the entry-point information, including
* paths to other entry-points that this entry-point depends upon.
*
* In this entry-point finder, we use the `EntryPointManifest` to avoid computing each
* entry-point's dependencies in the case that this had been done previously.
*
* @param entryPointPath the path to the entry-point whose information and dependencies are to be
* retrieved or computed.
*
* @returns the entry-point and its dependencies or `null` if the entry-point is not compiled by
* Angular or cannot be determined.
*/
protected getEntryPointWithDeps(entryPointPath: AbsoluteFsPath): EntryPointWithDependencies | null;
/**
* Walk the base paths looking for entry-points or load this information from an entry-point
* manifest, if available.
*/
private findOrLoadEntryPoints;
/**
* Search the `basePath` for possible Angular packages and entry-points.
*
* @param basePath The path at which to start the search.
* @returns an array of `EntryPoint`s that were found within `basePath`.
*/
walkBasePathForPackages(basePath: AbsoluteFsPath): EntryPointWithDependencies[];
}
@@ -0,0 +1,96 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/entry_point_finder/targeted_entry_point_finder" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { EntryPointWithDependencies } from '../dependencies/dependency_host';
import { DependencyResolver, SortedEntryPointsInfo } from '../dependencies/dependency_resolver';
import { NgccConfiguration } from '../packages/configuration';
import { EntryPointJsonProperty } from '../packages/entry_point';
import { PathMappings } from '../path_mappings';
import { TracingEntryPointFinder } from './tracing_entry_point_finder';
/**
* An EntryPointFinder that starts from a target entry-point and only finds
* entry-points that are dependencies of the target.
*
* This is faster than searching the entire file-system for all the entry-points,
* and is used primarily by the CLI integration.
*/
export declare class TargetedEntryPointFinder extends TracingEntryPointFinder {
private targetPath;
constructor(fs: ReadonlyFileSystem, config: NgccConfiguration, logger: Logger, resolver: DependencyResolver, basePath: AbsoluteFsPath, pathMappings: PathMappings | undefined, targetPath: AbsoluteFsPath);
/**
* Search for Angular entry-points that can be reached from the entry-point specified by the given
* `targetPath`.
*/
findEntryPoints(): SortedEntryPointsInfo;
/**
* Determine whether the entry-point at the given `targetPath` needs to be processed.
*
* @param propertiesToConsider the package.json properties that should be considered for
* processing.
* @param compileAllFormats true if all formats need to be processed, or false if it is enough for
* one of the formats covered by the `propertiesToConsider` is processed.
*/
targetNeedsProcessingOrCleaning(propertiesToConsider: EntryPointJsonProperty[], compileAllFormats: boolean): boolean;
/**
* Return an array containing the `targetPath` from which to start the trace.
*/
protected getInitialEntryPointPaths(): AbsoluteFsPath[];
/**
* For the given `entryPointPath`, compute, or retrieve, the entry-point information, including
* paths to other entry-points that this entry-point depends upon.
*
* @param entryPointPath the path to the entry-point whose information and dependencies are to be
* retrieved or computed.
*
* @returns the entry-point and its dependencies or `null` if the entry-point is not compiled by
* Angular or cannot be determined.
*/
protected getEntryPointWithDeps(entryPointPath: AbsoluteFsPath): EntryPointWithDependencies | null;
/**
* Compute the path to the package that contains the given entry-point.
*
* In this entry-point finder it is not trivial to find the containing package, since it is
* possible that this entry-point is not directly below the directory containing the package.
* Moreover, the import path could be affected by path-mapping.
*
* @param entryPointPath the path to the entry-point, whose package path we want to compute.
*/
private computePackagePath;
/**
* Compute whether the `test` path is contained within the `base` path.
*
* Note that this doesn't use a simple `startsWith()` since that would result in a false positive
* for `test` paths such as `a/b/c-x` when the `base` path is `a/b/c`.
*
* Since `fs.relative()` can be quite expensive we check the fast possibilities first.
*/
private isPathContainedBy;
/**
* Search down to the `entryPointPath` from the `containingPath` for the first `package.json` that
* we come to. This is the path to the entry-point's containing package. For example if
* `containingPath` is `/a/b/c` and `entryPointPath` is `/a/b/c/d/e` and there exists
* `/a/b/c/d/package.json` and `/a/b/c/d/e/package.json`, then we will return `/a/b/c/d`.
*
* To account for nested `node_modules` we actually start the search at the last `node_modules` in
* the `entryPointPath` that is below the `containingPath`. E.g. if `containingPath` is `/a/b/c`
* and `entryPointPath` is `/a/b/c/d/node_modules/x/y/z`, we start the search at
* `/a/b/c/d/node_modules`.
*/
private computePackagePathFromContainingPath;
/**
* Search up the directory tree from the `entryPointPath` looking for a `node_modules` directory
* that we can use as a potential starting point for computing the package path.
*/
private computePackagePathFromNearestNodeModules;
/**
* Split the given `path` into path segments using an FS independent algorithm.
*/
private splitPath;
}
@@ -0,0 +1,68 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/entry_point_finder/tracing_entry_point_finder" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { EntryPointWithDependencies } from '../dependencies/dependency_host';
import { DependencyResolver, SortedEntryPointsInfo } from '../dependencies/dependency_resolver';
import { NgccConfiguration } from '../packages/configuration';
import { PathMappings } from '../path_mappings';
import { EntryPointFinder } from './interface';
/**
* An EntryPointFinder that starts from a set of initial files and only returns entry-points that
* are dependencies of these files.
*
* This is faster than processing all entry-points in the entire file-system, and is used primarily
* by the CLI integration.
*
* There are two concrete implementations of this class.
*
* * `TargetEntryPointFinder` - is given a single entry-point as the initial entry-point. This can
* be used in the synchronous CLI integration where the build tool has identified an external
* import to one of the source files being built.
* * `ProgramBasedEntryPointFinder` - computes the initial entry-points from the source files
* computed from a `tsconfig.json` file. This can be used in the asynchronous CLI integration
* where the `tsconfig.json` to be used to do the build is known.
*/
export declare abstract class TracingEntryPointFinder implements EntryPointFinder {
protected fs: ReadonlyFileSystem;
protected config: NgccConfiguration;
protected logger: Logger;
protected resolver: DependencyResolver;
protected basePath: AbsoluteFsPath;
protected pathMappings: PathMappings | undefined;
private basePaths;
constructor(fs: ReadonlyFileSystem, config: NgccConfiguration, logger: Logger, resolver: DependencyResolver, basePath: AbsoluteFsPath, pathMappings: PathMappings | undefined);
/**
* Search for Angular package entry-points.
*/
findEntryPoints(): SortedEntryPointsInfo;
/**
* Return an array of entry-point paths from which to start the trace.
*/
protected abstract getInitialEntryPointPaths(): AbsoluteFsPath[];
/**
* For the given `entryPointPath`, compute, or retrieve, the entry-point information, including
* paths to other entry-points that this entry-point depends upon.
*
* @param entryPointPath the path to the entry-point whose information and dependencies are to be
* retrieved or computed.
*
* @returns the entry-point and its dependencies or `null` if the entry-point is not compiled by
* Angular or cannot be determined.
*/
protected abstract getEntryPointWithDeps(entryPointPath: AbsoluteFsPath): EntryPointWithDependencies | null;
/**
* Parse the path-mappings to compute the base-paths that need to be considered when finding
* entry-points.
*
* This processing can be time-consuming if the path-mappings are complex or extensive.
* So the result is cached locally once computed.
*/
protected getBasePaths(): AbsoluteFsPath[];
}
+39
View File
@@ -0,0 +1,39 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/entry_point_finder/utils" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { PathMappings } from '../path_mappings';
/**
* Extract all the base-paths that we need to search for entry-points.
*
* This always contains the standard base-path (`sourceDirectory`).
* But it also parses the `paths` mappings object to guess additional base-paths.
*
* For example:
*
* ```
* getBasePaths('/node_modules', {baseUrl: '/dist', paths: {'*': ['lib/*', 'lib/generated/*']}})
* > ['/node_modules', '/dist/lib']
* ```
*
* Notice that `'/dist'` is not included as there is no `'*'` path,
* and `'/dist/lib/generated'` is not included as it is covered by `'/dist/lib'`.
*
* @param sourceDirectory The standard base-path (e.g. node_modules).
* @param pathMappings Path mapping configuration, from which to extract additional base-paths.
*/
export declare function getBasePaths(logger: Logger, sourceDirectory: AbsoluteFsPath, pathMappings: PathMappings | undefined): AbsoluteFsPath[];
/**
* Run a task and track how long it takes.
*
* @param task The task whose duration we are tracking.
* @param log The function to call with the duration of the task.
* @returns The result of calling `task`.
*/
export declare function trackDuration<T = void>(task: () => T extends Promise<unknown> ? never : T, log: (duration: number) => void): T;
@@ -0,0 +1,10 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/analyze_entry_points" />
import { FileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { EntryPointFinder } from '../entry_point_finder/interface';
import { EntryPointJsonProperty } from '../packages/entry_point';
import { AnalyzeEntryPointsFn } from './api';
/**
* Create the function for performing the analysis of the entry-points.
*/
export declare function getAnalyzeEntryPointsFn(logger: Logger, finder: EntryPointFinder, fileSystem: FileSystem, supportedPropertiesToConsider: EntryPointJsonProperty[], typingsOnly: boolean, compileAllFormats: boolean, propertiesToConsider: string[], inParallel: boolean): AnalyzeEntryPointsFn;
+28
View File
@@ -0,0 +1,28 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/api" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { FileToWrite } from '../rendering/utils';
import { Task, TaskCompletedCallback, TaskQueue } from './tasks/api';
/**
* The type of the function that analyzes entry-points and creates the list of tasks.
*
* @return A list of tasks that need to be executed in order to process the necessary format
* properties for all entry-points.
*/
export declare type AnalyzeEntryPointsFn = () => TaskQueue;
/** The type of the function that can process/compile a task. */
export declare type CompileFn<T> = (task: Task) => void | T;
/** The type of the function that creates the `CompileFn` function used to process tasks. */
export declare type CreateCompileFn = <T extends void | Promise<void>>(beforeWritingFiles: (transformedFiles: FileToWrite[]) => T, onTaskCompleted: TaskCompletedCallback) => CompileFn<T>;
/**
* A class that orchestrates and executes the required work (i.e. analyzes the entry-points,
* processes the resulting tasks, does book-keeping and validates the final outcome).
*/
export interface Executor {
execute(analyzeEntryPoints: AnalyzeEntryPointsFn, createCompileFn: CreateCompileFn): void | Promise<void>;
}
+52
View File
@@ -0,0 +1,52 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/cluster/api" />
import { AbsoluteFsPath } from '../../../../src/ngtsc/file_system';
import { JsonObject } from '../../utils';
import { PackageJsonChange } from '../../writing/package_json_updater';
import { Task, TaskProcessingOutcome } from '../tasks/api';
/** A message reporting that the worker is ready for retrieving tasks. */
export interface ReadyMessage extends JsonObject {
type: 'ready';
}
/** A message reporting that an unrecoverable error occurred. */
export interface ErrorMessage extends JsonObject {
type: 'error';
error: string;
}
/** A message requesting the processing of a task. */
export interface ProcessTaskMessage extends JsonObject {
type: 'process-task';
task: Task;
}
/**
* A message reporting the result of processing the currently assigned task.
*
* NOTE: To avoid the communication overhead, the task is not included in the message. Instead, the
* master is responsible for keeping a mapping of workers to their currently assigned tasks.
*/
export interface TaskCompletedMessage extends JsonObject {
type: 'task-completed';
outcome: TaskProcessingOutcome;
message: string | null;
}
/** A message listing the paths to transformed files about to be written to disk. */
export interface TransformedFilesMessage extends JsonObject {
type: 'transformed-files';
files: AbsoluteFsPath[];
}
/** A message requesting the update of a `package.json` file. */
export interface UpdatePackageJsonMessage extends JsonObject {
type: 'update-package-json';
packageJsonPath: AbsoluteFsPath;
changes: PackageJsonChange[];
}
/** The type of messages sent from cluster workers to the cluster master. */
export declare type MessageFromWorker = ReadyMessage | ErrorMessage | TaskCompletedMessage | TransformedFilesMessage | UpdatePackageJsonMessage;
/** The type of messages sent from the cluster master to cluster workers. */
export declare type MessageToWorker = ProcessTaskMessage;
+30
View File
@@ -0,0 +1,30 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/cluster/executor" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { PathManipulation } from '../../../../src/ngtsc/file_system';
import { Logger } from '../../../../src/ngtsc/logging';
import { AsyncLocker } from '../../locking/async_locker';
import { FileWriter } from '../../writing/file_writer';
import { PackageJsonUpdater } from '../../writing/package_json_updater';
import { AnalyzeEntryPointsFn, CreateCompileFn, Executor } from '../api';
import { CreateTaskCompletedCallback } from '../tasks/api';
/**
* An `Executor` that processes tasks in parallel (on multiple processes) and completes
* asynchronously.
*/
export declare class ClusterExecutor implements Executor {
private workerCount;
private fileSystem;
private logger;
private fileWriter;
private pkgJsonUpdater;
private lockFile;
private createTaskCompletedCallback;
constructor(workerCount: number, fileSystem: PathManipulation, logger: Logger, fileWriter: FileWriter, pkgJsonUpdater: PackageJsonUpdater, lockFile: AsyncLocker, createTaskCompletedCallback: CreateTaskCompletedCallback);
execute(analyzeEntryPoints: AnalyzeEntryPointsFn, _createCompileFn: CreateCompileFn): Promise<void>;
}
+56
View File
@@ -0,0 +1,56 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/cluster/master" />
import { AbsoluteFsPath, PathManipulation } from '../../../../src/ngtsc/file_system';
import { Logger } from '../../../../src/ngtsc/logging';
import { FileWriter } from '../../writing/file_writer';
import { PackageJsonUpdater } from '../../writing/package_json_updater';
import { AnalyzeEntryPointsFn } from '../api';
import { CreateTaskCompletedCallback } from '../tasks/api';
/**
* The cluster master is responsible for analyzing all entry-points, planning the work that needs to
* be done, distributing it to worker-processes and collecting/post-processing the results.
*/
export declare class ClusterMaster {
private maxWorkerCount;
private fileSystem;
private logger;
private fileWriter;
private pkgJsonUpdater;
private finishedDeferred;
private processingStartTime;
private taskAssignments;
private taskQueue;
private onTaskCompleted;
private remainingRespawnAttempts;
constructor(maxWorkerCount: number, fileSystem: PathManipulation, logger: Logger, fileWriter: FileWriter, pkgJsonUpdater: PackageJsonUpdater, analyzeEntryPoints: AnalyzeEntryPointsFn, createTaskCompletedCallback: CreateTaskCompletedCallback);
run(): Promise<void>;
/** Try to find available (idle) workers and assign them available (non-blocked) tasks. */
private maybeDistributeWork;
/** Handle a worker's exiting. (Might be intentional or not.) */
private onWorkerExit;
/** Handle a message from a worker. */
private onWorkerMessage;
/** Handle a worker's coming online and ready for retrieving IPC messages. */
private onWorkerReady;
/** Handle a worker's having completed their assigned task. */
private onWorkerTaskCompleted;
/** Handle a worker's message regarding the files transformed while processing its task. */
private onWorkerTransformedFiles;
/** Handle a worker's request to update a `package.json` file. */
private onWorkerUpdatePackageJson;
/** Stop all workers and stop listening on cluster events. */
private stopWorkers;
/**
* Wrap an event handler to ensure that `finishedDeferred` will be rejected on error (regardless
* if the handler completes synchronously or asynchronously).
*/
private wrapEventHandler;
}
/** Gets the absolute file path to the cluster worker script. */
export declare function getClusterWorkerScriptPath(fileSystem: PathManipulation): AbsoluteFsPath;
@@ -0,0 +1,9 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/cluster/ngcc_cluster_worker" />
export {};
@@ -0,0 +1,23 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/cluster/package_json_updater" />
import { AbsoluteFsPath } from '../../../../src/ngtsc/file_system';
import { JsonObject } from '../../utils';
import { PackageJsonChange, PackageJsonUpdate, PackageJsonUpdater } from '../../writing/package_json_updater';
/**
* A `PackageJsonUpdater` for cluster workers that will send update changes to the master process so
* that it can safely handle update operations on multiple processes.
*/
export declare class ClusterWorkerPackageJsonUpdater implements PackageJsonUpdater {
constructor();
createUpdate(): PackageJsonUpdate;
/**
* Apply the changes in-memory (if necessary) and send a message to the master process.
*/
writeChanges(changes: PackageJsonChange[], packageJsonPath: AbsoluteFsPath, preExistingParsedJson?: JsonObject): void;
}
+45
View File
@@ -0,0 +1,45 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/cluster/utils" />
import { MessageFromWorker, MessageToWorker } from './api';
/** Expose a `Promise` instance as well as APIs for resolving/rejecting it. */
export declare class Deferred<T> {
/**
* Resolve the associated promise with the specified value.
* If the value is a rejection (constructed with `Promise.reject()`), the promise will be rejected
* instead.
*
* @param value The value to resolve the promise with.
*/
resolve: (value: T) => void;
/**
* Rejects the associated promise with the specified reason.
*
* @param reason The rejection reason.
*/
reject: (reason: any) => void;
/** The `Promise` instance associated with this deferred. */
promise: Promise<T>;
}
/**
* Send a message to the cluster master.
* (This function should be invoked from cluster workers only.)
*
* @param msg The message to send to the cluster master.
* @return A promise that is resolved once the message has been sent.
*/
export declare const sendMessageToMaster: (msg: MessageFromWorker) => Promise<void>;
/**
* Send a message to a cluster worker.
* (This function should be invoked from the cluster master only.)
*
* @param workerId The ID of the recipient worker.
* @param msg The message to send to the worker.
* @return A promise that is resolved once the message has been sent.
*/
export declare const sendMessageToWorker: (workerId: number, msg: MessageToWorker) => Promise<void>;
+11
View File
@@ -0,0 +1,11 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/cluster/worker" />
import { Logger } from '../../../../src/ngtsc/logging';
import { CreateCompileFn } from '../api';
export declare function startWorker(logger: Logger, createCompileFn: CreateCompileFn): Promise<void>;
@@ -0,0 +1,11 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/create_compile_function" />
import { FileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { ParsedConfiguration } from '../../../src/perform_compile';
import { PathMappings } from '../path_mappings';
import { FileWriter } from '../writing/file_writer';
import { CreateCompileFn } from './api';
/**
* The function for creating the `compile()` function.
*/
export declare function getCreateCompileFn(fileSystem: FileSystem, logger: Logger, fileWriter: FileWriter, enableI18nLegacyMessageIdFormat: boolean, tsConfig: ParsedConfiguration | null, pathMappings: PathMappings | undefined): CreateCompileFn;
@@ -0,0 +1,35 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/single_process_executor" />
import { Logger } from '../../../src/ngtsc/logging';
import { AsyncLocker } from '../locking/async_locker';
import { SyncLocker } from '../locking/sync_locker';
import { AnalyzeEntryPointsFn, CreateCompileFn, Executor } from './api';
import { CreateTaskCompletedCallback } from './tasks/api';
export declare abstract class SingleProcessorExecutorBase {
private logger;
private createTaskCompletedCallback;
constructor(logger: Logger, createTaskCompletedCallback: CreateTaskCompletedCallback);
doExecute(analyzeEntryPoints: AnalyzeEntryPointsFn, createCompileFn: CreateCompileFn): void | Promise<void>;
}
/**
* An `Executor` that processes all tasks serially and completes synchronously.
*/
export declare class SingleProcessExecutorSync extends SingleProcessorExecutorBase implements Executor {
private lockFile;
constructor(logger: Logger, lockFile: SyncLocker, createTaskCompletedCallback: CreateTaskCompletedCallback);
execute(analyzeEntryPoints: AnalyzeEntryPointsFn, createCompileFn: CreateCompileFn): void;
}
/**
* An `Executor` that processes all tasks serially, but still completes asynchronously.
*/
export declare class SingleProcessExecutorAsync extends SingleProcessorExecutorBase implements Executor {
private lockFile;
constructor(logger: Logger, lockFile: AsyncLocker, createTaskCompletedCallback: CreateTaskCompletedCallback);
execute(analyzeEntryPoints: AnalyzeEntryPointsFn, createCompileFn: CreateCompileFn): Promise<void>;
}
+142
View File
@@ -0,0 +1,142 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/tasks/api" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { EntryPoint, EntryPointJsonProperty } from '../../packages/entry_point';
import { JsonObject, PartiallyOrderedList } from '../../utils';
/**
* Represents a unit of work to be undertaken by an `Executor`.
*
* A task consists of processing a specific format property of an entry-point.
* This may or may not also include processing the typings for that entry-point, which only needs to
* happen once across all the formats.
*/
export interface Task extends JsonObject {
/** The `EntryPoint` which needs to be processed as part of the task. */
entryPoint: EntryPoint;
/**
* The `package.json` format property to process (i.e. the property which points to the file that
* is the program entry-point).
*/
formatProperty: EntryPointJsonProperty;
/**
* The list of all format properties (including `task.formatProperty`) that should be marked as
* processed once the task has been completed, because they point to the format-path that will be
* processed as part of the task.
*/
formatPropertiesToMarkAsProcessed: EntryPointJsonProperty[];
/**
* Whether to process typings for this entry-point as part of the task.
*/
processDts: DtsProcessing;
}
/**
* The options for processing Typescript typings (.d.ts) files.
*/
export declare enum DtsProcessing {
/**
* Yes, process the typings for this entry point as part of the task.
*/
Yes = 0,
/**
* No, do not process the typings as part of this task - they must have already been processed by
* another task or previous ngcc process.
*/
No = 1,
/**
* Only process the typings for this entry-point; do not render any JavaScript files for the
* `formatProperty` of this task.
*/
Only = 2
}
/**
* Represents a partially ordered list of tasks.
*
* The ordering/precedence of tasks is determined by the inter-dependencies between their associated
* entry-points. Specifically, the tasks' order/precedence is such that tasks associated to
* dependent entry-points always come after tasks associated with their dependencies.
*
* As result of this ordering, it is guaranteed that - by processing tasks in the order in which
* they appear in the list - a task's dependencies will always have been processed before processing
* the task itself.
*
* See `DependencyResolver#sortEntryPointsByDependency()`.
*/
export declare type PartiallyOrderedTasks = PartiallyOrderedList<Task>;
/**
* A mapping from Tasks to the Tasks that depend upon them (dependents).
*/
export declare type TaskDependencies = Map<Task, Set<Task>>;
export declare const TaskDependencies: MapConstructor;
/**
* A function to create a TaskCompletedCallback function.
*/
export declare type CreateTaskCompletedCallback = (taskQueue: TaskQueue) => TaskCompletedCallback;
/**
* A function to be called once a task has been processed.
*/
export declare type TaskCompletedCallback = (task: Task, outcome: TaskProcessingOutcome, message: string | null) => void;
/**
* Represents the outcome of processing a `Task`.
*/
export declare const enum TaskProcessingOutcome {
/** Successfully processed the target format property. */
Processed = 0,
/** Failed to process the target format. */
Failed = 1
}
/**
* A wrapper around a list of tasks and providing utility methods for getting the next task of
* interest and determining when all tasks have been completed.
*
* (This allows different implementations to impose different constraints on when a task's
* processing can start.)
*/
export interface TaskQueue {
/** Whether all tasks have been completed. */
allTasksCompleted: boolean;
/**
* Get the next task whose processing can start (if any).
*
* This implicitly marks the task as in-progress.
* (This information is used to determine whether all tasks have been completed.)
*
* @return The next task available for processing or `null`, if no task can be processed at the
* moment (including if there are no more unprocessed tasks).
*/
getNextTask(): Task | null;
/**
* Mark a task as completed.
*
* This removes the task from the internal list of in-progress tasks.
* (This information is used to determine whether all tasks have been completed.)
*
* @param task The task to mark as completed.
*/
markAsCompleted(task: Task): void;
/**
* Mark a task as failed.
*
* Do not process the tasks that depend upon the given task.
*/
markAsFailed(task: Task): void;
/**
* Mark a task as not processed (i.e. add an in-progress task back to the queue).
*
* This removes the task from the internal list of in-progress tasks and adds it back to the list
* of pending tasks.
*
* @param task The task to mark as not processed.
*/
markAsUnprocessed(task: Task): void;
/**
* Return a string representation of the task queue (for debugging purposes).
*
* @return A string representation of the task queue.
*/
toString(): string;
}
+42
View File
@@ -0,0 +1,42 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/tasks/completion" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { PathManipulation, ReadonlyFileSystem } from '../../../../src/ngtsc/file_system';
import { Logger } from '../../../../src/ngtsc/logging';
import { PackageJsonUpdater } from '../../writing/package_json_updater';
import { Task, TaskCompletedCallback, TaskProcessingOutcome, TaskQueue } from './api';
/**
* A function that can handle a specific outcome of a task completion.
*
* These functions can be composed using the `composeTaskCompletedCallbacks()`
* to create a `TaskCompletedCallback` function that can be passed to an `Executor`.
*/
export declare type TaskCompletedHandler = (task: Task, message: string | null) => void;
/**
* Compose a group of TaskCompletedHandlers into a single TaskCompletedCallback.
*
* The compose callback will receive an outcome and will delegate to the appropriate handler based
* on this outcome.
*
* @param callbacks a map of outcomes to handlers.
*/
export declare function composeTaskCompletedCallbacks(callbacks: Record<TaskProcessingOutcome, TaskCompletedHandler>): TaskCompletedCallback;
/**
* Create a handler that will mark the entry-points in a package as being processed.
*
* @param pkgJsonUpdater The service used to update the package.json
*/
export declare function createMarkAsProcessedHandler(fs: PathManipulation, pkgJsonUpdater: PackageJsonUpdater): TaskCompletedHandler;
/**
* Create a handler that will throw an error.
*/
export declare function createThrowErrorHandler(fs: ReadonlyFileSystem): TaskCompletedHandler;
/**
* Create a handler that logs an error and marks the task as failed.
*/
export declare function createLogErrorHandler(logger: Logger, fs: ReadonlyFileSystem, taskQueue: TaskQueue): TaskCompletedHandler;
@@ -0,0 +1,39 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/tasks/queues/base_task_queue" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { Logger } from '../../../../../src/ngtsc/logging';
import { PartiallyOrderedTasks, Task, TaskDependencies, TaskQueue } from '../api';
/**
* A base `TaskQueue` implementation to be used as base for concrete implementations.
*/
export declare abstract class BaseTaskQueue implements TaskQueue {
protected logger: Logger;
protected tasks: PartiallyOrderedTasks;
protected dependencies: TaskDependencies;
get allTasksCompleted(): boolean;
protected inProgressTasks: Set<Task>;
/**
* A map of tasks that should be skipped, mapped to the task that caused them to be skipped.
*/
private tasksToSkip;
constructor(logger: Logger, tasks: PartiallyOrderedTasks, dependencies: TaskDependencies);
protected abstract computeNextTask(): Task | null;
getNextTask(): Task | null;
markAsCompleted(task: Task): void;
markAsFailed(task: Task): void;
markAsUnprocessed(task: Task): void;
toString(): string;
/**
* Mark the given `task` as to be skipped, then recursive skip all its dependents.
*
* @param task The task to skip
* @param failedTask The task that failed, causing this task to be skipped
*/
protected skipDependentTasks(task: Task, failedTask: Task): void;
protected stringifyTasks(tasks: Task[], indentation: string): string;
}
@@ -0,0 +1,28 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/tasks/queues/parallel_task_queue" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { Logger } from '../../../../../src/ngtsc/logging';
import { PartiallyOrderedTasks, Task, TaskDependencies } from '../api';
import { BaseTaskQueue } from './base_task_queue';
/**
* A `TaskQueue` implementation that assumes tasks are processed in parallel, thus has to ensure a
* task's dependencies have been processed before processing the task.
*/
export declare class ParallelTaskQueue extends BaseTaskQueue {
/**
* A map from Tasks to the Tasks that it depends upon.
*
* This is the reverse mapping of `TaskDependencies`.
*/
private blockedTasks;
constructor(logger: Logger, tasks: PartiallyOrderedTasks, dependencies: TaskDependencies);
computeNextTask(): Task | null;
markAsCompleted(task: Task): void;
toString(): string;
private stringifyBlockedTasks;
}
@@ -0,0 +1,17 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/tasks/queues/serial_task_queue" />
import { Task } from '../api';
import { BaseTaskQueue } from './base_task_queue';
/**
* A `TaskQueue` implementation that assumes tasks are processed serially and each one is completed
* before requesting the next one.
*/
export declare class SerialTaskQueue extends BaseTaskQueue {
computeNextTask(): Task | null;
}
+58
View File
@@ -0,0 +1,58 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/execution/tasks/utils" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { DepGraph } from 'dependency-graph';
import { EntryPoint } from '../../packages/entry_point';
import { PartiallyOrderedTasks, Task, TaskDependencies } from './api';
/** Stringify a task for debugging purposes. */
export declare const stringifyTask: (task: Task) => string;
/**
* Compute a mapping of tasks to the tasks that are dependent on them (if any).
*
* Task A can depend upon task B, if either:
*
* * A and B have the same entry-point _and_ B is generating the typings for that entry-point
* (i.e. has `processDts: true`).
* * A's entry-point depends on B's entry-point _and_ B is also generating typings.
*
* NOTE: If a task is not generating typings, then it cannot affect anything which depends on its
* entry-point, regardless of the dependency graph. To put this another way, only the task
* which produces the typings for a dependency needs to have been completed.
*
* As a performance optimization, we take into account the fact that `tasks` are sorted in such a
* way that a task can only depend on earlier tasks (i.e. dependencies always come before
* dependents in the list of tasks).
*
* @param tasks A (partially ordered) list of tasks.
* @param graph The dependency graph between entry-points.
* @return A map from each task to those tasks directly dependent upon it.
*/
export declare function computeTaskDependencies(tasks: PartiallyOrderedTasks, graph: DepGraph<EntryPoint>): TaskDependencies;
export declare function getDependentsSet(map: TaskDependencies, task: Task): Set<Task>;
/**
* Invert the given mapping of Task dependencies.
*
* @param dependencies The mapping of tasks to the tasks that depend upon them.
* @returns A mapping of tasks to the tasks that they depend upon.
*/
export declare function getBlockedTasks(dependencies: TaskDependencies): Map<Task, Set<Task>>;
/**
* Sort a list of tasks by priority.
*
* Priority is determined by the number of other tasks that a task is (transitively) blocking:
* The more tasks a task is blocking the higher its priority is, because processing it will
* potentially unblock more tasks.
*
* To keep the behavior predictable, if two tasks block the same number of other tasks, their
* relative order in the original `tasks` lists is preserved.
*
* @param tasks A (partially ordered) list of tasks.
* @param dependencies The mapping of tasks to the tasks that depend upon them.
* @return The list of tasks sorted by priority.
*/
export declare function sortTasksByPriority(tasks: PartiallyOrderedTasks, dependencies: TaskDependencies): PartiallyOrderedTasks;
+70
View File
@@ -0,0 +1,70 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/host/commonjs_host" />
import ts from 'typescript';
import { Logger } from '../../../src/ngtsc/logging';
import { Declaration, Import } from '../../../src/ngtsc/reflection';
import { BundleProgram } from '../packages/bundle_program';
import { FactoryMap } from '../utils';
import { Esm5ReflectionHost } from './esm5_host';
import { NgccClassSymbol } from './ngcc_host';
export declare class CommonJsReflectionHost extends Esm5ReflectionHost {
protected commonJsExports: FactoryMap<ts.SourceFile, Map<string, Declaration<ts.Declaration>> | null>;
protected topLevelHelperCalls: FactoryMap<string, FactoryMap<ts.SourceFile, ts.CallExpression[]>>;
protected program: ts.Program;
protected compilerHost: ts.CompilerHost;
constructor(logger: Logger, isCore: boolean, src: BundleProgram, dts?: BundleProgram | null);
getImportOfIdentifier(id: ts.Identifier): Import | null;
getDeclarationOfIdentifier(id: ts.Identifier): Declaration | null;
getExportsOfModule(module: ts.Node): Map<string, Declaration> | null;
/**
* Search statements related to the given class for calls to the specified helper.
*
* In CommonJS these helper calls can be outside the class's IIFE at the top level of the
* source file. Searching the top level statements for helpers can be expensive, so we
* try to get helpers from the IIFE first and only fall back on searching the top level if
* no helpers are found.
*
* @param classSymbol the class whose helper calls we are interested in.
* @param helperNames the names of the helpers (e.g. `__decorate`) whose calls we are interested
* in.
* @returns an array of nodes of calls to the helper with the given name.
*/
protected getHelperCallsForClass(classSymbol: NgccClassSymbol, helperNames: string[]): ts.CallExpression[];
/**
* Find all the helper calls at the top level of a source file.
*
* We cache the helper calls per source file so that we don't have to keep parsing the code for
* each class in a file.
*
* @param sourceFile the source who may contain helper calls.
* @param helperNames the names of the helpers (e.g. `__decorate`) whose calls we are interested
* in.
* @returns an array of nodes of calls to the helper with the given name.
*/
private getTopLevelHelperCalls;
private computeExportsOfCommonJsModule;
private extractBasicCommonJsExportDeclaration;
private extractCommonJsWildcardReexports;
private extractCommonJsDefinePropertyExportDeclaration;
private findCommonJsImport;
/**
* Handle the case where the identifier represents a reference to a whole CommonJS
* module, i.e. the result of a call to `require(...)`.
*
* @param id the identifier whose declaration we are looking for.
* @returns a declaration if `id` refers to a CommonJS module, or `null` otherwise.
*/
private getCommonJsModuleDeclaration;
/**
* If this is an IFE then try to grab the outer and inner classes otherwise fallback on the super
* class.
*/
protected getDeclarationOfExpression(expression: ts.Expression): Declaration | null;
private resolveModuleName;
}
+147
View File
@@ -0,0 +1,147 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/host/commonjs_umd_utils" />
import ts from 'typescript';
import { Declaration } from '../../../src/ngtsc/reflection';
export interface ExportDeclaration {
name: string;
declaration: Declaration;
}
/**
* A CommonJS or UMD wildcard re-export statement.
*
* The CommonJS or UMD version of `export * from 'blah';`.
*
* These statements can have several forms (depending, for example, on whether
* the TypeScript helpers are imported or emitted inline). The expression can have one of the
* following forms:
* - `__export(firstArg)`
* - `__exportStar(firstArg)`
* - `tslib.__export(firstArg, exports)`
* - `tslib.__exportStar(firstArg, exports)`
*
* In all cases, we only care about `firstArg`, which is the first argument of the re-export call
* expression and can be either a `require('...')` call or an identifier (initialized via a
* `require('...')` call).
*/
export interface WildcardReexportStatement extends ts.ExpressionStatement {
expression: ts.CallExpression;
}
/**
* A CommonJS or UMD re-export statement using an `Object.defineProperty()` call.
* For example:
*
* ```
* Object.defineProperty(exports, "<exported-id>",
* { enumerable: true, get: function () { return <imported-id>; } });
* ```
*/
export interface DefinePropertyReexportStatement extends ts.ExpressionStatement {
expression: ts.CallExpression & {
arguments: [ts.Identifier, ts.StringLiteral, ts.ObjectLiteralExpression];
};
}
/**
* A call expression that has a string literal for its first argument.
*/
export interface RequireCall extends ts.CallExpression {
arguments: ts.CallExpression['arguments'] & [ts.StringLiteral];
}
/**
* Return the "namespace" of the specified `ts.Identifier` if the identifier is the RHS of a
* property access expression, i.e. an expression of the form `<namespace>.<id>` (in which case a
* `ts.Identifier` corresponding to `<namespace>` will be returned). Otherwise return `null`.
*/
export declare function findNamespaceOfIdentifier(id: ts.Identifier): ts.Identifier | null;
/**
* Return the `RequireCall` that is used to initialize the specified `ts.Identifier`, if the
* specified identifier was indeed initialized with a require call in a declaration of the form:
* `var <id> = require('...')`
*/
export declare function findRequireCallReference(id: ts.Identifier, checker: ts.TypeChecker): RequireCall | null;
/**
* Check whether the specified `ts.Statement` is a wildcard re-export statement.
* I.E. an expression statement of one of the following forms:
* - `__export(<foo>)`
* - `__exportStar(<foo>)`
* - `tslib.__export(<foo>, exports)`
* - `tslib.__exportStar(<foo>, exports)`
*/
export declare function isWildcardReexportStatement(stmt: ts.Statement): stmt is WildcardReexportStatement;
/**
* Check whether the statement is a re-export of the form:
*
* ```
* Object.defineProperty(exports, "<export-name>",
* { enumerable: true, get: function () { return <import-name>; } });
* ```
*/
export declare function isDefinePropertyReexportStatement(stmt: ts.Statement): stmt is DefinePropertyReexportStatement;
/**
* Extract the "value" of the getter in a `defineProperty` statement.
*
* This will return the `ts.Expression` value of a single `return` statement in the `get` method
* of the property definition object, or `null` if that is not possible.
*/
export declare function extractGetterFnExpression(statement: DefinePropertyReexportStatement): ts.Expression | null;
/**
* Check whether the specified `ts.Node` represents a `require()` call, i.e. an call expression of
* the form: `require('<foo>')`
*/
export declare function isRequireCall(node: ts.Node): node is RequireCall;
/**
* Check whether the specified `path` is an "external" import.
* In other words, that it comes from a entry-point outside the current one.
*/
export declare function isExternalImport(path: string): boolean;
/**
* A UMD/CommonJS style export declaration of the form `exports.<name>`.
*/
export interface ExportsDeclaration extends ts.PropertyAccessExpression {
name: ts.Identifier;
expression: ts.Identifier;
parent: ExportsAssignment;
}
/**
* Check whether the specified `node` is a property access expression of the form
* `exports.<foo>`.
*/
export declare function isExportsDeclaration(expr: ts.Node): expr is ExportsDeclaration;
/**
* A UMD/CommonJS style export assignment of the form `exports.<foo> = <bar>`.
*/
export interface ExportsAssignment extends ts.BinaryExpression {
left: ExportsDeclaration;
}
/**
* Check whether the specified `node` is an assignment expression of the form
* `exports.<foo> = <bar>`.
*/
export declare function isExportsAssignment(expr: ts.Node): expr is ExportsAssignment;
/**
* An expression statement of the form `exports.<foo> = <bar>;`.
*/
export interface ExportsStatement extends ts.ExpressionStatement {
expression: ExportsAssignment;
}
/**
* Check whether the specified `stmt` is an expression statement of the form
* `exports.<foo> = <bar>;`.
*/
export declare function isExportsStatement(stmt: ts.Node): stmt is ExportsStatement;
/**
* Find the far right hand side of a sequence of aliased assignments of the form
*
* ```
* exports.MyClass = alias1 = alias2 = <<declaration>>
* ```
*
* @param node the expression to parse
* @returns the original `node` or the far right expression of a series of assignments.
*/
export declare function skipAliases(node: ts.Expression): ts.Expression;
+44
View File
@@ -0,0 +1,44 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/host/delegating_host" />
import ts from 'typescript';
import { ClassDeclaration, ClassMember, CtorParameter, Declaration, DeclarationNode, Decorator, FunctionDefinition, Import, ReflectionHost } from '../../../src/ngtsc/reflection';
import { NgccClassSymbol, NgccReflectionHost } from './ngcc_host';
/**
* A reflection host implementation that delegates reflector queries depending on whether they
* reflect on declaration files (for dependent libraries) or source files within the entry-point
* that is being compiled. The first type of queries are handled by the regular TypeScript
* reflection host, whereas the other queries are handled by an `NgccReflectionHost` that is
* specific to the entry-point's format.
*/
export declare class DelegatingReflectionHost implements NgccReflectionHost {
private tsHost;
private ngccHost;
constructor(tsHost: ReflectionHost, ngccHost: NgccReflectionHost);
getConstructorParameters(clazz: ClassDeclaration): CtorParameter[] | null;
getDeclarationOfIdentifier(id: ts.Identifier): Declaration | null;
getDecoratorsOfDeclaration(declaration: DeclarationNode): Decorator[] | null;
getDefinitionOfFunction(fn: ts.Node): FunctionDefinition | null;
getDtsDeclaration(declaration: DeclarationNode): ts.Declaration | null;
getExportsOfModule(module: ts.Node): Map<string, Declaration> | null;
getGenericArityOfClass(clazz: ClassDeclaration): number | null;
getImportOfIdentifier(id: ts.Identifier): Import | null;
getInternalNameOfClass(clazz: ClassDeclaration): ts.Identifier;
getAdjacentNameOfClass(clazz: ClassDeclaration): ts.Identifier;
getMembersOfClass(clazz: ClassDeclaration): ClassMember[];
getVariableValue(declaration: ts.VariableDeclaration): ts.Expression | null;
hasBaseClass(clazz: ClassDeclaration): boolean;
getBaseClassExpression(clazz: ClassDeclaration): ts.Expression | null;
isClass(node: ts.Node): node is ClassDeclaration;
findClassSymbols(sourceFile: ts.SourceFile): NgccClassSymbol[];
getClassSymbol(node: ts.Node): NgccClassSymbol | undefined;
getDecoratorsOfSymbol(symbol: NgccClassSymbol): Decorator[] | null;
getEndOfClass(classSymbol: NgccClassSymbol): ts.Node;
detectKnownDeclaration<T extends Declaration>(decl: T): T;
isStaticallyExported(decl: ts.Node): boolean;
}
+936
View File
@@ -0,0 +1,936 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/host/esm2015_host" />
import ts from 'typescript';
import { Logger } from '../../../src/ngtsc/logging';
import { ClassDeclaration, ClassMember, ClassMemberKind, CtorParameter, Declaration, DeclarationNode, Decorator, EnumMember, TypeScriptReflectionHost } from '../../../src/ngtsc/reflection';
import { BundleProgram } from '../packages/bundle_program';
import { NgccClassSymbol, NgccReflectionHost } from './ngcc_host';
export declare const DECORATORS: ts.__String;
export declare const PROP_DECORATORS: ts.__String;
export declare const CONSTRUCTOR: ts.__String;
export declare const CONSTRUCTOR_PARAMS: ts.__String;
/**
* Esm2015 packages contain ECMAScript 2015 classes, etc.
* Decorators are defined via static properties on the class. For example:
*
* ```
* class SomeDirective {
* }
* SomeDirective.decorators = [
* { type: Directive, args: [{ selector: '[someDirective]' },] }
* ];
* SomeDirective.ctorParameters = () => [
* { type: ViewContainerRef, },
* { type: TemplateRef, },
* { type: undefined, decorators: [{ type: Inject, args: [INJECTED_TOKEN,] },] },
* ];
* SomeDirective.propDecorators = {
* "input1": [{ type: Input },],
* "input2": [{ type: Input },],
* };
* ```
*
* * Classes are decorated if they have a static property called `decorators`.
* * Members are decorated if there is a matching key on a static property
* called `propDecorators`.
* * Constructor parameters decorators are found on an object returned from
* a static method called `ctorParameters`.
*/
export declare class Esm2015ReflectionHost extends TypeScriptReflectionHost implements NgccReflectionHost {
protected logger: Logger;
protected isCore: boolean;
protected src: BundleProgram;
protected dts: BundleProgram | null;
/**
* A mapping from source declarations to typings declarations, which are both publicly exported.
*
* There should be one entry for every public export visible from the root file of the source
* tree. Note that by definition the key and value declarations will not be in the same TS
* program.
*/
protected publicDtsDeclarationMap: Map<DeclarationNode, ts.Declaration> | null;
/**
* A mapping from source declarations to typings declarations, which are not publicly exported.
*
* This mapping is a best guess between declarations that happen to be exported from their file by
* the same name in both the source and the dts file. Note that by definition the key and value
* declarations will not be in the same TS program.
*/
protected privateDtsDeclarationMap: Map<DeclarationNode, ts.Declaration> | null;
/**
* The set of source files that have already been preprocessed.
*/
protected preprocessedSourceFiles: Set<ts.SourceFile>;
/**
* In ES2015, class declarations may have been down-leveled into variable declarations,
* initialized using a class expression. In certain scenarios, an additional variable
* is introduced that represents the class so that results in code such as:
*
* ```
* let MyClass_1; let MyClass = MyClass_1 = class MyClass {};
* ```
*
* This map tracks those aliased variables to their original identifier, i.e. the key
* corresponds with the declaration of `MyClass_1` and its value becomes the `MyClass` identifier
* of the variable declaration.
*
* This map is populated during the preprocessing of each source file.
*/
protected aliasedClassDeclarations: Map<DeclarationNode, ts.Identifier>;
/**
* Caches the information of the decorators on a class, as the work involved with extracting
* decorators is complex and frequently used.
*
* This map is lazily populated during the first call to `acquireDecoratorInfo` for a given class.
*/
protected decoratorCache: Map<ClassDeclaration<DeclarationNode>, DecoratorInfo>;
constructor(logger: Logger, isCore: boolean, src: BundleProgram, dts?: BundleProgram | null);
/**
* Find a symbol for a node that we think is a class.
* Classes should have a `name` identifier, because they may need to be referenced in other parts
* of the program.
*
* In ES2015, a class may be declared using a variable declaration of the following structures:
*
* ```
* var MyClass = MyClass_1 = class MyClass {};
* ```
*
* or
*
* ```
* var MyClass = MyClass_1 = (() => { class MyClass {} ... return MyClass; })()
* ```
*
* Here, the intermediate `MyClass_1` assignment is optional. In the above example, the
* `class MyClass {}` node is returned as declaration of `MyClass`.
*
* @param declaration the declaration node whose symbol we are finding.
* @returns the symbol for the node or `undefined` if it is not a "class" or has no symbol.
*/
getClassSymbol(declaration: ts.Node): NgccClassSymbol | undefined;
/**
* Examine a declaration (for example, of a class or function) and return metadata about any
* decorators present on the declaration.
*
* @param declaration a TypeScript node representing the class or function over which to reflect.
* For example, if the intent is to reflect the decorators of a class and the source is in ES6
* format, this will be a `ts.ClassDeclaration` node. If the source is in ES5 format, this
* might be a `ts.VariableDeclaration` as classes in ES5 are represented as the result of an
* IIFE execution.
*
* @returns an array of `Decorator` metadata if decorators are present on the declaration, or
* `null` if either no decorators were present or if the declaration is not of a decoratable
* type.
*/
getDecoratorsOfDeclaration(declaration: DeclarationNode): Decorator[] | null;
/**
* Examine a declaration which should be of a class, and return metadata about the members of the
* class.
*
* @param clazz a `ClassDeclaration` representing the class over which to reflect.
*
* @returns an array of `ClassMember` metadata representing the members of the class.
*
* @throws if `declaration` does not resolve to a class declaration.
*/
getMembersOfClass(clazz: ClassDeclaration): ClassMember[];
/**
* Reflect over the constructor of a class and return metadata about its parameters.
*
* This method only looks at the constructor of a class directly and not at any inherited
* constructors.
*
* @param clazz a `ClassDeclaration` representing the class over which to reflect.
*
* @returns an array of `Parameter` metadata representing the parameters of the constructor, if
* a constructor exists. If the constructor exists and has 0 parameters, this array will be empty.
* If the class has no constructor, this method returns `null`.
*
* @throws if `declaration` does not resolve to a class declaration.
*/
getConstructorParameters(clazz: ClassDeclaration): CtorParameter[] | null;
getBaseClassExpression(clazz: ClassDeclaration): ts.Expression | null;
getInternalNameOfClass(clazz: ClassDeclaration): ts.Identifier;
getAdjacentNameOfClass(clazz: ClassDeclaration): ts.Identifier;
private getNameFromClassSymbolDeclaration;
/**
* Check whether the given node actually represents a class.
*/
isClass(node: ts.Node): node is ClassDeclaration;
/**
* Trace an identifier to its declaration, if possible.
*
* This method attempts to resolve the declaration of the given identifier, tracing back through
* imports and re-exports until the original declaration statement is found. A `Declaration`
* object is returned if the original declaration is found, or `null` is returned otherwise.
*
* In ES2015, we need to account for identifiers that refer to aliased class declarations such as
* `MyClass_1`. Since such declarations are only available within the module itself, we need to
* find the original class declaration, e.g. `MyClass`, that is associated with the aliased one.
*
* @param id a TypeScript `ts.Identifier` to trace back to a declaration.
*
* @returns metadata about the `Declaration` if the original declaration is found, or `null`
* otherwise.
*/
getDeclarationOfIdentifier(id: ts.Identifier): Declaration | null;
/**
* Gets all decorators of the given class symbol. Any decorator that have been synthetically
* injected by a migration will not be present in the returned collection.
*/
getDecoratorsOfSymbol(symbol: NgccClassSymbol): Decorator[] | null;
getVariableValue(declaration: ts.VariableDeclaration): ts.Expression | null;
/**
* Find all top-level class symbols in the given file.
* @param sourceFile The source file to search for classes.
* @returns An array of class symbols.
*/
findClassSymbols(sourceFile: ts.SourceFile): NgccClassSymbol[];
/**
* Get the number of generic type parameters of a given class.
*
* @param clazz a `ClassDeclaration` representing the class over which to reflect.
*
* @returns the number of type parameters of the class, if known, or `null` if the declaration
* is not a class or has an unknown number of type parameters.
*/
getGenericArityOfClass(clazz: ClassDeclaration): number | null;
/**
* Take an exported declaration of a class (maybe down-leveled to a variable) and look up the
* declaration of its type in a separate .d.ts tree.
*
* This function is allowed to return `null` if the current compilation unit does not have a
* separate .d.ts tree. When compiling TypeScript code this is always the case, since .d.ts files
* are produced only during the emit of such a compilation. When compiling .js code, however,
* there is frequently a parallel .d.ts tree which this method exposes.
*
* Note that the `ts.ClassDeclaration` returned from this function may not be from the same
* `ts.Program` as the input declaration.
*/
getDtsDeclaration(declaration: DeclarationNode): ts.Declaration | null;
getEndOfClass(classSymbol: NgccClassSymbol): ts.Node;
/**
* Check whether a `Declaration` corresponds with a known declaration, such as `Object`, and set
* its `known` property to the appropriate `KnownDeclaration`.
*
* @param decl The `Declaration` to check.
* @return The passed in `Declaration` (potentially enhanced with a `KnownDeclaration`).
*/
detectKnownDeclaration<T extends Declaration>(decl: T): T;
/**
* Extract all the "classes" from the `statement` and add them to the `classes` map.
*/
protected addClassSymbolsFromStatement(classes: Map<ts.Symbol, NgccClassSymbol>, statement: ts.Statement): void;
/**
* Compute the inner declaration node of a "class" from the given `declaration` node.
*
* @param declaration a node that is either an inner declaration or an alias of a class.
*/
protected getInnerDeclarationFromAliasOrInner(declaration: ts.Node): ts.Node;
/**
* A class may be declared as a top level class declaration:
*
* ```
* class OuterClass { ... }
* ```
*
* or in a variable declaration to a class expression:
*
* ```
* var OuterClass = ClassAlias = class InnerClass {};
* ```
*
* or in a variable declaration to an IIFE containing a class declaration
*
* ```
* var OuterClass = ClassAlias = (() => {
* class InnerClass {}
* ...
* return InnerClass;
* })()
* ```
*
* or in a variable declaration to an IIFE containing a function declaration
*
* ```
* var OuterClass = ClassAlias = (() => {
* function InnerClass() {}
* ...
* return InnerClass;
* })()
* ```
*
* This method returns an `NgccClassSymbol` when provided with one of these cases.
*
* @param declaration the declaration whose symbol we are finding.
* @returns the symbol for the class or `undefined` if `declaration` does not represent an outer
* declaration of a class.
*/
protected getClassSymbolFromOuterDeclaration(declaration: ts.Node): NgccClassSymbol | undefined;
/**
* In ES2015, a class may be declared using a variable declaration of the following structures:
*
* ```
* let MyClass = MyClass_1 = class MyClass {};
* ```
*
* or
*
* ```
* let MyClass = MyClass_1 = (() => { class MyClass {} ... return MyClass; })()
* ```
*
* or
*
* ```
* let MyClass = MyClass_1 = (() => { let MyClass = class MyClass {}; ... return MyClass; })()
* ```
*
* This method extracts the `NgccClassSymbol` for `MyClass` when provided with the
* `class MyClass {}` declaration node. When the `var MyClass` node or any other node is given,
* this method will return undefined instead.
*
* @param declaration the declaration whose symbol we are finding.
* @returns the symbol for the node or `undefined` if it does not represent an inner declaration
* of a class.
*/
protected getClassSymbolFromInnerDeclaration(declaration: ts.Node): NgccClassSymbol | undefined;
/**
* Creates an `NgccClassSymbol` from an outer and inner declaration. If a class only has an outer
* declaration, the "implementation" symbol of the created `NgccClassSymbol` will be set equal to
* the "declaration" symbol.
*
* @param outerDeclaration The outer declaration node of the class.
* @param innerDeclaration The inner declaration node of the class, or undefined if no inner
* declaration is present.
* @returns the `NgccClassSymbol` representing the class, or undefined if a `ts.Symbol` for any of
* the declarations could not be resolved.
*/
protected createClassSymbol(outerDeclaration: ts.Identifier, innerDeclaration: ts.Node | null): NgccClassSymbol | undefined;
private getAdjacentSymbol;
/**
* Resolve a `ts.Symbol` to its declaration and detect whether it corresponds with a known
* declaration.
*/
protected getDeclarationOfSymbol(symbol: ts.Symbol, originalId: ts.Identifier | null): Declaration | null;
/**
* Finds the identifier of the actual class declaration for a potentially aliased declaration of a
* class.
*
* If the given declaration is for an alias of a class, this function will determine an identifier
* to the original declaration that represents this class.
*
* @param declaration The declaration to resolve.
* @returns The original identifier that the given class declaration resolves to, or `undefined`
* if the declaration does not represent an aliased class.
*/
protected resolveAliasedClassIdentifier(declaration: DeclarationNode): ts.Identifier | null;
/**
* Ensures that the source file that `node` is part of has been preprocessed.
*
* During preprocessing, all statements in the source file will be visited such that certain
* processing steps can be done up-front and cached for subsequent usages.
*
* @param sourceFile The source file that needs to have gone through preprocessing.
*/
protected ensurePreprocessed(sourceFile: ts.SourceFile): void;
/**
* Analyzes the given statement to see if it corresponds with a variable declaration like
* `let MyClass = MyClass_1 = class MyClass {};`. If so, the declaration of `MyClass_1`
* is associated with the `MyClass` identifier.
*
* @param statement The statement that needs to be preprocessed.
*/
protected preprocessStatement(statement: ts.Statement): void;
/**
* Get the top level statements for a module.
*
* In ES5 and ES2015 this is just the top level statements of the file.
* @param sourceFile The module whose statements we want.
* @returns An array of top level statements for the given module.
*/
protected getModuleStatements(sourceFile: ts.SourceFile): ts.Statement[];
/**
* Walk the AST looking for an assignment to the specified symbol.
* @param node The current node we are searching.
* @returns an expression that represents the value of the variable, or undefined if none can be
* found.
*/
protected findDecoratedVariableValue(node: ts.Node | undefined, symbol: ts.Symbol): ts.CallExpression | null;
/**
* Try to retrieve the symbol of a static property on a class.
*
* In some cases, a static property can either be set on the inner (implementation or adjacent)
* declaration inside the class' IIFE, or it can be set on the outer variable declaration.
* Therefore, the host checks all places, first looking up the property on the inner symbols, and
* if the property is not found it will fall back to looking up the property on the outer symbol.
*
* @param symbol the class whose property we are interested in.
* @param propertyName the name of static property.
* @returns the symbol if it is found or `undefined` if not.
*/
protected getStaticProperty(symbol: NgccClassSymbol, propertyName: ts.__String): ts.Symbol | undefined;
/**
* This is the main entry-point for obtaining information on the decorators of a given class. This
* information is computed either from static properties if present, or using `tslib.__decorate`
* helper calls otherwise. The computed result is cached per class.
*
* @param classSymbol the class for which decorators should be acquired.
* @returns all information of the decorators on the class.
*/
protected acquireDecoratorInfo(classSymbol: NgccClassSymbol): DecoratorInfo;
/**
* Attempts to compute decorator information from static properties "decorators", "propDecorators"
* and "ctorParameters" on the class. If neither of these static properties is present the
* library is likely not compiled using tsickle for usage with Closure compiler, in which case
* `null` is returned.
*
* @param classSymbol The class symbol to compute the decorators information for.
* @returns All information on the decorators as extracted from static properties, or `null` if
* none of the static properties exist.
*/
protected computeDecoratorInfoFromStaticProperties(classSymbol: NgccClassSymbol): {
classDecorators: Decorator[] | null;
memberDecorators: Map<string, Decorator[]> | null;
constructorParamInfo: ParamInfo[] | null;
};
/**
* Get all class decorators for the given class, where the decorators are declared
* via a static property. For example:
*
* ```
* class SomeDirective {}
* SomeDirective.decorators = [
* { type: Directive, args: [{ selector: '[someDirective]' },] }
* ];
* ```
*
* @param decoratorsSymbol the property containing the decorators we want to get.
* @returns an array of decorators or null if none where found.
*/
protected getClassDecoratorsFromStaticProperty(decoratorsSymbol: ts.Symbol): Decorator[] | null;
/**
* Examine a symbol which should be of a class, and return metadata about its members.
*
* @param symbol the `ClassSymbol` representing the class over which to reflect.
* @returns an array of `ClassMember` metadata representing the members of the class.
*/
protected getMembersOfSymbol(symbol: NgccClassSymbol): ClassMember[];
/**
* Member decorators may be declared as static properties of the class:
*
* ```
* SomeDirective.propDecorators = {
* "ngForOf": [{ type: Input },],
* "ngForTrackBy": [{ type: Input },],
* "ngForTemplate": [{ type: Input },],
* };
* ```
*
* @param decoratorsProperty the class whose member decorators we are interested in.
* @returns a map whose keys are the name of the members and whose values are collections of
* decorators for the given member.
*/
protected getMemberDecoratorsFromStaticProperty(decoratorsProperty: ts.Symbol): Map<string, Decorator[]>;
/**
* For a given class symbol, collects all decorator information from tslib helper methods, as
* generated by TypeScript into emitted JavaScript files.
*
* Class decorators are extracted from calls to `tslib.__decorate` that look as follows:
*
* ```
* let SomeDirective = class SomeDirective {}
* SomeDirective = __decorate([
* Directive({ selector: '[someDirective]' }),
* ], SomeDirective);
* ```
*
* The extraction of member decorators is similar, with the distinction that its 2nd and 3rd
* argument correspond with a "prototype" target and the name of the member to which the
* decorators apply.
*
* ```
* __decorate([
* Input(),
* __metadata("design:type", String)
* ], SomeDirective.prototype, "input1", void 0);
* ```
*
* @param classSymbol The class symbol for which decorators should be extracted.
* @returns All information on the decorators of the class.
*/
protected computeDecoratorInfoFromHelperCalls(classSymbol: NgccClassSymbol): DecoratorInfo;
/**
* Extract the details of an entry within a `__decorate` helper call. For example, given the
* following code:
*
* ```
* __decorate([
* Directive({ selector: '[someDirective]' }),
* tslib_1.__param(2, Inject(INJECTED_TOKEN)),
* tslib_1.__metadata("design:paramtypes", [ViewContainerRef, TemplateRef, String])
* ], SomeDirective);
* ```
*
* it can be seen that there are calls to regular decorators (the `Directive`) and calls into
* `tslib` functions which have been inserted by TypeScript. Therefore, this function classifies
* a call to correspond with
* 1. a real decorator like `Directive` above, or
* 2. a decorated parameter, corresponding with `__param` calls from `tslib`, or
* 3. the type information of parameters, corresponding with `__metadata` call from `tslib`
*
* @param expression the expression that needs to be reflected into a `DecorateHelperEntry`
* @returns an object that indicates which of the three categories the call represents, together
* with the reflected information of the call, or null if the call is not a valid decorate call.
*/
protected reflectDecorateHelperEntry(expression: ts.Expression): DecorateHelperEntry | null;
protected reflectDecoratorCall(call: ts.CallExpression): Decorator | null;
/**
* Check the given statement to see if it is a call to any of the specified helper functions or
* null if not found.
*
* Matching statements will look like: `tslib_1.__decorate(...);`.
* @param statement the statement that may contain the call.
* @param helperNames the names of the helper we are looking for.
* @returns the node that corresponds to the `__decorate(...)` call or null if the statement
* does not match.
*/
protected getHelperCall(statement: ts.Statement, helperNames: string[]): ts.CallExpression | null;
/**
* Reflect over the given array node and extract decorator information from each element.
*
* This is used for decorators that are defined in static properties. For example:
*
* ```
* SomeDirective.decorators = [
* { type: Directive, args: [{ selector: '[someDirective]' },] }
* ];
* ```
*
* @param decoratorsArray an expression that contains decorator information.
* @returns an array of decorator info that was reflected from the array node.
*/
protected reflectDecorators(decoratorsArray: ts.Expression): Decorator[];
/**
* Reflect over a symbol and extract the member information, combining it with the
* provided decorator information, and whether it is a static member.
*
* A single symbol may represent multiple class members in the case of accessors;
* an equally named getter/setter accessor pair is combined into a single symbol.
* When the symbol is recognized as representing an accessor, its declarations are
* analyzed such that both the setter and getter accessor are returned as separate
* class members.
*
* One difference wrt the TypeScript host is that in ES2015, we cannot see which
* accessor originally had any decorators applied to them, as decorators are applied
* to the property descriptor in general, not a specific accessor. If an accessor
* has both a setter and getter, any decorators are only attached to the setter member.
*
* @param symbol the symbol for the member to reflect over.
* @param decorators an array of decorators associated with the member.
* @param isStatic true if this member is static, false if it is an instance property.
* @returns the reflected member information, or null if the symbol is not a member.
*/
protected reflectMembers(symbol: ts.Symbol, decorators?: Decorator[], isStatic?: boolean): ClassMember[] | null;
/**
* Reflect over a symbol and extract the member information, combining it with the
* provided decorator information, and whether it is a static member.
* @param node the declaration node for the member to reflect over.
* @param kind the assumed kind of the member, may become more accurate during reflection.
* @param decorators an array of decorators associated with the member.
* @param isStatic true if this member is static, false if it is an instance property.
* @returns the reflected member information, or null if the symbol is not a member.
*/
protected reflectMember(node: ts.Declaration, kind: ClassMemberKind | null, decorators?: Decorator[], isStatic?: boolean): ClassMember | null;
/**
* Find the declarations of the constructor parameters of a class identified by its symbol.
* @param classSymbol the class whose parameters we want to find.
* @returns an array of `ts.ParameterDeclaration` objects representing each of the parameters in
* the class's constructor or null if there is no constructor.
*/
protected getConstructorParameterDeclarations(classSymbol: NgccClassSymbol): ts.ParameterDeclaration[] | null;
/**
* Get the parameter decorators of a class constructor.
*
* @param classSymbol the class whose parameter info we want to get.
* @param parameterNodes the array of TypeScript parameter nodes for this class's constructor.
* @returns an array of constructor parameter info objects.
*/
protected getConstructorParamInfo(classSymbol: NgccClassSymbol, parameterNodes: ts.ParameterDeclaration[]): CtorParameter[];
/**
* Compute the `TypeValueReference` for the given `typeExpression`.
*
* Although `typeExpression` is a valid `ts.Expression` that could be emitted directly into the
* generated code, ngcc still needs to resolve the declaration and create an `IMPORTED` type
* value reference as the compiler has specialized handling for some symbols, for example
* `ChangeDetectorRef` from `@angular/core`. Such an `IMPORTED` type value reference will result
* in a newly generated namespace import, instead of emitting the original `typeExpression` as is.
*/
private typeToValue;
/**
* Determines where the `expression` is imported from.
*
* @param expression the expression to determine the import details for.
* @returns the `Import` for the expression, or `null` if the expression is not imported or the
* expression syntax is not supported.
*/
private getImportOfExpression;
/**
* Get the parameter type and decorators for the constructor of a class,
* where the information is stored on a static property of the class.
*
* Note that in ESM2015, the property is defined an array, or by an arrow function that returns
* an array, of decorator and type information.
*
* For example,
*
* ```
* SomeDirective.ctorParameters = () => [
* {type: ViewContainerRef},
* {type: TemplateRef},
* {type: undefined, decorators: [{ type: Inject, args: [INJECTED_TOKEN]}]},
* ];
* ```
*
* or
*
* ```
* SomeDirective.ctorParameters = [
* {type: ViewContainerRef},
* {type: TemplateRef},
* {type: undefined, decorators: [{type: Inject, args: [INJECTED_TOKEN]}]},
* ];
* ```
*
* @param paramDecoratorsProperty the property that holds the parameter info we want to get.
* @returns an array of objects containing the type and decorators for each parameter.
*/
protected getParamInfoFromStaticProperty(paramDecoratorsProperty: ts.Symbol): ParamInfo[] | null;
/**
* Search statements related to the given class for calls to the specified helper.
* @param classSymbol the class whose helper calls we are interested in.
* @param helperNames the names of the helpers (e.g. `__decorate`) whose calls we are interested
* in.
* @returns an array of CallExpression nodes for each matching helper call.
*/
protected getHelperCallsForClass(classSymbol: NgccClassSymbol, helperNames: string[]): ts.CallExpression[];
/**
* Find statements related to the given class that may contain calls to a helper.
*
* In ESM2015 code the helper calls are in the top level module, so we have to consider
* all the statements in the module.
*
* @param classSymbol the class whose helper calls we are interested in.
* @returns an array of statements that may contain helper calls.
*/
protected getStatementsForClass(classSymbol: NgccClassSymbol): ts.Statement[];
/**
* Test whether a decorator was imported from `@angular/core`.
*
* Is the decorator:
* * externally imported from `@angular/core`?
* * the current hosted program is actually `@angular/core` and
* - relatively internally imported; or
* - not imported, from the current file.
*
* @param decorator the decorator to test.
*/
protected isFromCore(decorator: Decorator): boolean;
/**
* Create a mapping between the public exports in a src program and the public exports of a dts
* program.
*
* @param src the program bundle containing the source files.
* @param dts the program bundle containing the typings files.
* @returns a map of source declarations to typings declarations.
*/
protected computePublicDtsDeclarationMap(src: BundleProgram, dts: BundleProgram): Map<DeclarationNode, ts.Declaration>;
/**
* Create a mapping between the "private" exports in a src program and the "private" exports of a
* dts program. These exports may be exported from individual files in the src or dts programs,
* but not exported from the root file (i.e publicly from the entry-point).
*
* This mapping is a "best guess" since we cannot guarantee that two declarations that happen to
* be exported from a file with the same name are actually equivalent. But this is a reasonable
* estimate for the purposes of ngcc.
*
* @param src the program bundle containing the source files.
* @param dts the program bundle containing the typings files.
* @returns a map of source declarations to typings declarations.
*/
protected computePrivateDtsDeclarationMap(src: BundleProgram, dts: BundleProgram): Map<DeclarationNode, ts.Declaration>;
/**
* Collect mappings between names of exported declarations in a file and its actual declaration.
*
* Any new mappings are added to the `dtsDeclarationMap`.
*/
protected collectDtsExportedDeclarations(dtsDeclarationMap: Map<string, ts.Declaration>, srcFile: ts.SourceFile, checker: ts.TypeChecker): void;
protected collectSrcExportedDeclarations(declarationMap: Map<DeclarationNode, ts.Declaration>, dtsDeclarationMap: Map<string, ts.Declaration>, srcFile: ts.SourceFile): void;
protected getDeclarationOfExpression(expression: ts.Expression): Declaration | null;
/** Checks if the specified declaration resolves to the known JavaScript global `Object`. */
protected isJavaScriptObjectDeclaration(decl: Declaration): boolean;
/**
* In JavaScript, enum declarations are emitted as a regular variable declaration followed by an
* IIFE in which the enum members are assigned.
*
* export var Enum;
* (function (Enum) {
* Enum["a"] = "A";
* Enum["b"] = "B";
* })(Enum || (Enum = {}));
*
* @param declaration A variable declaration that may represent an enum
* @returns An array of enum members if the variable declaration is followed by an IIFE that
* declares the enum members, or null otherwise.
*/
protected resolveEnumMembers(declaration: ts.VariableDeclaration): EnumMember[] | null;
/**
* Attempts to extract all `EnumMember`s from a function that is according to the JavaScript emit
* format for enums:
*
* function (Enum) {
* Enum["MemberA"] = "a";
* Enum["MemberB"] = "b";
* }
*
* @param fn The function expression that is assumed to contain enum members.
* @returns All enum members if the function is according to the correct syntax, null otherwise.
*/
private reflectEnumMembers;
/**
* Attempts to extract a single `EnumMember` from a statement in the following syntax:
*
* Enum["MemberA"] = "a";
*
* or, for enum member with numeric values:
*
* Enum[Enum["MemberA"] = 0] = "MemberA";
*
* @param enumName The identifier of the enum that the members should be set on.
* @param statement The statement to inspect.
* @returns An `EnumMember` if the statement is according to the expected syntax, null otherwise.
*/
protected reflectEnumMember(enumName: ts.Identifier, statement: ts.Statement): EnumMember | null;
private getAdjacentNameOfClassSymbol;
}
/**
* An enum member assignment that looks like `Enum[X] = Y;`.
*/
export declare type EnumMemberAssignment = ts.BinaryExpression & {
left: ts.ElementAccessExpression;
};
export declare type ParamInfo = {
decorators: Decorator[] | null;
typeExpression: ts.Expression | null;
};
/**
* Represents a call to `tslib.__metadata` as present in `tslib.__decorate` calls. This is a
* synthetic decorator inserted by TypeScript that contains reflection information about the
* target of the decorator, i.e. the class or property.
*/
export interface ParameterTypes {
type: 'params';
types: ts.Expression[];
}
/**
* Represents a call to `tslib.__param` as present in `tslib.__decorate` calls. This contains
* information on any decorators were applied to a certain parameter.
*/
export interface ParameterDecorators {
type: 'param:decorators';
index: number;
decorator: Decorator;
}
/**
* Represents a call to a decorator as it was present in the original source code, as present in
* `tslib.__decorate` calls.
*/
export interface DecoratorCall {
type: 'decorator';
decorator: Decorator;
}
/**
* Represents the different kinds of decorate helpers that may be present as first argument to
* `tslib.__decorate`, as follows:
*
* ```
* __decorate([
* Directive({ selector: '[someDirective]' }),
* tslib_1.__param(2, Inject(INJECTED_TOKEN)),
* tslib_1.__metadata("design:paramtypes", [ViewContainerRef, TemplateRef, String])
* ], SomeDirective);
* ```
*/
export declare type DecorateHelperEntry = ParameterTypes | ParameterDecorators | DecoratorCall;
/**
* The recorded decorator information of a single class. This information is cached in the host.
*/
interface DecoratorInfo {
/**
* All decorators that were present on the class. If no decorators were present, this is `null`
*/
classDecorators: Decorator[] | null;
/**
* All decorators per member of the class they were present on.
*/
memberDecorators: Map<string, Decorator[]>;
/**
* Represents the constructor parameter information, such as the type of a parameter and all
* decorators for a certain parameter. Indices in this array correspond with the parameter's
* index in the constructor. Note that this array may be sparse, i.e. certain constructor
* parameters may not have any info recorded.
*/
constructorParamInfo: ParamInfo[];
}
/**
* A statement node that represents an assignment.
*/
export declare type AssignmentStatement = ts.ExpressionStatement & {
expression: {
left: ts.Identifier;
right: ts.Expression;
};
};
/**
* Test whether a statement node is an assignment statement.
* @param statement the statement to test.
*/
export declare function isAssignmentStatement(statement: ts.Statement): statement is AssignmentStatement;
/**
* Parse the `expression` that is believed to be an IIFE and return the AST node that corresponds to
* the body of the IIFE.
*
* The expression may be wrapped in parentheses, which are stripped off.
*
* If the IIFE is an arrow function then its body could be a `ts.Expression` rather than a
* `ts.FunctionBody`.
*
* @param expression the expression to parse.
* @returns the `ts.Expression` or `ts.FunctionBody` that holds the body of the IIFE or `undefined`
* if the `expression` did not have the correct shape.
*/
export declare function getIifeBody(expression: ts.Expression): ts.ConciseBody | undefined;
/**
* Returns true if the `node` is an assignment of the form `a = b`.
*
* @param node The AST node to check.
*/
export declare function isAssignment(node: ts.Node): node is ts.AssignmentExpression<ts.EqualsToken>;
/**
* Tests whether the provided call expression targets a class, by verifying its arguments are
* according to the following form:
*
* ```
* __decorate([], SomeDirective);
* ```
*
* @param call the call expression that is tested to represent a class decorator call.
* @param matches predicate function to test whether the call is associated with the desired class.
*/
export declare function isClassDecorateCall(call: ts.CallExpression, matches: (identifier: ts.Identifier) => boolean): call is ts.CallExpression & {
arguments: [ts.ArrayLiteralExpression, ts.Expression];
};
/**
* Tests whether the provided call expression targets a member of the class, by verifying its
* arguments are according to the following form:
*
* ```
* __decorate([], SomeDirective.prototype, "member", void 0);
* ```
*
* @param call the call expression that is tested to represent a member decorator call.
* @param matches predicate function to test whether the call is associated with the desired class.
*/
export declare function isMemberDecorateCall(call: ts.CallExpression, matches: (identifier: ts.Identifier) => boolean): call is ts.CallExpression & {
arguments: [ts.ArrayLiteralExpression, ts.StringLiteral, ts.StringLiteral];
};
/**
* Helper method to extract the value of a property given the property's "symbol",
* which is actually the symbol of the identifier of the property.
*/
export declare function getPropertyValueFromSymbol(propSymbol: ts.Symbol): ts.Expression | undefined;
declare type InitializedVariableClassDeclaration = ClassDeclaration<ts.VariableDeclaration> & {
initializer: ts.Expression;
};
/**
* Handle a variable declaration of the form
*
* ```
* var MyClass = alias1 = alias2 = <<declaration>>
* ```
*
* @param node the LHS of a variable declaration.
* @returns the original AST node or the RHS of a series of assignments in a variable
* declaration.
*/
export declare function skipClassAliases(node: InitializedVariableClassDeclaration): ts.Expression;
/**
* This expression could either be a class expression
*
* ```
* class MyClass {};
* ```
*
* or an IIFE wrapped class expression
*
* ```
* (() => {
* class MyClass {}
* ...
* return MyClass;
* })()
* ```
*
* or an IIFE wrapped aliased class expression
*
* ```
* (() => {
* let MyClass = class MyClass {}
* ...
* return MyClass;
* })()
* ```
*
* or an IFFE wrapped ES5 class function
*
* ```
* (function () {
* function MyClass() {}
* ...
* return MyClass
* })()
* ```
*
* @param expression the node that represents the class whose declaration we are finding.
* @returns the declaration of the class or `null` if it is not a "class".
*/
export declare function getInnerClassDeclaration(expression: ts.Expression): ClassDeclaration<ts.ClassExpression | ts.ClassDeclaration | ts.FunctionDeclaration> | null;
/**
* Find the statement that contains the given node
* @param node a node whose containing statement we wish to find
*/
export declare function getContainingStatement(node: ts.Node): ts.Statement;
/**
* Get a node that represents the actual (outer) declaration of a class from its implementation.
*
* Sometimes, the implementation of a class is an expression that is hidden inside an IIFE and
* assigned to a variable outside the IIFE, which is what the rest of the program interacts with.
* For example,
*
* ```
* OuterNode = Alias = (function() { function InnerNode() {} return InnerNode; })();
* ```
*
* @param node a node that could be the implementation inside an IIFE.
* @returns a node that represents the outer declaration, or `null` if it is does not match the IIFE
* format shown above.
*/
export declare function getOuterNodeFromInnerDeclaration(node: ts.Node): ts.Node | null;
export {};
+300
View File
@@ -0,0 +1,300 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/host/esm5_host" />
import ts from 'typescript';
import { ClassDeclaration, ClassMember, Declaration, Decorator, FunctionDefinition } from '../../../src/ngtsc/reflection';
import { Esm2015ReflectionHost, ParamInfo } from './esm2015_host';
import { NgccClassSymbol } from './ngcc_host';
/**
* ESM5 packages contain ECMAScript IIFE functions that act like classes. For example:
*
* ```
* var CommonModule = (function () {
* function CommonModule() {
* }
* CommonModule.decorators = [ ... ];
* return CommonModule;
* ```
*
* * "Classes" are decorated if they have a static property called `decorators`.
* * Members are decorated if there is a matching key on a static property
* called `propDecorators`.
* * Constructor parameters decorators are found on an object returned from
* a static method called `ctorParameters`.
*
*/
export declare class Esm5ReflectionHost extends Esm2015ReflectionHost {
getBaseClassExpression(clazz: ClassDeclaration): ts.Expression | null;
/**
* Trace an identifier to its declaration, if possible.
*
* This method attempts to resolve the declaration of the given identifier, tracing back through
* imports and re-exports until the original declaration statement is found. A `Declaration`
* object is returned if the original declaration is found, or `null` is returned otherwise.
*
* In ES5, the implementation of a class is a function expression that is hidden inside an IIFE.
* If we are looking for the declaration of the identifier of the inner function expression, we
* will get hold of the outer "class" variable declaration and return its identifier instead. See
* `getClassDeclarationFromInnerFunctionDeclaration()` for more info.
*
* @param id a TypeScript `ts.Identifier` to trace back to a declaration.
*
* @returns metadata about the `Declaration` if the original declaration is found, or `null`
* otherwise.
*/
getDeclarationOfIdentifier(id: ts.Identifier): Declaration | null;
/**
* Parse a function declaration to find the relevant metadata about it.
*
* In ESM5 we need to do special work with optional arguments to the function, since they get
* their own initializer statement that needs to be parsed and then not included in the "body"
* statements of the function.
*
* @param node the function declaration to parse.
* @returns an object containing the node, statements and parameters of the function.
*/
getDefinitionOfFunction(node: ts.Node): FunctionDefinition | null;
/**
* Check whether a `Declaration` corresponds with a known declaration, such as a TypeScript helper
* function, and set its `known` property to the appropriate `KnownDeclaration`.
*
* @param decl The `Declaration` to check.
* @return The passed in `Declaration` (potentially enhanced with a `KnownDeclaration`).
*/
detectKnownDeclaration<T extends Declaration>(decl: T): T;
/**
* In ES5, the implementation of a class is a function expression that is hidden inside an IIFE,
* whose value is assigned to a variable (which represents the class to the rest of the program).
* So we might need to dig around to get hold of the "class" declaration.
*
* This method extracts a `NgccClassSymbol` if `declaration` is the function declaration inside
* the IIFE. Otherwise, undefined is returned.
*
* @param declaration the declaration whose symbol we are finding.
* @returns the symbol for the node or `undefined` if it is not a "class" or has no symbol.
*/
protected getClassSymbolFromInnerDeclaration(declaration: ts.Node): NgccClassSymbol | undefined;
/**
* Find the declarations of the constructor parameters of a class identified by its symbol.
*
* In ESM5, there is no "class" so the constructor that we want is actually the inner function
* declaration inside the IIFE, whose return value is assigned to the outer variable declaration
* (that represents the class to the rest of the program).
*
* @param classSymbol the symbol of the class (i.e. the outer variable declaration) whose
* parameters we want to find.
* @returns an array of `ts.ParameterDeclaration` objects representing each of the parameters in
* the class's constructor or `null` if there is no constructor.
*/
protected getConstructorParameterDeclarations(classSymbol: NgccClassSymbol): ts.ParameterDeclaration[] | null;
/**
* Get the parameter type and decorators for the constructor of a class,
* where the information is stored on a static method of the class.
*
* In this case the decorators are stored in the body of a method
* (`ctorParameters`) attached to the constructor function.
*
* Note that unlike ESM2015 this is a function expression rather than an arrow
* function:
*
* ```
* SomeDirective.ctorParameters = function() { return [
* { type: ViewContainerRef, },
* { type: TemplateRef, },
* { type: IterableDiffers, },
* { type: undefined, decorators: [{ type: Inject, args: [INJECTED_TOKEN,] },] },
* ]; };
* ```
*
* @param paramDecoratorsProperty the property that holds the parameter info we want to get.
* @returns an array of objects containing the type and decorators for each parameter.
*/
protected getParamInfoFromStaticProperty(paramDecoratorsProperty: ts.Symbol): ParamInfo[] | null;
/**
* Reflect over a symbol and extract the member information, combining it with the
* provided decorator information, and whether it is a static member.
*
* If a class member uses accessors (e.g getters and/or setters) then it gets downleveled
* in ES5 to a single `Object.defineProperty()` call. In that case we must parse this
* call to extract the one or two ClassMember objects that represent the accessors.
*
* @param symbol the symbol for the member to reflect over.
* @param decorators an array of decorators associated with the member.
* @param isStatic true if this member is static, false if it is an instance property.
* @returns the reflected member information, or null if the symbol is not a member.
*/
protected reflectMembers(symbol: ts.Symbol, decorators?: Decorator[], isStatic?: boolean): ClassMember[] | null;
/**
* Find statements related to the given class that may contain calls to a helper.
*
* In ESM5 code the helper calls are hidden inside the class's IIFE.
*
* @param classSymbol the class whose helper calls we are interested in. We expect this symbol
* to reference the inner identifier inside the IIFE.
* @returns an array of statements that may contain helper calls.
*/
protected getStatementsForClass(classSymbol: NgccClassSymbol): ts.Statement[];
/**
* A constructor function may have been "synthesized" by TypeScript during JavaScript emit,
* in the case no user-defined constructor exists and e.g. property initializers are used.
* Those initializers need to be emitted into a constructor in JavaScript, so the TypeScript
* compiler generates a synthetic constructor.
*
* We need to identify such constructors as ngcc needs to be able to tell if a class did
* originally have a constructor in the TypeScript source. For ES5, we can not tell an
* empty constructor apart from a synthesized constructor, but fortunately that does not
* matter for the code generated by ngtsc.
*
* When a class has a superclass however, a synthesized constructor must not be considered
* as a user-defined constructor as that prevents a base factory call from being created by
* ngtsc, resulting in a factory function that does not inject the dependencies of the
* superclass. Hence, we identify a default synthesized super call in the constructor body,
* according to the structure that TypeScript's ES2015 to ES5 transformer generates in
* https://github.com/Microsoft/TypeScript/blob/v3.2.2/src/compiler/transformers/es2015.ts#L1082-L1098
*
* Additionally, we handle synthetic delegate constructors that are emitted when TypeScript
* downlevel's ES2015 synthetically generated to ES5. These vary slightly from the default
* structure mentioned above because the ES2015 output uses a spread operator, for delegating
* to the parent constructor, that is preserved through a TypeScript helper in ES5. e.g.
*
* ```
* return _super.apply(this, tslib.__spread(arguments)) || this;
* ```
*
* or, since TypeScript 4.2 it would be
*
* ```
* return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this;
* ```
*
* Such constructs can be still considered as synthetic delegate constructors as they are
* the product of a common TypeScript to ES5 synthetic constructor, just being downleveled
* to ES5 using `tsc`. See: https://github.com/angular/angular/issues/38453.
*
*
* @param constructor a constructor function to test
* @returns true if the constructor appears to have been synthesized
*/
private isSynthesizedConstructor;
/**
* Identifies synthesized super calls which pass-through function arguments directly and are
* being assigned to a common `_this` variable. The following patterns we intend to match:
*
* 1. Delegate call emitted by TypeScript when it emits ES5 directly.
* ```
* var _this = _super !== null && _super.apply(this, arguments) || this;
* ```
*
* 2. Delegate call emitted by TypeScript when it downlevel's ES2015 to ES5.
* ```
* var _this = _super.apply(this, tslib.__spread(arguments)) || this;
* ```
* or using the syntax emitted since TypeScript 4.2:
* ```
* return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this;
* ```
*
* @param statement a statement that may be a synthesized super call
* @returns true if the statement looks like a synthesized super call
*/
private isSynthesizedSuperThisAssignment;
/**
* Identifies synthesized super calls which pass-through function arguments directly and
* are being returned. The following patterns correspond to synthetic super return calls:
*
* 1. Delegate call emitted by TypeScript when it emits ES5 directly.
* ```
* return _super !== null && _super.apply(this, arguments) || this;
* ```
*
* 2. Delegate call emitted by TypeScript when it downlevel's ES2015 to ES5.
* ```
* return _super.apply(this, tslib.__spread(arguments)) || this;
* ```
* or using the syntax emitted since TypeScript 4.2:
* ```
* return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this;
* ```
*
* @param statement a statement that may be a synthesized super call
* @returns true if the statement looks like a synthesized super call
*/
private isSynthesizedSuperReturnStatement;
/**
* Identifies synthesized super calls which pass-through function arguments directly. The
* synthetic delegate super call match the following patterns we intend to match:
*
* 1. Delegate call emitted by TypeScript when it emits ES5 directly.
* ```
* _super !== null && _super.apply(this, arguments) || this;
* ```
*
* 2. Delegate call emitted by TypeScript when it downlevel's ES2015 to ES5.
* ```
* _super.apply(this, tslib.__spread(arguments)) || this;
* ```
* or using the syntax emitted since TypeScript 4.2:
* ```
* return _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this;
* ```
*
* @param expression an expression that may represent a default super call
* @returns true if the expression corresponds with the above form
*/
private isSynthesizedDefaultSuperCall;
/**
* Tests whether the expression corresponds to a `super` call passing through
* function arguments without any modification. e.g.
*
* ```
* _super !== null && _super.apply(this, arguments) || this;
* ```
*
* This structure is generated by TypeScript when transforming ES2015 to ES5, see
* https://github.com/Microsoft/TypeScript/blob/v3.2.2/src/compiler/transformers/es2015.ts#L1148-L1163
*
* Additionally, we also handle cases where `arguments` are wrapped by a TypeScript spread
* helper.
* This can happen if ES2015 class output contain auto-generated constructors due to class
* members. The ES2015 output will be using `super(...arguments)` to delegate to the superclass,
* but once downleveled to ES5, the spread operator will be persisted through a TypeScript spread
* helper. For example:
*
* ```
* _super.apply(this, __spread(arguments)) || this;
* ```
*
* or, since TypeScript 4.2 it would be
*
* ```
* _super.apply(this, tslib.__spreadArray([], tslib.__read(arguments))) || this;
* ```
*
* More details can be found in: https://github.com/angular/angular/issues/38453.
*
* @param expression an expression that may represent a default super call
* @returns true if the expression corresponds with the above form
*/
private isSuperApplyCall;
/**
* Determines if the provided expression is one of the following call expressions:
*
* 1. `__spread(arguments)`
* 2. `__spreadArray([], __read(arguments))`
* 3. `__spreadArray([], __read(arguments), false)`
*
* The tslib helpers may have been emitted inline as in the above example, or they may be read
* from a namespace import.
*/
private isSpreadArgumentsExpression;
/**
* Inspects the provided expression and determines if it corresponds with a known helper function
* as receiver expression.
*/
private extractKnownHelperCall;
}
+88
View File
@@ -0,0 +1,88 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/host/ngcc_host" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { ClassDeclaration, Declaration, Decorator, ReflectionHost } from '../../../src/ngtsc/reflection';
import { SymbolWithValueDeclaration } from '../../../src/ngtsc/util/src/typescript';
/**
* The symbol corresponding to a "class" declaration. I.e. a `ts.Symbol` whose `valueDeclaration` is
* a `ClassDeclaration`.
*/
export declare type ClassSymbol = ts.Symbol & {
valueDeclaration: ClassDeclaration;
};
/**
* A representation of a class that accounts for the potential existence of two `ClassSymbol`s for a
* given class, as the compiled JavaScript bundles that ngcc reflects on can have two declarations.
*/
export interface NgccClassSymbol {
/**
* The name of the class.
*/
name: string;
/**
* Represents the symbol corresponding with the outer declaration of the class. This should be
* considered the public class symbol, i.e. its declaration is visible to the rest of the program.
*/
declaration: ClassSymbol;
/**
* Represents the symbol corresponding with the inner declaration of the class, referred to as its
* "implementation". This is not necessarily a `ClassSymbol` but rather just a `ts.Symbol`, as the
* inner declaration does not need to satisfy the requirements imposed on a publicly visible class
* declaration.
*/
implementation: SymbolWithValueDeclaration;
/**
* Represents the symbol corresponding to a variable within a class IIFE that may be used to
* attach static properties or decorated.
*/
adjacent?: SymbolWithValueDeclaration;
}
/**
* A reflection host that has extra methods for looking at non-Typescript package formats
*/
export interface NgccReflectionHost extends ReflectionHost {
/**
* Find a symbol for a declaration that we think is a class.
* @param declaration The declaration whose symbol we are finding
* @returns the symbol for the declaration or `undefined` if it is not
* a "class" or has no symbol.
*/
getClassSymbol(declaration: ts.Node): NgccClassSymbol | undefined;
/**
* Retrieves all decorators of a given class symbol.
* @param symbol Class symbol that can refer to a declaration which can hold decorators.
* @returns An array of decorators or null if none are declared.
*/
getDecoratorsOfSymbol(symbol: NgccClassSymbol): Decorator[] | null;
/**
* Retrieves all class symbols of a given source file.
* @param sourceFile The source file to search for classes.
* @returns An array of found class symbols.
*/
findClassSymbols(sourceFile: ts.SourceFile): NgccClassSymbol[];
/**
* Find the last node that is relevant to the specified class.
*
* As well as the main declaration, classes can have additional statements such as static
* properties (`SomeClass.staticProp = ...;`) and decorators (`__decorate(SomeClass, ...);`).
* It is useful to know exactly where the class "ends" so that we can inject additional
* statements after that point.
*
* @param classSymbol The class whose statements we want.
*/
getEndOfClass(classSymbol: NgccClassSymbol): ts.Node;
/**
* Check whether a `Declaration` corresponds with a known declaration and set its `known` property
* to the appropriate `KnownDeclaration`.
*
* @param decl The `Declaration` to check.
* @return The passed in `Declaration` (potentially enhanced with a `KnownDeclaration`).
*/
detectKnownDeclaration<T extends Declaration>(decl: T): T;
}
+86
View File
@@ -0,0 +1,86 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/host/umd_host" />
import ts from 'typescript';
import { Logger } from '../../../src/ngtsc/logging';
import { Declaration, Import } from '../../../src/ngtsc/reflection';
import { BundleProgram } from '../packages/bundle_program';
import { FactoryMap } from '../utils';
import { Esm5ReflectionHost } from './esm5_host';
import { NgccClassSymbol } from './ngcc_host';
export declare class UmdReflectionHost extends Esm5ReflectionHost {
protected umdModules: FactoryMap<ts.SourceFile, UmdModule | null>;
protected umdExports: FactoryMap<ts.SourceFile, Map<string, Declaration<ts.Declaration>> | null>;
protected umdImportPaths: FactoryMap<ts.ParameterDeclaration, string | null>;
protected program: ts.Program;
protected compilerHost: ts.CompilerHost;
constructor(logger: Logger, isCore: boolean, src: BundleProgram, dts?: BundleProgram | null);
getImportOfIdentifier(id: ts.Identifier): Import | null;
getDeclarationOfIdentifier(id: ts.Identifier): Declaration | null;
getExportsOfModule(module: ts.Node): Map<string, Declaration> | null;
getUmdModule(sourceFile: ts.SourceFile): UmdModule | null;
getUmdImportPath(importParameter: ts.ParameterDeclaration): string | null;
/**
* Get the top level statements for a module.
*
* In UMD modules these are the body of the UMD factory function.
*
* @param sourceFile The module whose statements we want.
* @returns An array of top level statements for the given module.
*/
protected getModuleStatements(sourceFile: ts.SourceFile): ts.Statement[];
protected getClassSymbolFromOuterDeclaration(declaration: ts.Node): NgccClassSymbol | undefined;
protected getClassSymbolFromInnerDeclaration(declaration: ts.Node): NgccClassSymbol | undefined;
/**
* Extract all "classes" from the `statement` and add them to the `classes` map.
*/
protected addClassSymbolsFromStatement(classes: Map<ts.Symbol, NgccClassSymbol>, statement: ts.Statement): void;
/**
* Analyze the given statement to see if it corresponds with an exports declaration like
* `exports.MyClass = MyClass_1 = <class def>;`. If so, the declaration of `MyClass_1`
* is associated with the `MyClass` identifier.
*
* @param statement The statement that needs to be preprocessed.
*/
protected preprocessStatement(statement: ts.Statement): void;
private computeUmdModule;
private computeExportsOfUmdModule;
private computeImportPath;
private extractBasicUmdExportDeclaration;
private extractUmdWildcardReexports;
private extractUmdDefinePropertyExportDeclaration;
/**
* Is the identifier a parameter on a UMD factory function, e.g. `function factory(this, core)`?
* If so then return its declaration.
*/
private findUmdImportParameter;
private getUmdDeclaration;
private getExportsDeclaration;
private getUmdModuleDeclaration;
private getImportPathFromParameter;
private getImportPathFromRequireCall;
/**
* If this is an IIFE then try to grab the outer and inner classes otherwise fallback on the super
* class.
*/
protected getDeclarationOfExpression(expression: ts.Expression): Declaration | null;
private resolveModuleName;
}
export declare function parseStatementForUmdModule(statement: ts.Statement): UmdModule | null;
export declare function getImportsOfUmdModule(umdModule: UmdModule): {
parameter: ts.ParameterDeclaration;
path: string;
}[];
interface UmdModule {
wrapperFn: ts.FunctionExpression;
factoryFn: ts.FunctionExpression;
factoryCalls: Record<'amdDefine' | 'commonJs' | 'commonJs2' | 'global', ts.CallExpression | null> & {
cjsCallForImports: ts.CallExpression;
};
}
export {};
+10
View File
@@ -0,0 +1,10 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/host/utils" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
export declare function stripParentheses(node: ts.Node): ts.Node;
+35
View File
@@ -0,0 +1,35 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/locking/async_locker" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { Logger } from '../../../src/ngtsc/logging';
import { LockFile } from './lock_file';
/**
* AsyncLocker is used to prevent more than one instance of ngcc executing at the same time,
* when being called in an asynchronous context.
*
* * When ngcc starts executing, it creates a file in the `compiler-cli/ngcc` folder.
* * If it finds one is already there then it pauses and waits for the file to be removed by the
* other process. If the file is not removed within a set timeout period given by
* `retryDelay*retryAttempts` an error is thrown with a suitable error message.
* * If the process locking the file changes, then we restart the timeout.
* * When ngcc completes executing, it removes the file so that future ngcc executions can start.
*/
export declare class AsyncLocker {
private lockFile;
protected logger: Logger;
private retryDelay;
private retryAttempts;
constructor(lockFile: LockFile, logger: Logger, retryDelay: number, retryAttempts: number);
/**
* Run a function guarded by the lock file.
*
* @param fn The function to run.
*/
lock<T>(fn: () => Promise<T>): Promise<T>;
protected create(): Promise<void>;
}
+29
View File
@@ -0,0 +1,29 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/locking/lock_file" />
import { AbsoluteFsPath, PathManipulation } from '../../../src/ngtsc/file_system';
export declare function getLockFilePath(fs: PathManipulation): AbsoluteFsPath;
export interface LockFile {
path: AbsoluteFsPath;
/**
* Write a lock file to disk containing the PID of the current process.
*/
write(): void;
/**
* Read the PID, of the process holding the lock, from the lock-file.
*
* It is feasible that the lock-file was removed between the call to `write()` that effectively
* checks for existence and this attempt to read the file. If so then this method should just
* gracefully return `"{unknown}"`.
*/
read(): string;
/**
* Remove the lock file from disk, whether or not it exists.
*/
remove(): void;
}
@@ -0,0 +1,43 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/locking/lock_file_with_child_process/index" />
/// <reference types="node" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { ChildProcess } from 'child_process';
import { AbsoluteFsPath, FileSystem } from '../../../../src/ngtsc/file_system';
import { Logger } from '../../../../src/ngtsc/logging';
import { LockFile } from '../lock_file';
/**
* This `LockFile` implementation uses a child-process to remove the lock file when the main process
* exits (for whatever reason).
*
* There are a few milliseconds between the child-process being forked and it registering its
* `disconnect` event, which is responsible for tidying up the lock-file in the event that the main
* process exits unexpectedly.
*
* We eagerly create the unlocker child-process so that it maximizes the time before the lock-file
* is actually written, which makes it very unlikely that the unlocker would not be ready in the
* case that the developer hits Ctrl-C or closes the terminal within a fraction of a second of the
* lock-file being created.
*
* The worst case scenario is that ngcc is killed too quickly and leaves behind an orphaned
* lock-file. In which case the next ngcc run will display a helpful error message about deleting
* the lock-file.
*/
export declare class LockFileWithChildProcess implements LockFile {
protected fs: FileSystem;
protected logger: Logger;
path: AbsoluteFsPath;
private unlocker;
constructor(fs: FileSystem, logger: Logger);
write(): void;
read(): string;
remove(): void;
protected createUnlocker(path: AbsoluteFsPath): ChildProcess;
}
/** Gets the absolute file path to the lock file unlocker script. */
export declare function getLockFileUnlockerScriptPath(fileSystem: FileSystem): AbsoluteFsPath;
@@ -0,0 +1,2 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/locking/lock_file_with_child_process/ngcc_lock_unlocker" />
export {};
@@ -0,0 +1,17 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/locking/lock_file_with_child_process/util" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, FileSystem } from '../../../../src/ngtsc/file_system';
import { Logger } from '../../../../src/ngtsc/logging';
/**
* Remove the lock-file at the provided `lockFilePath` from the given file-system.
*
* It only removes the file if the pid stored in the file matches the provided `pid`.
* The provided `pid` is of the process that is exiting and so no longer needs to hold the lock.
*/
export declare function removeLockFile(fs: FileSystem, logger: Logger, lockFilePath: AbsoluteFsPath, pid: string): void;
+36
View File
@@ -0,0 +1,36 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/locking/sync_locker" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { LockFile } from './lock_file';
/**
* SyncLocker is used to prevent more than one instance of ngcc executing at the same time,
* when being called in a synchronous context.
*
* * When ngcc starts executing, it creates a file in the `compiler-cli/ngcc` folder.
* * If it finds one is already there then it fails with a suitable error message.
* * When ngcc completes executing, it removes the file so that future ngcc executions can start.
*/
export declare class SyncLocker {
private lockFile;
constructor(lockFile: LockFile);
/**
* Run the given function guarded by the lock file.
*
* @param fn the function to run.
* @returns the value returned from the `fn` call.
*/
lock<T>(fn: () => T): T;
/**
* Write a lock file to disk, or error if there is already one there.
*/
protected create(): void;
/**
* The lock-file already exists so raise a helpful error.
*/
protected handleExistingLockFile(): void;
}
+18
View File
@@ -0,0 +1,18 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/main" />
import { AsyncNgccOptions, SyncNgccOptions } from './ngcc_options';
/**
* This is the main entry-point into ngcc (aNGular Compatibility Compiler).
*
* You can call this function to process one or more npm packages, to ensure
* that they are compatible with the ivy compiler (ngtsc).
*
* @param options The options telling ngcc what to compile and how.
*/
export declare function mainNgcc<T extends AsyncNgccOptions | SyncNgccOptions>(options: T): T extends AsyncNgccOptions ? Promise<void> : void;
+60
View File
@@ -0,0 +1,60 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/migrations/migration" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { MetadataReader } from '../../../src/ngtsc/metadata';
import { PartialEvaluator } from '../../../src/ngtsc/partial_evaluator';
import { ClassDeclaration, Decorator } from '../../../src/ngtsc/reflection';
import { HandlerFlags } from '../../../src/ngtsc/transform';
import { NgccReflectionHost } from '../host/ngcc_host';
/**
* Implement this interface and add it to the `DecorationAnalyzer.migrations` collection to get ngcc
* to modify the analysis of the decorators in the program in order to migrate older code to work
* with Ivy.
*
* `Migration.apply()` is called for every class in the program being compiled by ngcc.
*
* Note that the underlying program could be in a variety of different formats, e.g. ES2015, ES5,
* UMD, CommonJS etc. This means that an author of a `Migration` should not attempt to navigate and
* manipulate the AST nodes directly. Instead, the `MigrationHost` interface, passed to the
* `Migration`, provides access to a `MetadataReader`, `ReflectionHost` and `PartialEvaluator`
* interfaces, which should be used.
*/
export interface Migration {
apply(clazz: ClassDeclaration, host: MigrationHost): ts.Diagnostic | null;
}
export interface MigrationHost {
/** Provides access to the decorator information associated with classes. */
readonly metadata: MetadataReader;
/** Provides access to navigate the AST in a format-agnostic manner. */
readonly reflectionHost: NgccReflectionHost;
/** Enables expressions to be statically evaluated in the context of the program. */
readonly evaluator: PartialEvaluator;
/**
* Associate a new synthesized decorator, which did not appear in the original source, with a
* given class.
* @param clazz the class to receive the new decorator.
* @param decorator the decorator to inject.
* @param flags optional bitwise flag to influence the compilation of the decorator.
*/
injectSyntheticDecorator(clazz: ClassDeclaration, decorator: Decorator, flags?: HandlerFlags): void;
/**
* Retrieves all decorators that are associated with the class, including synthetic decorators
* that have been injected before.
* @param clazz the class for which all decorators are retrieved.
* @returns the list of the decorators, or null if the class was not decorated.
*/
getAllDecorators(clazz: ClassDeclaration): Decorator[] | null;
/**
* Determines whether the provided class in within scope of the entry-point that is currently
* being compiled.
* @param clazz the class for which to determine whether it is within the current entry-point.
* @returns true if the file is part of the compiled entry-point, false otherwise.
*/
isInScope(clazz: ClassDeclaration): boolean;
}
@@ -0,0 +1,36 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/migrations/missing_injectable_migration" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { ClassDeclaration, Decorator } from '../../../src/ngtsc/reflection';
import { Migration, MigrationHost } from './migration';
/**
* Ensures that classes that are provided as an Angular service in either `NgModule.providers` or
* `Directive.providers`/`Component.viewProviders` are decorated with one of the `@Injectable`,
* `@Directive`, `@Component` or `@Pipe` decorators, adding an `@Injectable()` decorator when none
* are present.
*
* At least one decorator is now mandatory, as otherwise the compiler would not compile an
* injectable definition for the service. This is unlike View Engine, where having just an unrelated
* decorator may have been sufficient for the service to become injectable.
*
* In essence, this migration operates on classes that are themselves an NgModule, Directive or
* Component. Their metadata is statically evaluated so that their "providers"/"viewProviders"
* properties can be analyzed. For any provider that refers to an undecorated class, the class will
* be migrated to have an `@Injectable()` decorator.
*
* This implementation mirrors the "missing-injectable" schematic.
*/
export declare class MissingInjectableMigration implements Migration {
apply(clazz: ClassDeclaration, host: MigrationHost): ts.Diagnostic | null;
}
/**
* Determines the original name of a decorator if it is from '@angular/core'. For other decorators,
* null is returned.
*/
export declare function getAngularCoreDecoratorName(decorator: Decorator): string | null;
@@ -0,0 +1,16 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/migrations/undecorated_child_migration" />
import ts from 'typescript';
import { Reference } from '../../../src/ngtsc/imports';
import { ClassDeclaration } from '../../../src/ngtsc/reflection';
import { Migration, MigrationHost } from './migration';
export declare class UndecoratedChildMigration implements Migration {
apply(clazz: ClassDeclaration, host: MigrationHost): ts.Diagnostic | null;
maybeMigrate(ref: Reference<ClassDeclaration>, host: MigrationHost): void;
}
@@ -0,0 +1,52 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/migrations/undecorated_parent_migration" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { ClassDeclaration } from '../../../src/ngtsc/reflection';
import { Migration, MigrationHost } from './migration';
/**
* Ensure that the parents of directives and components that have no constructor are also decorated
* as a `Directive`.
*
* Example:
*
* ```
* export class BasePlain {
* constructor(private vcr: ViewContainerRef) {}
* }
*
* @Directive({selector: '[blah]'})
* export class DerivedDir extends BasePlain {}
* ```
*
* When compiling `DerivedDir` which extends the undecorated `BasePlain` class, the compiler needs
* to generate a directive def (`ɵdir`) for `DerivedDir`. In particular, it needs to generate a
* factory function that creates instances of `DerivedDir`.
*
* As `DerivedDir` has no constructor, the factory function for `DerivedDir` must delegate to the
* factory function for `BasePlain`. But for this to work, `BasePlain` must have a factory function,
* itself.
*
* This migration adds a `Directive` decorator to such undecorated parent classes, to ensure that
* the compiler will create the necessary factory function.
*
* The resulting code looks like:
*
* ```
* @Directive()
* export class BasePlain {
* constructor(private vcr: ViewContainerRef) {}
* }
*
* @Directive({selector: '[blah]'})
* export class DerivedDir extends BasePlain {}
* ```
*/
export declare class UndecoratedParentMigration implements Migration {
apply(clazz: ClassDeclaration, host: MigrationHost): ts.Diagnostic | null;
}
+42
View File
@@ -0,0 +1,42 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/migrations/utils" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { ClassDeclaration, Decorator } from '../../../src/ngtsc/reflection';
import { MigrationHost } from './migration';
export declare function isClassDeclaration(clazz: ts.Node): clazz is ClassDeclaration<ts.Declaration>;
/**
* Returns true if the `clazz` is decorated as a `Directive` or `Component`.
*/
export declare function hasDirectiveDecorator(host: MigrationHost, clazz: ClassDeclaration): boolean;
/**
* Returns true if the `clazz` is decorated as a `Pipe`.
*/
export declare function hasPipeDecorator(host: MigrationHost, clazz: ClassDeclaration): boolean;
/**
* Returns true if the `clazz` has its own constructor function.
*/
export declare function hasConstructor(host: MigrationHost, clazz: ClassDeclaration): boolean;
/**
* Create an empty `Directive` decorator that will be associated with the `clazz`.
*/
export declare function createDirectiveDecorator(clazz: ClassDeclaration, metadata?: {
selector: string | null;
exportAs: string[] | null;
}): Decorator;
/**
* Create an empty `Component` decorator that will be associated with the `clazz`.
*/
export declare function createComponentDecorator(clazz: ClassDeclaration, metadata: {
selector: string | null;
exportAs: string[] | null;
}): Decorator;
/**
* Create an empty `Injectable` decorator that will be associated with the `clazz`.
*/
export declare function createInjectableDecorator(clazz: ClassDeclaration): Decorator;
+156
View File
@@ -0,0 +1,156 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/ngcc_options" />
import { AbsoluteFsPath, FileSystem } from '../../src/ngtsc/file_system';
import { Logger } from '../../src/ngtsc/logging';
import { ParsedConfiguration } from '../../src/perform_compile';
import { PathMappings } from './path_mappings';
import { FileWriter } from './writing/file_writer';
import { PackageJsonUpdater } from './writing/package_json_updater';
/**
* The options to configure the ngcc compiler for synchronous execution.
*/
export interface SyncNgccOptions {
/** The absolute path to the `node_modules` folder that contains the packages to process. */
basePath: string;
/**
* The path to the primary package to be processed. If not absolute then it must be relative to
* `basePath`.
*
* All its dependencies will need to be processed too.
*
* If this property is provided then `errorOnFailedEntryPoint` is forced to true.
*/
targetEntryPointPath?: string;
/**
* Which entry-point properties in the package.json to consider when processing an entry-point.
* Each property should hold a path to the particular bundle format for the entry-point.
* Defaults to all the properties in the package.json.
*/
propertiesToConsider?: string[];
/**
* Whether to only process the typings files for this entry-point.
*
* This is useful when running ngcc only to provide typings files to downstream tooling such as
* the Angular Language Service or ng-packagr. Defaults to `false`.
*
* If this is set to `true` then `compileAllFormats` is forced to `false`.
*/
typingsOnly?: boolean;
/**
* Whether to process all formats specified by (`propertiesToConsider`) or to stop processing
* this entry-point at the first matching format.
*
* Defaults to `true`, but is forced to `false` if `typingsOnly` is `true`.
*/
compileAllFormats?: boolean;
/**
* Whether to create new entry-points bundles rather than overwriting the original files.
*/
createNewEntryPointFormats?: boolean;
/**
* Provide a logger that will be called with log messages.
*/
logger?: Logger;
/**
* Paths mapping configuration (`paths` and `baseUrl`), as found in `ts.CompilerOptions`.
* These are used to resolve paths to locally built Angular libraries.
*
* Note that `pathMappings` specified here take precedence over any `pathMappings` loaded from a
* TS config file.
*/
pathMappings?: PathMappings;
/**
* Provide a file-system service that will be used by ngcc for all file interactions.
*/
fileSystem?: FileSystem;
/**
* Whether the compilation should run and return asynchronously. Allowing asynchronous execution
* may speed up the compilation by utilizing multiple CPU cores (if available).
*
* Default: `false` (i.e. run synchronously)
*/
async?: false;
/**
* Set to true in order to terminate immediately with an error code if an entry-point fails to be
* processed.
*
* If `targetEntryPointPath` is provided then this property is always true and cannot be
* changed. Otherwise the default is false.
*
* When set to false, ngcc will continue to process entry-points after a failure. In which case it
* will log an error and resume processing other entry-points.
*/
errorOnFailedEntryPoint?: boolean;
/**
* Render `$localize` messages with legacy format ids.
*
* The default value is `true`. Only set this to `false` if you do not want legacy message ids to
* be rendered. For example, if you are not using legacy message ids in your translation files
* AND are not doing compile-time inlining of translations, in which case the extra message ids
* would add unwanted size to the final source bundle.
*
* It is safe to leave this set to true if you are doing compile-time inlining because the extra
* legacy message ids will all be stripped during translation.
*/
enableI18nLegacyMessageIdFormat?: boolean;
/**
* Whether to invalidate any entry-point manifest file that is on disk. Instead, walk the
* directory tree looking for entry-points, and then write a new entry-point manifest, if
* possible.
*
* Default: `false` (i.e. the manifest will be used if available)
*/
invalidateEntryPointManifest?: boolean;
/**
* An absolute path to a TS config file (e.g. `tsconfig.json`) or a directory containing one, that
* will be used to configure module resolution with things like path mappings, if not specified
* explicitly via the `pathMappings` property to `mainNgcc`.
*
* If `undefined`, ngcc will attempt to load a `tsconfig.json` file from the directory above the
* `basePath`.
*
* If `null`, ngcc will not attempt to load any TS config file at all.
*/
tsConfigPath?: string | null;
/**
* Use the program defined in the loaded tsconfig.json (if available - see
* `tsConfigPath` option) to identify the entry-points that should be processed.
* If this is set to `true` then only the entry-points reachable from the given
* program (and their dependencies) will be processed.
*/
findEntryPointsFromTsConfigProgram?: boolean;
}
/**
* The options to configure the ngcc compiler for asynchronous execution.
*/
export declare type AsyncNgccOptions = Omit<SyncNgccOptions, 'async'> & {
async: true;
};
/**
* The options to configure the ngcc compiler.
*/
export declare type NgccOptions = AsyncNgccOptions | SyncNgccOptions;
export declare type OptionalNgccOptionKeys = 'targetEntryPointPath' | 'tsConfigPath' | 'pathMappings' | 'findEntryPointsFromTsConfigProgram';
export declare type RequiredNgccOptions = Required<Omit<NgccOptions, OptionalNgccOptionKeys>>;
export declare type OptionalNgccOptions = Pick<NgccOptions, OptionalNgccOptionKeys>;
export declare type SharedSetup = {
fileSystem: FileSystem;
absBasePath: AbsoluteFsPath;
projectPath: AbsoluteFsPath;
tsConfig: ParsedConfiguration | null;
getFileWriter(pkgJsonUpdater: PackageJsonUpdater): FileWriter;
};
/**
* Instantiate common utilities that are always used and fix up options with defaults, as necessary.
*
* NOTE: Avoid eagerly instantiating anything that might not be used when running sync/async.
*/
export declare function getSharedSetup(options: NgccOptions): SharedSetup & RequiredNgccOptions & OptionalNgccOptions;
export declare function clearTsConfigCache(): void;
/**
* Determines the maximum number of workers to use for parallel execution. This can be set using the
* NGCC_MAX_WORKERS environment variable, or is computed based on the number of available CPUs. One
* CPU core is always reserved for the master process, so we take the number of CPUs minus one, with
* a maximum of 4 workers. We don't scale the number of workers beyond 4 by default, as it takes
* considerably more memory and CPU cycles while not offering a substantial improvement in time.
*/
export declare function getMaxNumberOfWorkers(): number;
@@ -0,0 +1,17 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/adjust_cjs_umd_exports" />
/**
* UMD/CJS bundles generated by Rollup may be using an element access expression like
* `exports["ɵa"]` for declaring and exporting classes, instead of a property access like
* `exports.ɵa`. The element access syntax introduces a problem for ngcc, where it wouldn't consider
* such export as class declaration, causing them to be skipped. The ngtsc compiler is implemented
* with the assumption that all class declarations use a `ts.Identifier` as name, whereas the
* element access is using a string literal for the declared name. This makes it troublesome for
* ngcc to support this syntax form in UMD bundles.
*
* To work around the problem, this function transforms these access expressions into regular
* property accesses. The source text is parsed to an AST to allow finding the element accesses in a
* robust way, after which the affected text ranges are replaced with property accesses in the
* original source text. These replacement operations are faster than applying an AST transform and
* going through a `ts.Printer` to print the text back out.
*/
export declare function adjustElementAccessExports(sourceText: string): string;
+45
View File
@@ -0,0 +1,45 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/build_marker" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath } from '../../../src/ngtsc/file_system';
import { PackageJsonUpdater } from '../writing/package_json_updater';
import { EntryPointPackageJson, PackageJsonFormatProperties } from './entry_point';
export declare const NGCC_VERSION = "15.0.4";
/**
* Returns true if there is a format in this entry-point that was compiled with an outdated version
* of ngcc.
*
* @param packageJson The parsed contents of the package.json for the entry-point
*/
export declare function needsCleaning(packageJson: EntryPointPackageJson): boolean;
/**
* Clean any build marker artifacts from the given `packageJson` object.
* @param packageJson The parsed contents of the package.json to modify
* @returns true if the package was modified during cleaning
*/
export declare function cleanPackageJson(packageJson: EntryPointPackageJson): boolean;
/**
* Check whether ngcc has already processed a given entry-point format.
*
* @param packageJson The parsed contents of the package.json file for the entry-point.
* @param format The entry-point format property in the package.json to check.
* @returns true if the `format` in the entry-point has already been processed by this ngcc version,
* false otherwise.
*/
export declare function hasBeenProcessed(packageJson: EntryPointPackageJson, format: PackageJsonFormatProperties): boolean;
/**
* Write a build marker for the given entry-point and format properties, to indicate that they have
* been compiled by this version of ngcc.
*
* @param pkgJsonUpdater The writer to use for updating `package.json`.
* @param packageJson The parsed contents of the `package.json` file for the entry-point.
* @param packageJsonPath The absolute path to the `package.json` file.
* @param properties The properties in the `package.json` of the formats for which we are writing
* the marker.
*/
export declare function markAsProcessed(pkgJsonUpdater: PackageJsonUpdater, packageJson: EntryPointPackageJson, packageJsonPath: AbsoluteFsPath, formatProperties: PackageJsonFormatProperties[]): void;
+36
View File
@@ -0,0 +1,36 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/bundle_program" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
/**
* An entry point bundle contains one or two programs, e.g. `src` and `dts`,
* that are compiled via TypeScript.
*
* 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
* file, if appropriate.
*/
export interface BundleProgram {
program: ts.Program;
options: ts.CompilerOptions;
host: ts.CompilerHost;
path: AbsoluteFsPath;
file: ts.SourceFile;
package: AbsoluteFsPath;
r3SymbolsPath: AbsoluteFsPath | null;
r3SymbolsFile: ts.SourceFile | null;
}
/**
* Create a bundle program.
*/
export declare function makeBundleProgram(fs: ReadonlyFileSystem, isCore: boolean, pkg: AbsoluteFsPath, path: AbsoluteFsPath, r3FileName: string, options: ts.CompilerOptions, host: ts.CompilerHost, additionalFiles?: AbsoluteFsPath[]): BundleProgram;
/**
* Search the given directory hierarchy to find the path to the `r3_symbols` file.
*/
export declare function findR3SymbolsPath(fs: ReadonlyFileSystem, directory: AbsoluteFsPath, filename: string): AbsoluteFsPath | null;
+223
View File
@@ -0,0 +1,223 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/configuration" />
import { AbsoluteFsPath, PathManipulation, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { PackageJsonFormatPropertiesMap } from './entry_point';
/**
* The format of a project level configuration file.
*/
export interface NgccProjectConfig {
/**
* The packages that are configured by this project config.
*/
packages?: {
[packagePath: string]: RawNgccPackageConfig | undefined;
};
/**
* Options that control how locking the process is handled.
*/
locking?: ProcessLockingConfiguration;
/**
* Name of hash algorithm used to generate hashes of the configuration.
*
* Defaults to `sha256`.
*/
hashAlgorithm?: string;
}
/**
* Options that control how locking the process is handled.
*/
export interface ProcessLockingConfiguration {
/**
* The number of times the AsyncLocker will attempt to lock the process before failing.
* Defaults to 500.
*/
retryAttempts?: number;
/**
* The number of milliseconds between attempts to lock the process.
* Defaults to 500ms.
* */
retryDelay?: number;
}
/**
* The raw format of a package level configuration (as it appears in configuration files).
*/
export interface RawNgccPackageConfig {
/**
* The entry-points to configure for this package.
*
* In the config file the keys are paths relative to the package path.
*/
entryPoints?: {
[entryPointPath: string]: NgccEntryPointConfig;
};
/**
* A collection of regexes that match deep imports to ignore, for this package, rather than
* displaying a warning.
*/
ignorableDeepImportMatchers?: RegExp[];
}
/**
* Configuration options for an entry-point.
*
* The existence of a configuration for a path tells ngcc that this should be considered for
* processing as an entry-point.
*/
export interface NgccEntryPointConfig {
/** Do not process (or even acknowledge the existence of) this entry-point, if true. */
ignore?: boolean;
/**
* This property, if provided, holds values that will override equivalent properties in an
* entry-point's package.json file.
*/
override?: PackageJsonFormatPropertiesMap;
/**
* Normally, ngcc will skip compilation of entrypoints that contain imports that can't be resolved
* or understood. If this option is specified, ngcc will proceed with compiling the entrypoint
* even in the face of such missing dependencies.
*/
ignoreMissingDependencies?: boolean;
/**
* Enabling this option for an entrypoint tells ngcc that deep imports might be used for the files
* it contains, and that it should generate private re-exports alongside the NgModule of all the
* directives/pipes it makes available in support of those imports.
*/
generateDeepReexports?: boolean;
}
interface VersionedPackageConfig extends RawNgccPackageConfig {
versionRange: string;
}
/**
* The internal representation of a configuration file. Configured packages are transformed into
* `ProcessedNgccPackageConfig` when a certain version is requested.
*/
export declare class PartiallyProcessedConfig {
/**
* The packages that are configured by this project config, keyed by package name.
*/
packages: Map<string, VersionedPackageConfig[]>;
/**
* Options that control how locking the process is handled.
*/
locking: ProcessLockingConfiguration;
/**
* Name of hash algorithm used to generate hashes of the configuration.
*
* Defaults to `sha256`.
*/
hashAlgorithm: string;
constructor(projectConfig: NgccProjectConfig);
private splitNameAndVersion;
/**
* Registers the configuration for a particular version of the provided package.
*/
private addPackageConfig;
/**
* Finds the configuration for a particular version of the provided package.
*/
findPackageConfig(packageName: string, version: string | null): VersionedPackageConfig | null;
/**
* Converts the configuration into a JSON representation that is used to compute a hash of the
* configuration.
*/
toJson(): string;
}
/**
* The default configuration for ngcc.
*
* This is the ultimate fallback configuration that ngcc will use if there is no configuration
* for a package at the package level or project level.
*
* This configuration is for packages that are "dead" - i.e. no longer maintained and so are
* unlikely to be fixed to work with ngcc, nor provide a package level config of their own.
*
* The fallback process for looking up configuration is:
*
* Project -> Package -> Default
*
* If a package provides its own configuration then that would override this default one.
*
* Also application developers can always provide configuration at their project level which
* will override everything else.
*
* Note that the fallback is package based not entry-point based.
* For example, if a there is configuration for a package at the project level this will replace all
* entry-point configurations that may have been provided in the package level or default level
* configurations, even if the project level configuration does not provide for a given entry-point.
*/
export declare const DEFAULT_NGCC_CONFIG: NgccProjectConfig;
/**
* The processed package level configuration as a result of processing a raw package level config.
*/
export declare class ProcessedNgccPackageConfig implements Omit<RawNgccPackageConfig, 'entryPoints'> {
/**
* The absolute path to this instance of the package.
* Note that there may be multiple instances of a package inside a project in nested
* `node_modules/`. For example, one at `<project-root>/node_modules/some-package/` and one at
* `<project-root>/node_modules/other-package/node_modules/some-package/`.
*/
packagePath: AbsoluteFsPath;
/**
* The entry-points to configure for this package.
*
* In contrast to `RawNgccPackageConfig`, the paths are absolute and take the path of the specific
* instance of the package into account.
*/
entryPoints: Map<AbsoluteFsPath, NgccEntryPointConfig>;
/**
* A collection of regexes that match deep imports to ignore, for this package, rather than
* displaying a warning.
*/
ignorableDeepImportMatchers: RegExp[];
constructor(fs: PathManipulation, packagePath: AbsoluteFsPath, { entryPoints, ignorableDeepImportMatchers, }: RawNgccPackageConfig);
}
/**
* Ngcc has a hierarchical configuration system that lets us "fix up" packages that do not
* work with ngcc out of the box.
*
* There are three levels at which configuration can be declared:
*
* * Default level - ngcc comes with built-in configuration for well known cases.
* * Package level - a library author publishes a configuration with their package to fix known
* issues.
* * Project level - the application developer provides a configuration that fixes issues specific
* to the libraries used in their application.
*
* Ngcc will match configuration based on the package name but also on its version. This allows
* configuration to provide different fixes to different version ranges of a package.
*
* * Package level configuration is specific to the package version where the configuration is
* found.
* * Default and project level configuration should provide version ranges to ensure that the
* configuration is only applied to the appropriate versions of a package.
*
* When getting a configuration for a package (via `getConfig()`) the caller should provide the
* version of the package in question, if available. If it is not provided then the first available
* configuration for a package is returned.
*/
export declare class NgccConfiguration {
private fs;
private defaultConfig;
private projectConfig;
private cache;
readonly hash: string;
readonly hashAlgorithm: string;
constructor(fs: ReadonlyFileSystem, baseDir: AbsoluteFsPath);
/**
* Get the configuration options for locking the ngcc process.
*/
getLockingConfig(): Required<ProcessLockingConfiguration>;
/**
* Get a configuration for the given `version` of a package at `packagePath`.
*
* @param packageName The name of the package whose config we want.
* @param packagePath The path to the package whose config we want.
* @param version The version of the package whose config we want, or `null` if the package's
* package.json did not exist or was invalid.
*/
getPackageConfig(packageName: string, packagePath: AbsoluteFsPath, version: string | null): ProcessedNgccPackageConfig;
private getRawPackageConfig;
private loadProjectConfig;
private loadPackageConfig;
private evalSrcFile;
private computeHash;
}
export {};
+110
View File
@@ -0,0 +1,110 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/entry_point" />
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { JsonObject } from '../utils';
import { NgccConfiguration } from './configuration';
/**
* The possible values for the format of an entry-point.
*/
export declare type EntryPointFormat = 'esm5' | 'esm2015' | 'umd' | 'commonjs';
/**
* An object containing information about an entry-point, including paths
* to each of the possible entry-point formats.
*/
export interface EntryPoint extends JsonObject {
/** The name of the entry-point (e.g. `@angular/core` or `@angular/common/http`). */
name: string;
/** The path to this entry point. */
path: AbsoluteFsPath;
/**
* The name of the package that contains this entry-point (e.g. `@angular/core` or
* `@angular/common`).
*/
packageName: string;
/** The path to the package that contains this entry-point. */
packagePath: AbsoluteFsPath;
/** The URL of the repository. */
repositoryUrl: string;
/** The parsed package.json file for this entry-point. */
packageJson: EntryPointPackageJson;
/** The path to a typings (.d.ts) file for this entry-point. */
typings: AbsoluteFsPath;
/** Is this EntryPoint compiled with the Angular View Engine compiler? */
compiledByAngular: boolean;
/** Should ngcc ignore missing dependencies and process this entrypoint anyway? */
ignoreMissingDependencies: boolean;
/** Should ngcc generate deep re-exports for this entrypoint? */
generateDeepReexports: boolean;
}
export interface PackageJsonFormatPropertiesMap {
browser?: string;
fesm2015?: string;
fesm5?: string;
es2015?: string;
esm2015?: string;
esm5?: string;
main?: string;
module?: string;
types?: string;
typings?: string;
}
export declare type PackageJsonFormatProperties = keyof PackageJsonFormatPropertiesMap;
/**
* The properties that may be loaded from the `package.json` file.
*/
export interface EntryPointPackageJson extends JsonObject, PackageJsonFormatPropertiesMap {
name: string;
version?: string;
scripts?: Record<string, string>;
repository?: string | {
url: string;
};
__processed_by_ivy_ngcc__?: Record<string, string>;
}
export declare type EntryPointJsonProperty = Exclude<PackageJsonFormatProperties, 'types' | 'typings'>;
export declare const SUPPORTED_FORMAT_PROPERTIES: EntryPointJsonProperty[];
/**
* The path does not represent an entry-point, i.e. there is no package.json at the path and there
* is no config to force an entry-point.
*/
export declare const NO_ENTRY_POINT = "no-entry-point";
/**
* The path represents an entry-point that is `ignored` by an ngcc config.
*/
export declare const IGNORED_ENTRY_POINT = "ignored-entry-point";
/**
* The path has a package.json, but it is not a valid entry-point for ngcc processing.
*/
export declare const INCOMPATIBLE_ENTRY_POINT = "incompatible-entry-point";
/**
* The result of calling `getEntryPointInfo()`.
*
* This will be an `EntryPoint` object if an Angular entry-point was identified;
* Otherwise it will be a flag indicating one of:
* * NO_ENTRY_POINT - the path is not an entry-point or ngcc is configured to ignore it
* * INCOMPATIBLE_ENTRY_POINT - the path was a non-processable entry-point that should be searched
* for sub-entry-points
*/
export declare type GetEntryPointResult = EntryPoint | typeof IGNORED_ENTRY_POINT | typeof INCOMPATIBLE_ENTRY_POINT | typeof NO_ENTRY_POINT;
/**
* Try to create an entry-point from the given paths and properties.
*
* @param packagePath the absolute path to the containing npm package
* @param entryPointPath the absolute path to the potential entry-point.
* @returns
* - An entry-point if it is valid and not ignored.
* - `NO_ENTRY_POINT` when there is no package.json at the path and there is no config to force an
* entry-point,
* - `IGNORED_ENTRY_POINT` when the entry-point is ignored by an ngcc config.
* - `INCOMPATIBLE_ENTRY_POINT` when there is a package.json but it is not a valid Angular compiled
* entry-point.
*/
export declare function getEntryPointInfo(fs: ReadonlyFileSystem, config: NgccConfiguration, logger: Logger, packagePath: AbsoluteFsPath, entryPointPath: AbsoluteFsPath): GetEntryPointResult;
export declare function isEntryPoint(result: GetEntryPointResult): result is EntryPoint;
/**
* Convert a package.json property into an entry-point format.
*
* @param property The property to convert to a format.
* @returns An entry-point format or `undefined` if none match the given property.
*/
export declare function getEntryPointFormat(fs: ReadonlyFileSystem, entryPoint: EntryPoint, property: EntryPointJsonProperty): EntryPointFormat | undefined;
+47
View File
@@ -0,0 +1,47 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/entry_point_bundle" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { AbsoluteFsPath, FileSystem } from '../../../src/ngtsc/file_system';
import { DtsProcessing } from '../execution/tasks/api';
import { PathMappings } from '../path_mappings';
import { BundleProgram } from './bundle_program';
import { EntryPoint, EntryPointFormat } from './entry_point';
import { SharedFileCache } from './source_file_cache';
/**
* A bundle of files and paths (and TS programs) that correspond to a particular
* format of a package entry-point.
*/
export interface EntryPointBundle {
entryPoint: EntryPoint;
format: EntryPointFormat;
isCore: boolean;
isFlatCore: boolean;
rootDirs: AbsoluteFsPath[];
src: BundleProgram;
dts: BundleProgram | null;
dtsProcessing: DtsProcessing;
enableI18nLegacyMessageIdFormat: boolean;
}
/**
* Get an object that describes a formatted bundle for an entry-point.
* @param fs The current file-system being used.
* @param entryPoint The entry-point that contains the bundle.
* @param sharedFileCache The cache to use for source files that are shared across all entry-points.
* @param moduleResolutionCache The module resolution cache to use.
* @param formatPath The path to the source files for this bundle.
* @param isCore This entry point is the Angular core package.
* @param format The underlying format of the bundle.
* @param dtsProcessing Whether to transform the typings along with this bundle.
* @param pathMappings An optional set of mappings to use when compiling files.
* @param mirrorDtsFromSrc If true then the `dts` program will contain additional files that
* were guessed by mapping the `src` files to `dts` files.
* @param enableI18nLegacyMessageIdFormat Whether to render legacy message ids for i18n messages in
* component templates.
*/
export declare function makeEntryPointBundle(fs: FileSystem, entryPoint: EntryPoint, sharedFileCache: SharedFileCache, moduleResolutionCache: ts.ModuleResolutionCache, formatPath: string, isCore: boolean, format: EntryPointFormat, dtsProcessing: DtsProcessing, pathMappings?: PathMappings, mirrorDtsFromSrc?: boolean, enableI18nLegacyMessageIdFormat?: boolean): EntryPointBundle;
@@ -0,0 +1,80 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/entry_point_manifest" />
import { AbsoluteFsPath, FileSystem, PathSegment } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { EntryPointWithDependencies } from '../dependencies/dependency_host';
import { NgccConfiguration } from './configuration';
import { PackageJsonFormatProperties } from './entry_point';
/**
* Manages reading and writing a manifest file that contains a list of all the entry-points that
* were found below a given basePath.
*
* This is a super-set of the entry-points that are actually processed for a given run of ngcc,
* since some may already be processed, or excluded if they do not have the required format.
*/
export declare class EntryPointManifest {
private fs;
private config;
private logger;
constructor(fs: FileSystem, config: NgccConfiguration, logger: Logger);
/**
* Try to get the entry-point info from a manifest file for the given `basePath` if it exists and
* is not out of date.
*
* Reasons for the manifest to be out of date are:
*
* * the file does not exist
* * the ngcc version has changed
* * the package lock-file (i.e. yarn.lock or package-lock.json) has changed
* * the project configuration has changed
* * one or more entry-points in the manifest are not valid
*
* @param basePath The path that would contain the entry-points and the manifest file.
* @returns an array of entry-point information for all entry-points found below the given
* `basePath` or `null` if the manifest was out of date.
*/
readEntryPointsUsingManifest(basePath: AbsoluteFsPath): EntryPointWithDependencies[] | null;
/**
* Write a manifest file at the given `basePath`.
*
* The manifest includes the current ngcc version and hashes of the package lock-file and current
* project config. These will be used to check whether the manifest file is out of date. See
* `readEntryPointsUsingManifest()`.
*
* @param basePath The path where the manifest file is to be written.
* @param entryPoints A collection of entry-points to record in the manifest.
*/
writeEntryPointManifest(basePath: AbsoluteFsPath, entryPoints: EntryPointWithDependencies[]): void;
private getEntryPointManifestPath;
private computeLockFileHash;
}
/**
* A specialized implementation of the `EntryPointManifest` that can be used to invalidate the
* current manifest file.
*
* It always returns `null` from the `readEntryPointsUsingManifest()` method, which forces a new
* manifest to be created, which will overwrite the current file when `writeEntryPointManifest()`
* is called.
*/
export declare class InvalidatingEntryPointManifest extends EntryPointManifest {
readEntryPointsUsingManifest(_basePath: AbsoluteFsPath): EntryPointWithDependencies[] | null;
}
export declare type EntryPointPaths = [
string,
string,
Array<AbsoluteFsPath>?,
Array<AbsoluteFsPath | PathSegment>?,
Array<AbsoluteFsPath>?
];
/**
* The JSON format of the manifest file that is written to disk.
*/
export interface EntryPointManifestFile {
ngccVersion: string;
configFileHash: string;
lockFileHash: string;
entryPointPaths: EntryPointPaths[];
}
/** The JSON format of the entrypoint properties. */
export declare type NewEntryPointPropertiesMap = {
[Property in PackageJsonFormatProperties as `${Property}_ivy_ngcc`]?: string;
};
+37
View File
@@ -0,0 +1,37 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/ngcc_compiler_host" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { AbsoluteFsPath, FileSystem, NgtscCompilerHost } from '../../../src/ngtsc/file_system';
import { EntryPointFileCache } from './source_file_cache';
/**
* Represents a compiler host that resolves a module import as a JavaScript source file if
* available, instead of the .d.ts typings file that would have been resolved by TypeScript. This
* is necessary for packages that have their typings in the same directory as the sources, which
* would otherwise let TypeScript prefer the .d.ts file instead of the JavaScript source file.
*/
export declare class NgccSourcesCompilerHost extends NgtscCompilerHost {
private cache;
private moduleResolutionCache;
protected packagePath: AbsoluteFsPath;
constructor(fs: FileSystem, options: ts.CompilerOptions, cache: EntryPointFileCache, moduleResolutionCache: ts.ModuleResolutionCache, packagePath: AbsoluteFsPath);
getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile | undefined;
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ts.ResolvedProjectReference): Array<ts.ResolvedModule | undefined>;
}
/**
* A compiler host implementation that is used for the typings program. It leverages the entry-point
* cache for source files and module resolution, as these results can be reused across the sources
* program.
*/
export declare class NgccDtsCompilerHost extends NgtscCompilerHost {
private cache;
private moduleResolutionCache;
constructor(fs: FileSystem, options: ts.CompilerOptions, cache: EntryPointFileCache, moduleResolutionCache: ts.ModuleResolutionCache);
getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile | undefined;
resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ts.ResolvedProjectReference): Array<ts.ResolvedModule | undefined>;
}
@@ -0,0 +1,42 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/patch_ts_expando_initializer" />
/**
* Consider the following ES5 code that may have been generated for a class:
*
* ```
* var A = (function(){
* function A() {}
* return A;
* }());
* A.staticProp = true;
* ```
*
* Here, TypeScript marks the symbol for "A" as a so-called "expando symbol", which causes
* "staticProp" to be added as an export of the "A" symbol.
*
* In the example above, symbol "A" has been assigned some flags to indicate that it represents a
* class. Due to this flag, the symbol is considered an expando symbol and as such, "staticProp" is
* stored in `ts.Symbol.exports`.
*
* A problem arises when "A" is not at the top-level, i.e. in UMD bundles. In that case, the symbol
* does not have the flag that marks the symbol as a class. Therefore, TypeScript inspects "A"'s
* initializer expression, which is an IIFE in the above example. Unfortunately however, only IIFEs
* of the form `(function(){})()` qualify as initializer for an "expando symbol"; the slightly
* different form seen in the example above, `(function(){}())`, does not. This prevents the "A"
* symbol from being considered an expando symbol, in turn preventing "staticProp" from being stored
* in `ts.Symbol.exports`.
*
* The logic for identifying symbols as "expando symbols" can be found here:
* https://github.com/microsoft/TypeScript/blob/v3.4.5/src/compiler/binder.ts#L2656-L2685
*
* Notice how the `getExpandoInitializer` function is available on the "ts" namespace in the
* compiled bundle, so we are able to override this function to accommodate for the alternative
* IIFE notation. The original implementation can be found at:
* https://github.com/Microsoft/TypeScript/blob/v3.4.5/src/compiler/utilities.ts#L1864-L1887
*
* Issue tracked in https://github.com/microsoft/TypeScript/issues/31778
*
* @returns the function to pass to `restoreGetExpandoInitializer` to undo the patch, or null if
* the issue is known to have been fixed.
*/
export declare function patchTsGetExpandoInitializer(): unknown;
export declare function restoreGetExpandoInitializer(originalGetExpandoInitializer: unknown): void;
+98
View File
@@ -0,0 +1,98 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/source_file_cache" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
/**
* A cache that holds on to source files that can be shared for processing all entry-points in a
* single invocation of ngcc. In particular, the following files are shared across all entry-points
* through this cache:
*
* 1. Default library files such as `lib.dom.d.ts` and `lib.es5.d.ts`. These files don't change
* and some are very large, so parsing is expensive. Therefore, the parsed `ts.SourceFile`s for
* the default library files are cached.
* 2. The typings of @angular scoped packages. The typing files for @angular packages are typically
* used in the entry-points that ngcc processes, so benefit from a single source file cache.
* Especially `@angular/core/core.d.ts` is large and expensive to parse repeatedly. In contrast
* to default library files, we have to account for these files to be invalidated during a single
* invocation of ngcc, as ngcc will overwrite the .d.ts files during its processing.
*
* The lifecycle of this cache corresponds with a single invocation of ngcc. Separate invocations,
* e.g. the CLI's synchronous module resolution fallback will therefore all have their own cache.
* This allows for the source file cache to be garbage collected once ngcc processing has completed.
*/
export declare class SharedFileCache {
private fs;
private sfCache;
constructor(fs: ReadonlyFileSystem);
/**
* Loads a `ts.SourceFile` if the provided `fileName` is deemed appropriate to be cached. To
* optimize for memory usage, only files that are generally used in all entry-points are cached.
* If `fileName` is not considered to benefit from caching or the requested file does not exist,
* then `undefined` is returned.
*/
getCachedSourceFile(fileName: string): ts.SourceFile | undefined;
/**
* Attempts to load the source file from the cache, or parses the file into a `ts.SourceFile` if
* it's not yet cached. This method assumes that the file will not be modified for the duration
* that this cache is valid for. If that assumption does not hold, the `getVolatileCachedFile`
* method is to be used instead.
*/
private getStableCachedFile;
/**
* In contrast to `getStableCachedFile`, this method always verifies that the cached source file
* is the same as what's stored on disk. This is done for files that are expected to change during
* ngcc's processing, such as @angular scoped packages for which the .d.ts files are overwritten
* by ngcc. If the contents on disk have changed compared to a previously cached source file, the
* content from disk is re-parsed and the cache entry is replaced.
*/
private getVolatileCachedFile;
}
/**
* Determines whether the provided path corresponds with a default library file inside of the
* typescript package.
*
* @param absPath The path for which to determine if it corresponds with a default library file.
* @param fs The filesystem to use for inspecting the path.
*/
export declare function isDefaultLibrary(absPath: AbsoluteFsPath, fs: ReadonlyFileSystem): boolean;
/**
* Determines whether the provided path corresponds with a .d.ts file inside of an @angular
* scoped package. This logic only accounts for the .d.ts files in the root, which is sufficient
* to find the large, flattened entry-point files that benefit from caching.
*
* @param absPath The path for which to determine if it corresponds with an @angular .d.ts file.
* @param fs The filesystem to use for inspecting the path.
*/
export declare function isAngularDts(absPath: AbsoluteFsPath, fs: ReadonlyFileSystem): boolean;
/**
* A cache for processing a single entry-point. This exists to share `ts.SourceFile`s between the
* source and typing programs that are created for a single program.
*/
export declare class EntryPointFileCache {
private fs;
private sharedFileCache;
private processSourceText;
private readonly sfCache;
constructor(fs: ReadonlyFileSystem, sharedFileCache: SharedFileCache, processSourceText: (sourceText: string) => string);
/**
* Returns and caches a parsed `ts.SourceFile` for the provided `fileName`. If the `fileName` is
* cached in the shared file cache, that result is used. Otherwise, the source file is cached
* internally. This method returns `undefined` if the requested file does not exist.
*
* @param fileName The path of the file to retrieve a source file for.
* @param languageVersion The language version to use for parsing the file.
*/
getCachedSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile | undefined;
}
/**
* Creates a `ts.ModuleResolutionCache` that uses the provided filesystem for path operations.
*
* @param fs The filesystem to use for path operations.
*/
export declare function createModuleResolutionCache(fs: ReadonlyFileSystem): ts.ModuleResolutionCache;
+71
View File
@@ -0,0 +1,71 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/packages/transformer" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { ParsedConfiguration } from '../../..';
import { ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { ModuleWithProvidersAnalyses } from '../analysis/module_with_providers_analyzer';
import { ExportInfo } from '../analysis/private_declarations_analyzer';
import { CompiledFile } from '../analysis/types';
import { NgccReflectionHost } from '../host/ngcc_host';
import { RenderingFormatter } from '../rendering/rendering_formatter';
import { FileToWrite } from '../rendering/utils';
import { EntryPointBundle } from './entry_point_bundle';
export declare type TransformResult = {
success: true;
diagnostics: ts.Diagnostic[];
transformedFiles: FileToWrite[];
} | {
success: false;
diagnostics: ts.Diagnostic[];
};
/**
* A Package is stored in a directory on disk and that directory can contain one or more package
* formats - e.g. fesm2015, UMD, etc. Additionally, each package provides typings (`.d.ts` files).
*
* Each of these formats exposes one or more entry points, which are source files that need to be
* parsed to identify the decorated exported classes that need to be analyzed and compiled by one or
* more `DecoratorHandler` objects.
*
* Each entry point to a package is identified by a `package.json` which contains properties that
* indicate what formatted bundles are accessible via this end-point.
*
* Each bundle is identified by a root `SourceFile` that can be parsed and analyzed to
* identify classes that need to be transformed; and then finally rendered and written to disk.
*
* Along with the source files, the corresponding source maps (either inline or external) and
* `.d.ts` files are transformed accordingly.
*
* - Flat file packages have all the classes in a single file.
* - Other packages may re-export classes from other non-entry point files.
* - Some formats may contain multiple "modules" in a single file.
*/
export declare class Transformer {
private fs;
private logger;
private tsConfig;
constructor(fs: ReadonlyFileSystem, logger: Logger, tsConfig?: ParsedConfiguration | null);
/**
* Transform the source (and typings) files of a bundle.
* @param bundle the bundle to transform.
* @returns information about the files that were transformed.
*/
transform(bundle: EntryPointBundle): TransformResult;
getHost(bundle: EntryPointBundle): NgccReflectionHost;
getRenderingFormatter(host: NgccReflectionHost, bundle: EntryPointBundle): RenderingFormatter;
analyzeProgram(reflectionHost: NgccReflectionHost, bundle: EntryPointBundle): ProgramAnalyses;
}
export declare function hasErrors(diagnostics: ts.Diagnostic[]): boolean;
interface ProgramAnalyses {
decorationAnalyses: Map<ts.SourceFile, CompiledFile>;
privateDeclarationsAnalyses: ExportInfo[];
moduleWithProvidersAnalyses: ModuleWithProvidersAnalyses | null;
diagnostics: ts.Diagnostic[];
}
export {};
+20
View File
@@ -0,0 +1,20 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/path_mappings" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, PathManipulation } from '../../src/ngtsc/file_system';
import { ParsedConfiguration } from '../../src/perform_compile';
export declare type PathMappings = {
baseUrl: string;
paths: {
[key: string]: string[];
};
};
/**
* If `pathMappings` is not provided directly, then try getting it from `tsConfig`, if available.
*/
export declare function getPathMappingsFromTsConfig(fs: PathManipulation, tsConfig: ParsedConfiguration | null, projectPath: AbsoluteFsPath): PathMappings | undefined;
@@ -0,0 +1,35 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/rendering/commonjs_rendering_formatter" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import MagicString from 'magic-string';
import ts from 'typescript';
import { PathManipulation } from '../../../src/ngtsc/file_system';
import { Reexport } from '../../../src/ngtsc/imports';
import { Import, ImportManager } from '../../../src/ngtsc/translator';
import { ExportInfo } from '../analysis/private_declarations_analyzer';
import { NgccReflectionHost } from '../host/ngcc_host';
import { Esm5RenderingFormatter } from './esm5_rendering_formatter';
/**
* A RenderingFormatter that works with CommonJS files, instead of `import` and `export` statements
* the module is an IIFE with a factory function call with dependencies, which are defined in a
* wrapper function for AMD, CommonJS and global module formats.
*/
export declare class CommonJsRenderingFormatter extends Esm5RenderingFormatter {
protected commonJsHost: NgccReflectionHost;
constructor(fs: PathManipulation, commonJsHost: NgccReflectionHost, isCore: boolean);
/**
* Add the imports below any in situ imports as `require` calls.
*/
addImports(output: MagicString, imports: Import[], file: ts.SourceFile): void;
/**
* Add the exports to the bottom of the file.
*/
addExports(output: MagicString, entryPointBasePath: string, exports: ExportInfo[], importManager: ImportManager, file: ts.SourceFile): void;
addDirectExports(output: MagicString, exports: Reexport[], importManager: ImportManager, file: ts.SourceFile): void;
protected findEndOfImports(sf: ts.SourceFile): number;
}
+52
View File
@@ -0,0 +1,52 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/rendering/dts_renderer" />
import ts from 'typescript';
import { ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { Reexport } from '../../../src/ngtsc/imports';
import { Logger } from '../../../src/ngtsc/logging';
import { CompileResult } from '../../../src/ngtsc/transform';
import { ModuleWithProvidersAnalyses, ModuleWithProvidersInfo } from '../analysis/module_with_providers_analyzer';
import { ExportInfo, PrivateDeclarationsAnalyses } from '../analysis/private_declarations_analyzer';
import { DecorationAnalyses } from '../analysis/types';
import { NgccReflectionHost } from '../host/ngcc_host';
import { EntryPointBundle } from '../packages/entry_point_bundle';
import { RenderingFormatter } from './rendering_formatter';
import { FileToWrite } from './utils';
/**
* A structure that captures information about what needs to be rendered
* in a typings file.
*
* It is created as a result of processing the analysis passed to the renderer.
*
* The `renderDtsFile()` method consumes it when rendering a typings file.
*/
declare class DtsRenderInfo {
classInfo: DtsClassInfo[];
moduleWithProviders: ModuleWithProvidersInfo[];
privateExports: ExportInfo[];
reexports: Reexport[];
}
/**
* Information about a class in a typings file.
*/
export interface DtsClassInfo {
dtsDeclaration: ts.Declaration;
compilation: CompileResult[];
}
/**
* A base-class for rendering an `AnalyzedFile`.
*
* Package formats have output files that must be rendered differently. Concrete sub-classes must
* implement the `addImports`, `addDefinitions` and `removeDecorators` abstract methods.
*/
export declare class DtsRenderer {
private dtsFormatter;
private fs;
private logger;
private host;
private bundle;
constructor(dtsFormatter: RenderingFormatter, fs: ReadonlyFileSystem, logger: Logger, host: NgccReflectionHost, bundle: EntryPointBundle);
renderProgram(decorationAnalyses: DecorationAnalyses, privateDeclarationsAnalyses: PrivateDeclarationsAnalyses, moduleWithProvidersAnalyses: ModuleWithProvidersAnalyses | null): FileToWrite[];
renderDtsFile(dtsFile: ts.SourceFile, renderInfo: DtsRenderInfo): FileToWrite[];
private getTypingsFilesToRender;
}
export {};
@@ -0,0 +1,36 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/rendering/esm5_rendering_formatter" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { Statement } from '@angular/compiler';
import MagicString from 'magic-string';
import ts from 'typescript';
import { ImportManager } from '../../../src/ngtsc/translator';
import { CompiledClass } from '../analysis/types';
import { EsmRenderingFormatter } from './esm_rendering_formatter';
/**
* A RenderingFormatter that works with files that use ECMAScript Module `import` and `export`
* statements, but instead of `class` declarations it uses ES5 `function` wrappers for classes.
*/
export declare class Esm5RenderingFormatter extends EsmRenderingFormatter {
/**
* Add the definitions, directly before the return statement, inside the IIFE of each decorated
* class.
*/
addDefinitions(output: MagicString, compiledClass: CompiledClass, definitions: string): void;
/**
* Convert a `Statement` to JavaScript code in a format suitable for rendering by this formatter.
*
* @param stmt The `Statement` to print.
* @param sourceFile A `ts.SourceFile` that provides context for the statement. See
* `ts.Printer#printNode()` for more info.
* @param importManager The `ImportManager` to use for managing imports.
*
* @return The JavaScript code corresponding to `stmt` (in the appropriate format).
*/
printStatement(stmt: Statement, sourceFile: ts.SourceFile, importManager: ImportManager): string;
}
@@ -0,0 +1,85 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/rendering/esm_rendering_formatter" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { Statement } from '@angular/compiler';
import MagicString from 'magic-string';
import ts from 'typescript';
import { AbsoluteFsPath, PathManipulation } from '../../../src/ngtsc/file_system';
import { Reexport } from '../../../src/ngtsc/imports';
import { Import, ImportManager } from '../../../src/ngtsc/translator';
import { ModuleWithProvidersInfo } from '../analysis/module_with_providers_analyzer';
import { ExportInfo } from '../analysis/private_declarations_analyzer';
import { CompiledClass } from '../analysis/types';
import { NgccReflectionHost } from '../host/ngcc_host';
import { RedundantDecoratorMap, RenderingFormatter } from './rendering_formatter';
/**
* A RenderingFormatter that works with ECMAScript Module import and export statements.
*/
export declare class EsmRenderingFormatter implements RenderingFormatter {
protected fs: PathManipulation;
protected host: NgccReflectionHost;
protected isCore: boolean;
protected printer: ts.Printer;
constructor(fs: PathManipulation, host: NgccReflectionHost, isCore: boolean);
/**
* Add the imports at the top of the file, after any imports that are already there.
*/
addImports(output: MagicString, imports: Import[], sf: ts.SourceFile): void;
/**
* Add the exports to the end of the file.
*/
addExports(output: MagicString, entryPointBasePath: AbsoluteFsPath, exports: ExportInfo[], importManager: ImportManager, file: ts.SourceFile): void;
/**
* Add plain exports to the end of the file.
*
* Unlike `addExports`, direct exports go directly in a .js and .d.ts file and don't get added to
* an entrypoint.
*/
addDirectExports(output: MagicString, exports: Reexport[], importManager: ImportManager, file: ts.SourceFile): void;
/**
* Add the constants directly after the imports.
*/
addConstants(output: MagicString, constants: string, file: ts.SourceFile): void;
/**
* Add the definitions directly after their decorated class.
*/
addDefinitions(output: MagicString, compiledClass: CompiledClass, definitions: string): void;
/**
* Add the adjacent statements after all static properties of the class.
*/
addAdjacentStatements(output: MagicString, compiledClass: CompiledClass, statements: string): void;
/**
* Remove static decorator properties from classes.
*/
removeDecorators(output: MagicString, decoratorsToRemove: RedundantDecoratorMap): void;
/**
* Add the type parameters to the appropriate functions that return `ModuleWithProviders`
* structures.
*
* This function will only get called on typings files.
*/
addModuleWithProvidersParams(outputText: MagicString, moduleWithProviders: ModuleWithProvidersInfo[], importManager: ImportManager): void;
/**
* Convert a `Statement` to JavaScript code in a format suitable for rendering by this formatter.
*
* @param stmt The `Statement` to print.
* @param sourceFile A `ts.SourceFile` that provides context for the statement. See
* `ts.Printer#printNode()` for more info.
* @param importManager The `ImportManager` to use for managing imports.
*
* @return The JavaScript code corresponding to `stmt` (in the appropriate format).
*/
printStatement(stmt: Statement, sourceFile: ts.SourceFile, importManager: ImportManager): string;
protected findEndOfImports(sf: ts.SourceFile): number;
/**
* Check whether the given type is the core Angular `ModuleWithProviders` interface.
* @param typeName The type to check.
* @returns true if the type is the core Angular `ModuleWithProviders` interface.
*/
private isCoreModuleWithProvidersType;
}
@@ -0,0 +1,14 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/rendering/ngcc_import_rewriter" />
import { ImportRewriter } from '../../../src/ngtsc/imports';
export declare class NgccFlatImportRewriter implements ImportRewriter {
shouldImportSymbol(symbol: string, specifier: string): boolean;
rewriteSymbol(symbol: string, specifier: string): string;
rewriteSpecifier(originalModulePath: string, inContextOfFile: string): string;
}
+73
View File
@@ -0,0 +1,73 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/rendering/renderer" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { ConstantPool } from '@angular/compiler';
import ts from 'typescript';
import { ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { ImportManager } from '../../../src/ngtsc/translator';
import { ParsedConfiguration } from '../../../src/perform_compile';
import { PrivateDeclarationsAnalyses } from '../analysis/private_declarations_analyzer';
import { CompiledFile, DecorationAnalyses } from '../analysis/types';
import { NgccReflectionHost } from '../host/ngcc_host';
import { EntryPointBundle } from '../packages/entry_point_bundle';
import { RenderingFormatter } from './rendering_formatter';
import { FileToWrite } from './utils';
/**
* A base-class for rendering an `AnalyzedFile`.
*
* Package formats have output files that must be rendered differently. Concrete sub-classes must
* implement the `addImports`, `addDefinitions` and `removeDecorators` abstract methods.
*/
export declare class Renderer {
private host;
private srcFormatter;
private fs;
private logger;
private bundle;
private tsConfig;
constructor(host: NgccReflectionHost, srcFormatter: RenderingFormatter, fs: ReadonlyFileSystem, logger: Logger, bundle: EntryPointBundle, tsConfig?: ParsedConfiguration | null);
renderProgram(decorationAnalyses: DecorationAnalyses, privateDeclarationsAnalyses: PrivateDeclarationsAnalyses): FileToWrite[];
/**
* Render the source code and source-map for an Analyzed file.
* @param compiledFile The analyzed file to render.
* @param targetPath The absolute path where the rendered file will be written.
*/
renderFile(sourceFile: ts.SourceFile, compiledFile: CompiledFile | undefined, privateDeclarationsAnalyses: PrivateDeclarationsAnalyses): FileToWrite[];
/**
* From the given list of classes, computes a map of decorators that should be removed.
* The decorators to remove are keyed by their container node, such that we can tell if
* we should remove the entire decorator property.
* @param classes The list of classes that may have decorators to remove.
* @returns A map of decorators to remove, keyed by their container node.
*/
private computeDecoratorsToRemove;
/**
* Render the definitions as source code for the given class.
* @param sourceFile The file containing the class to process.
* @param clazz The class whose definitions are to be rendered.
* @param compilation The results of analyzing the class - this is used to generate the rendered
* definitions.
* @param imports An object that tracks the imports that are needed by the rendered definitions.
*/
private renderDefinitions;
/**
* Render the adjacent statements as source code for the given class.
* @param sourceFile The file containing the class to process.
* @param clazz The class whose statements are to be rendered.
* @param compilation The results of analyzing the class - this is used to generate the rendered
* definitions.
* @param imports An object that tracks the imports that are needed by the rendered definitions.
*/
private renderAdjacentStatements;
private renderStatements;
}
/**
* Render the constant pool as source code for the given class.
*/
export declare function renderConstantPool(formatter: RenderingFormatter, sourceFile: ts.SourceFile, constantPool: ConstantPool, imports: ImportManager): string;
@@ -0,0 +1,38 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/rendering/rendering_formatter" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { Statement } from '@angular/compiler';
import MagicString from 'magic-string';
import ts from 'typescript';
import { Reexport } from '../../../src/ngtsc/imports';
import { Import, ImportManager } from '../../../src/ngtsc/translator';
import { ModuleWithProvidersInfo } from '../analysis/module_with_providers_analyzer';
import { ExportInfo } from '../analysis/private_declarations_analyzer';
import { CompiledClass } from '../analysis/types';
/**
* The collected decorators that have become redundant after the compilation
* of Ivy static fields. The map is keyed by the container node, such that we
* can tell if we should remove the entire decorator property
*/
export declare type RedundantDecoratorMap = Map<ts.Node, ts.Node[]>;
export declare const RedundantDecoratorMap: MapConstructor;
/**
* Implement this interface with methods that know how to render a specific format,
* such as ESM5 or UMD.
*/
export interface RenderingFormatter {
addConstants(output: MagicString, constants: string, file: ts.SourceFile): void;
addImports(output: MagicString, imports: Import[], sf: ts.SourceFile): void;
addExports(output: MagicString, entryPointBasePath: string, exports: ExportInfo[], importManager: ImportManager, file: ts.SourceFile): void;
addDirectExports(output: MagicString, exports: Reexport[], importManager: ImportManager, file: ts.SourceFile): void;
addDefinitions(output: MagicString, compiledClass: CompiledClass, definitions: string): void;
addAdjacentStatements(output: MagicString, compiledClass: CompiledClass, statements: string): void;
removeDecorators(output: MagicString, decoratorsToRemove: RedundantDecoratorMap): void;
addModuleWithProvidersParams(outputText: MagicString, moduleWithProviders: ModuleWithProvidersInfo[], importManager: ImportManager): void;
printStatement(stmt: Statement, sourceFile: ts.SourceFile, importManager: ImportManager): string;
}
+24
View File
@@ -0,0 +1,24 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/rendering/source_maps" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import mapHelpers from 'convert-source-map';
import MagicString from 'magic-string';
import ts from 'typescript';
import { ReadonlyFileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { FileToWrite } from './utils';
export interface SourceMapInfo {
source: string;
map: mapHelpers.SourceMapConverter | null;
isInline: boolean;
}
/**
* Merge the input and output source-maps, replacing the source-map comment in the output file
* with an appropriate source-map comment pointing to the merged source-map.
*/
export declare function renderSourceAndMap(logger: Logger, fs: ReadonlyFileSystem, sourceFile: ts.SourceFile, generatedMagicString: MagicString): FileToWrite[];
@@ -0,0 +1,55 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/rendering/umd_rendering_formatter" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import MagicString from 'magic-string';
import ts from 'typescript';
import { PathManipulation } from '../../../src/ngtsc/file_system';
import { Reexport } from '../../../src/ngtsc/imports';
import { Import, ImportManager } from '../../../src/ngtsc/translator';
import { ExportInfo } from '../analysis/private_declarations_analyzer';
import { UmdReflectionHost } from '../host/umd_host';
import { Esm5RenderingFormatter } from './esm5_rendering_formatter';
/**
* A RenderingFormatter that works with UMD files, instead of `import` and `export` statements
* the module is an IIFE with a factory function call with dependencies, which are defined in a
* wrapper function for AMD, CommonJS and global module formats.
*/
export declare class UmdRenderingFormatter extends Esm5RenderingFormatter {
protected umdHost: UmdReflectionHost;
constructor(fs: PathManipulation, umdHost: UmdReflectionHost, isCore: boolean);
/**
* Add the imports to the UMD module IIFE.
*
* Note that imports at "prepended" to the start of the parameter list of the factory function,
* and so also to the arguments passed to it when it is called.
* This is because there are scenarios where the factory function does not accept as many
* parameters as are passed as argument in the call. For example:
*
* ```
* (function (global, factory) {
* typeof exports === 'object' && typeof module !== 'undefined' ?
* factory(exports,require('x'),require('z')) :
* typeof define === 'function' && define.amd ?
* define(['exports', 'x', 'z'], factory) :
* (global = global || self, factory(global.myBundle = {}, global.x));
* }(this, (function (exports, x) { ... }
* ```
*
* (See that the `z` import is not being used by the factory function.)
*/
addImports(output: MagicString, imports: Import[], file: ts.SourceFile): void;
/**
* Add the exports to the bottom of the UMD module factory function.
*/
addExports(output: MagicString, entryPointBasePath: string, exports: ExportInfo[], importManager: ImportManager, file: ts.SourceFile): void;
addDirectExports(output: MagicString, exports: Reexport[], importManager: ImportManager, file: ts.SourceFile): void;
/**
* Add the constants to the top of the UMD factory function.
*/
addConstants(output: MagicString, constants: string, file: ts.SourceFile): void;
}
+25
View File
@@ -0,0 +1,25 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/rendering/utils" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { AbsoluteFsPath } from '../../../src/ngtsc/file_system';
import { ImportRewriter } from '../../../src/ngtsc/imports';
/**
* Information about a file that has been rendered.
*/
export interface FileToWrite {
/** Path to where the file should be written. */
path: AbsoluteFsPath;
/** The contents of the file to be be written. */
contents: string;
}
/**
* Create an appropriate ImportRewriter given the parameters.
*/
export declare function getImportRewriter(r3SymbolsFile: ts.SourceFile | null, isCore: boolean, isFlat: boolean): ImportRewriter;
export declare function stripExtension<T extends string>(filePath: T): T;
+113
View File
@@ -0,0 +1,113 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/utils" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import ts from 'typescript';
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../src/ngtsc/file_system';
import { DeclarationNode, KnownDeclaration } from '../../src/ngtsc/reflection';
export declare type JsonPrimitive = string | number | boolean | null;
export declare type JsonValue = JsonPrimitive | JsonArray | JsonObject | undefined;
export interface JsonArray extends Array<JsonValue> {
}
export interface JsonObject {
[key: string]: JsonValue;
}
/**
* A list (`Array`) of partially ordered `T` items.
*
* The items in the list are partially ordered in the sense that any element has either the same or
* higher precedence than any element which appears later in the list. What "higher precedence"
* means and how it is determined is implementation-dependent.
*
* See [PartiallyOrderedSet](https://en.wikipedia.org/wiki/Partially_ordered_set) for more details.
* (Refraining from using the term "set" here, to avoid confusion with JavaScript's
* [Set](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Set).)
*
* NOTE: A plain `Array<T>` is not assignable to a `PartiallyOrderedList<T>`, but a
* `PartiallyOrderedList<T>` is assignable to an `Array<T>`.
*/
export interface PartiallyOrderedList<T> extends Array<T> {
_partiallyOrdered: true;
map<U>(callbackfn: (value: T, index: number, array: PartiallyOrderedList<T>) => U, thisArg?: any): PartiallyOrderedList<U>;
slice(...args: Parameters<Array<T>['slice']>): PartiallyOrderedList<T>;
}
export declare function getOriginalSymbol(checker: ts.TypeChecker): (symbol: ts.Symbol) => ts.Symbol;
export declare function isDefined<T>(value: T | undefined | null): value is T;
export declare function getNameText(name: ts.PropertyName | ts.BindingName): string;
/**
* Does the given declaration have a name which is an identifier?
* @param declaration The declaration to test.
* @returns true if the declaration has an identifier for a name.
*/
export declare function hasNameIdentifier(declaration: ts.Node): declaration is DeclarationNode & {
name: ts.Identifier;
};
/**
* Test whether a path is "relative".
*
* Relative paths start with `/`, `./` or `../` (or the Windows equivalents); or are simply `.` or
* `..`.
*/
export declare function isRelativePath(path: string): boolean;
/**
* A `Map`-like object that can compute and memoize a missing value for any key.
*
* The computed values are memoized, so the factory function is not called more than once per key.
* This is useful for storing values that are expensive to compute and may be used multiple times.
*/
export declare class FactoryMap<K, V> {
private factory;
private internalMap;
constructor(factory: (key: K) => V, entries?: readonly (readonly [K, V])[] | null);
get(key: K): V;
set(key: K, value: V): void;
}
/**
* Attempt to resolve a `path` to a file by appending the provided `postFixes`
* to the `path` and checking if the file exists on disk.
* @returns An absolute path to the first matching existing file, or `null` if none exist.
*/
export declare function resolveFileWithPostfixes(fs: ReadonlyFileSystem, path: AbsoluteFsPath, postFixes: string[]): AbsoluteFsPath | null;
/**
* Determine whether a function declaration corresponds with a TypeScript helper function, returning
* its kind if so or null if the declaration does not seem to correspond with such a helper.
*/
export declare function getTsHelperFnFromDeclaration(decl: DeclarationNode): KnownDeclaration | null;
/**
* Determine whether an identifier corresponds with a TypeScript helper function (based on its
* name), returning its kind if so or null if the identifier does not seem to correspond with such a
* helper.
*/
export declare function getTsHelperFnFromIdentifier(id: ts.Identifier): KnownDeclaration | null;
/**
* An identifier may become repeated when bundling multiple source files into a single bundle, so
* bundlers have a strategy of suffixing non-unique identifiers with a suffix like $2. This function
* strips off such suffixes, so that ngcc deals with the canonical name of an identifier.
* @param value The value to strip any suffix of, if applicable.
* @returns The canonical representation of the value, without any suffix.
*/
export declare function stripDollarSuffix(value: string): string;
export declare function stripExtension(fileName: string): string;
/**
* Parse the JSON from a `package.json` file.
*
* @param packageJsonPath The absolute path to the `package.json` file.
* @returns JSON from the `package.json` file if it exists and is valid, `null` otherwise.
*/
export declare function loadJson<T extends JsonObject = JsonObject>(fs: ReadonlyFileSystem, packageJsonPath: AbsoluteFsPath): T | null;
/**
* Given the parsed JSON of a `package.json` file, try to extract info for a secondary entry-point
* from the `exports` property. Such info will only be present for packages following Angular
* Package Format v14+.
*
* @param primaryPackageJson The parsed JSON of the primary `package.json` (or `null` if it failed
* to be loaded).
* @param packagePath The absolute path to the containing npm package.
* @param entryPointPath The absolute path to the secondary entry-point.
* @returns The `exports` info for the specified entry-point if it exists, `null` otherwise.
*/
export declare function loadSecondaryEntryPointInfoForApfV14(fs: ReadonlyFileSystem, primaryPackageJson: JsonObject | null, packagePath: AbsoluteFsPath, entryPointPath: AbsoluteFsPath): JsonObject | null;
@@ -0,0 +1,45 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/writing/cleaning/cleaning_strategies" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, FileSystem, PathSegment } from '../../../../src/ngtsc/file_system';
/**
* Implement this interface to extend the cleaning strategies of the `PackageCleaner`.
*/
export interface CleaningStrategy {
canClean(path: AbsoluteFsPath, basename: PathSegment): boolean;
clean(path: AbsoluteFsPath, basename: PathSegment): void;
}
/**
* A CleaningStrategy that reverts changes to package.json files by removing the build marker and
* other properties.
*/
export declare class PackageJsonCleaner implements CleaningStrategy {
private fs;
constructor(fs: FileSystem);
canClean(_path: AbsoluteFsPath, basename: PathSegment): boolean;
clean(path: AbsoluteFsPath, _basename: PathSegment): void;
}
/**
* A CleaningStrategy that removes the extra directory containing generated entry-point formats.
*/
export declare class NgccDirectoryCleaner implements CleaningStrategy {
private fs;
constructor(fs: FileSystem);
canClean(path: AbsoluteFsPath, basename: PathSegment): boolean;
clean(path: AbsoluteFsPath, _basename: PathSegment): void;
}
/**
* A CleaningStrategy that reverts files that were overwritten and removes the backup files that
* ngcc created.
*/
export declare class BackupFileCleaner implements CleaningStrategy {
private fs;
constructor(fs: FileSystem);
canClean(path: AbsoluteFsPath, basename: PathSegment): boolean;
clean(path: AbsoluteFsPath, _basename: PathSegment): void;
}
@@ -0,0 +1,39 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/writing/cleaning/package_cleaner" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, FileSystem, ReadonlyFileSystem } from '../../../../src/ngtsc/file_system';
import { EntryPoint } from '../../packages/entry_point';
import { CleaningStrategy } from './cleaning_strategies';
/**
* A class that can clean ngcc artifacts from a directory.
*/
export declare class PackageCleaner {
private fs;
private cleaners;
constructor(fs: ReadonlyFileSystem, cleaners: CleaningStrategy[]);
/**
* Recurse through the file-system cleaning files and directories as determined by the configured
* cleaning-strategies.
*
* @param directory the current directory to clean
*/
clean(directory: AbsoluteFsPath): void;
}
/**
* Iterate through the given `entryPoints` identifying the package for each that has at least one
* outdated processed format, then cleaning those packages.
*
* Note that we have to clean entire packages because there is no clear file-system boundary
* between entry-points within a package. So if one entry-point is outdated we have to clean
* everything within that package.
*
* @param fileSystem the current file-system
* @param entryPoints the entry-points that have been collected for this run of ngcc
* @returns true if packages needed to be cleaned.
*/
export declare function cleanOutdatedPackages(fileSystem: FileSystem, entryPoints: EntryPoint[]): boolean;
+16
View File
@@ -0,0 +1,16 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/writing/cleaning/utils" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, ReadonlyFileSystem } from '../../../../src/ngtsc/file_system';
/**
* Returns true if the given `path` is a directory (not a symlink) and actually exists.
*
* @param fs the current filesystem
* @param path the path to check
*/
export declare function isLocalDirectory(fs: ReadonlyFileSystem, path: AbsoluteFsPath): boolean;
+29
View File
@@ -0,0 +1,29 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/writing/file_writer" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath } from '../../../src/ngtsc/file_system';
import { EntryPoint, EntryPointJsonProperty } from '../packages/entry_point';
import { EntryPointBundle } from '../packages/entry_point_bundle';
import { FileToWrite } from '../rendering/utils';
/**
* Responsible for writing out the transformed files to disk.
*/
export interface FileWriter {
writeBundle(bundle: EntryPointBundle, transformedFiles: FileToWrite[], formatProperties: EntryPointJsonProperty[]): void;
/**
* Revert the changes to an entry-point processed for the specified format-properties by the same
* `FileWriter` implementation.
*
* @param entryPoint The entry-point to revert.
* @param transformedFilePaths The original paths of the transformed files. (The transformed files
* may be written at the same or a different location, depending on the `FileWriter`
* implementation.)
* @param formatProperties The format-properties pointing to the entry-point.
*/
revertBundle(entryPoint: EntryPoint, transformedFilePaths: AbsoluteFsPath[], formatProperties: EntryPointJsonProperty[]): void;
}
@@ -0,0 +1,29 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/writing/in_place_file_writer" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, FileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { EntryPoint, EntryPointJsonProperty } from '../packages/entry_point';
import { EntryPointBundle } from '../packages/entry_point_bundle';
import { FileToWrite } from '../rendering/utils';
import { FileWriter } from './file_writer';
export declare const NGCC_BACKUP_EXTENSION = ".__ivy_ngcc_bak";
/**
* This FileWriter overwrites the transformed file, in-place, while creating
* a back-up of the original file with an extra `.__ivy_ngcc_bak` extension.
*/
export declare class InPlaceFileWriter implements FileWriter {
protected fs: FileSystem;
protected logger: Logger;
protected errorOnFailedEntryPoint: boolean;
constructor(fs: FileSystem, logger: Logger, errorOnFailedEntryPoint: boolean);
writeBundle(_bundle: EntryPointBundle, transformedFiles: FileToWrite[], _formatProperties?: EntryPointJsonProperty[]): void;
revertBundle(_entryPoint: EntryPoint, transformedFilePaths: AbsoluteFsPath[], _formatProperties: EntryPointJsonProperty[]): void;
protected writeFileAndBackup(file: FileToWrite): void;
protected revertFileAndBackup(filePath: AbsoluteFsPath): void;
}
@@ -0,0 +1,49 @@
/// <amd-module name="@angular/compiler-cli/ngcc/src/writing/new_entry_point_file_writer" />
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
import { AbsoluteFsPath, FileSystem } from '../../../src/ngtsc/file_system';
import { Logger } from '../../../src/ngtsc/logging';
import { EntryPoint, EntryPointJsonProperty } from '../packages/entry_point';
import { EntryPointBundle } from '../packages/entry_point_bundle';
import { FileToWrite } from '../rendering/utils';
import { InPlaceFileWriter } from './in_place_file_writer';
import { PackageJsonUpdater } from './package_json_updater';
export declare const NGCC_DIRECTORY = "__ivy_ngcc__";
export declare const NGCC_PROPERTY_EXTENSION = "_ivy_ngcc";
/**
* This FileWriter creates a copy of the original entry-point, then writes the transformed
* files onto the files in this copy, and finally updates the package.json with a new
* entry-point format property that points to this new entry-point.
*
* If there are transformed typings files in this bundle, they are updated in-place (see the
* `InPlaceFileWriter`).
*/
export declare class NewEntryPointFileWriter extends InPlaceFileWriter {
private pkgJsonUpdater;
constructor(fs: FileSystem, logger: Logger, errorOnFailedEntryPoint: boolean, pkgJsonUpdater: PackageJsonUpdater);
writeBundle(bundle: EntryPointBundle, transformedFiles: FileToWrite[], formatProperties: EntryPointJsonProperty[]): void;
revertBundle(entryPoint: EntryPoint, transformedFilePaths: AbsoluteFsPath[], formatProperties: EntryPointJsonProperty[]): void;
protected copyBundle(bundle: EntryPointBundle, packagePath: AbsoluteFsPath, ngccFolder: AbsoluteFsPath, transformedFiles: FileToWrite[]): void;
/**
* If a source file has an associated source-map, then copy this, while updating its sourceRoot
* accordingly.
*
* For now don't try to parse the source for inline source-maps or external source-map links,
* since that is more complex and will slow ngcc down.
* Instead just check for a source-map file residing next to the source file, which is by far
* the most common case.
*
* @param originalSrcPath absolute path to the original source file being copied.
* @param newSrcPath absolute path to where the source will be written.
*/
protected copyAndUpdateSourceMap(originalSrcPath: AbsoluteFsPath, newSrcPath: AbsoluteFsPath): void;
protected writeFile(file: FileToWrite, packagePath: AbsoluteFsPath, ngccFolder: AbsoluteFsPath): void;
protected revertFile(filePath: AbsoluteFsPath, packagePath: AbsoluteFsPath): void;
protected updatePackageJson(entryPoint: EntryPoint, formatProperties: EntryPointJsonProperty[], ngccFolder: AbsoluteFsPath): void;
protected revertPackageJson(entryPoint: EntryPoint, formatProperties: EntryPointJsonProperty[]): void;
}
@@ -0,0 +1,99 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* 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
*/
/// <amd-module name="@angular/compiler-cli/ngcc/src/writing/package_json_updater" />
import { AbsoluteFsPath, FileSystem } from '../../../src/ngtsc/file_system';
import { JsonObject, JsonValue } from '../utils';
export declare type PackageJsonChange = [string[], JsonValue, PackageJsonPropertyPositioning];
export declare type PackageJsonPropertyPositioning = 'unimportant' | 'alphabetic' | {
before: string;
};
export declare type WritePackageJsonChangesFn = (changes: PackageJsonChange[], packageJsonPath: AbsoluteFsPath, parsedJson?: JsonObject) => void;
/**
* A utility object that can be used to safely update values in a `package.json` file.
*
* Example usage:
* ```ts
* const updatePackageJson = packageJsonUpdater
* .createUpdate()
* .addChange(['name'], 'package-foo')
* .addChange(['scripts', 'foo'], 'echo FOOOO...', 'unimportant')
* .addChange(['dependencies', 'baz'], '1.0.0', 'alphabetic')
* .addChange(['dependencies', 'bar'], '2.0.0', {before: 'baz'})
* .writeChanges('/foo/package.json');
* // or
* // .writeChanges('/foo/package.json', inMemoryParsedJson);
* ```
*/
export interface PackageJsonUpdater {
/**
* Create a `PackageJsonUpdate` object, which provides a fluent API for batching updates to a
* `package.json` file. (Batching the updates is useful, because it avoids unnecessary I/O
* operations.)
*/
createUpdate(): PackageJsonUpdate;
/**
* Write a set of changes to the specified `package.json` file (and optionally a pre-existing,
* in-memory representation of it).
*
* @param changes The set of changes to apply.
* @param packageJsonPath The path to the `package.json` file that needs to be updated.
* @param parsedJson A pre-existing, in-memory representation of the `package.json` file that
* needs to be updated as well.
*/
writeChanges(changes: PackageJsonChange[], packageJsonPath: AbsoluteFsPath, parsedJson?: JsonObject): void;
}
/**
* A utility class providing a fluent API for recording multiple changes to a `package.json` file
* (and optionally its in-memory parsed representation).
*
* NOTE: This class should generally not be instantiated directly; instances are implicitly created
* via `PackageJsonUpdater#createUpdate()`.
*/
export declare class PackageJsonUpdate {
private writeChangesImpl;
private changes;
private applied;
constructor(writeChangesImpl: WritePackageJsonChangesFn);
/**
* Record a change to a `package.json` property.
*
* If the ancestor objects do not yet exist in the `package.json` file, they will be created. The
* positioning of the property can also be specified. (If the property already exists, it will be
* moved accordingly.)
*
* NOTE: Property positioning is only guaranteed to be respected in the serialized `package.json`
* file. Positioning will not be taken into account when updating in-memory representations.
*
* NOTE 2: Property positioning only affects the last property in `propertyPath`. Ancestor
* objects' positioning will not be affected.
*
* @param propertyPath The path of a (possibly nested) property to add/update.
* @param value The new value to set the property to.
* @param position The desired position for the added/updated property.
*/
addChange(propertyPath: string[], value: JsonValue, positioning?: PackageJsonPropertyPositioning): this;
/**
* Write the recorded changes to the associated `package.json` file (and optionally a
* pre-existing, in-memory representation of it).
*
* @param packageJsonPath The path to the `package.json` file that needs to be updated.
* @param parsedJson A pre-existing, in-memory representation of the `package.json` file that
* needs to be updated as well.
*/
writeChanges(packageJsonPath: AbsoluteFsPath, parsedJson?: JsonObject): void;
private ensureNotApplied;
private ensureNotSynthesized;
}
/** A `PackageJsonUpdater` that writes directly to the file-system. */
export declare class DirectPackageJsonUpdater implements PackageJsonUpdater {
private fs;
constructor(fs: FileSystem);
createUpdate(): PackageJsonUpdate;
writeChanges(changes: PackageJsonChange[], packageJsonPath: AbsoluteFsPath, preExistingParsedJson?: JsonObject): void;
}
export declare function applyChange(ctx: JsonObject, propPath: string[], value: JsonValue, positioning: PackageJsonPropertyPositioning): void;