feat: add .ngsummary.ts files to support AOT unit tests
Design doc: https://docs.google.com/document/d/1VmTkz0EbEVSWfEEWEvQ5sXyQXSCvtMOw4t7pKU-jOwc/edit?usp=sharing
This commit is contained in:

committed by
Matias Niemelä

parent
2714644528
commit
547c363473
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTypeSummary, componentFactoryName, createHostComponentMeta, flatten, identifierName, sourceUrl, templateSourceUrl} from '../compile_metadata';
|
||||
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompileProviderMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, componentFactoryName, createHostComponentMeta, flatten, identifierName, sourceUrl, templateSourceUrl} from '../compile_metadata';
|
||||
import {CompilerConfig} from '../config';
|
||||
import {Identifiers, createIdentifier, createIdentifierToken} from '../identifiers';
|
||||
import {CompileMetadataResolver} from '../metadata_resolver';
|
||||
@ -22,9 +22,9 @@ import {ViewCompiler} from '../view_compiler/view_compiler';
|
||||
import {AotCompilerHost} from './compiler_host';
|
||||
import {GeneratedFile} from './generated_file';
|
||||
import {StaticSymbol} from './static_symbol';
|
||||
import {StaticSymbolResolver} from './static_symbol_resolver';
|
||||
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
|
||||
import {serializeSummaries} from './summary_serializer';
|
||||
import {ngfactoryFilePath, splitTypescriptSuffix, summaryFileName} from './util';
|
||||
import {ngfactoryFilePath, splitTypescriptSuffix, summaryFileName, summaryForJitFileName, summaryForJitName} from './util';
|
||||
|
||||
export class AotCompiler {
|
||||
constructor(
|
||||
@ -59,12 +59,12 @@ export class AotCompiler {
|
||||
srcFileUrl: string, ngModuleByPipeOrDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
|
||||
directives: StaticSymbol[], pipes: StaticSymbol[], ngModules: StaticSymbol[],
|
||||
injectables: StaticSymbol[]): GeneratedFile[] {
|
||||
const fileSuffix = splitTypescriptSuffix(srcFileUrl)[1];
|
||||
const fileSuffix = splitTypescriptSuffix(srcFileUrl, true)[1];
|
||||
const statements: o.Statement[] = [];
|
||||
const exportedVars: string[] = [];
|
||||
const generatedFiles: GeneratedFile[] = [];
|
||||
|
||||
generatedFiles.push(this._createSummary(
|
||||
generatedFiles.push(...this._createSummary(
|
||||
srcFileUrl, directives, pipes, ngModules, injectables, statements, exportedVars));
|
||||
|
||||
// compile all ng modules
|
||||
@ -101,7 +101,7 @@ export class AotCompiler {
|
||||
});
|
||||
if (statements.length > 0) {
|
||||
const srcModule = this._codegenSourceModule(
|
||||
srcFileUrl, ngfactoryFilePath(srcFileUrl), statements, exportedVars);
|
||||
srcFileUrl, ngfactoryFilePath(srcFileUrl, true), statements, exportedVars);
|
||||
generatedFiles.unshift(srcModule);
|
||||
}
|
||||
return generatedFiles;
|
||||
@ -110,23 +110,45 @@ export class AotCompiler {
|
||||
private _createSummary(
|
||||
srcFileUrl: string, directives: StaticSymbol[], pipes: StaticSymbol[],
|
||||
ngModules: StaticSymbol[], injectables: StaticSymbol[], targetStatements: o.Statement[],
|
||||
targetExportedVars: string[]): GeneratedFile {
|
||||
targetExportedVars: string[]): GeneratedFile[] {
|
||||
const symbolSummaries = this._symbolResolver.getSymbolsOf(srcFileUrl)
|
||||
.map(symbol => this._symbolResolver.resolveSymbol(symbol));
|
||||
const typeSummaries: CompileTypeSummary[] = [
|
||||
...ngModules.map(ref => this._metadataResolver.getNgModuleSummary(ref) !),
|
||||
...directives.map(ref => this._metadataResolver.getDirectiveSummary(ref) !),
|
||||
...pipes.map(ref => this._metadataResolver.getPipeSummary(ref) !),
|
||||
...injectables.map(ref => this._metadataResolver.getInjectableSummary(ref) !)
|
||||
];
|
||||
const {json, exportAs} = serializeSummaries(
|
||||
this._summaryResolver, this._symbolResolver, symbolSummaries, typeSummaries);
|
||||
const typeData: {
|
||||
summary: CompileTypeSummary,
|
||||
metadata: CompileNgModuleMetadata | CompileDirectiveMetadata | CompilePipeMetadata |
|
||||
CompileTypeMetadata
|
||||
}[] =
|
||||
[
|
||||
...ngModules.map(ref => ({
|
||||
summary: this._metadataResolver.getNgModuleSummary(ref) !,
|
||||
metadata: this._metadataResolver.getNgModuleMetadata(ref) !
|
||||
})),
|
||||
...directives.map(ref => ({
|
||||
summary: this._metadataResolver.getDirectiveSummary(ref) !,
|
||||
metadata: this._metadataResolver.getDirectiveMetadata(ref) !
|
||||
})),
|
||||
...pipes.map(ref => ({
|
||||
summary: this._metadataResolver.getPipeSummary(ref) !,
|
||||
metadata: this._metadataResolver.getPipeMetadata(ref) !
|
||||
})),
|
||||
...injectables.map(ref => ({
|
||||
summary: this._metadataResolver.getInjectableSummary(ref) !,
|
||||
metadata: this._metadataResolver.getInjectableSummary(ref) !.type
|
||||
}))
|
||||
];
|
||||
const {json, exportAs, forJit} =
|
||||
serializeSummaries(this._summaryResolver, this._symbolResolver, symbolSummaries, typeData);
|
||||
exportAs.forEach((entry) => {
|
||||
targetStatements.push(
|
||||
o.variable(entry.exportAs).set(o.importExpr({reference: entry.symbol})).toDeclStmt());
|
||||
targetExportedVars.push(entry.exportAs);
|
||||
});
|
||||
return new GeneratedFile(srcFileUrl, summaryFileName(srcFileUrl), json);
|
||||
return [
|
||||
new GeneratedFile(srcFileUrl, summaryFileName(srcFileUrl), json),
|
||||
this._codegenSourceModule(
|
||||
srcFileUrl, summaryForJitFileName(srcFileUrl, true), forJit.statements,
|
||||
forJit.exportedVars)
|
||||
];
|
||||
}
|
||||
|
||||
private _compileModule(ngModuleType: StaticSymbol, targetStatements: o.Statement[]): string {
|
||||
|
@ -35,7 +35,6 @@ import {StaticSymbolResolver} from './static_symbol_resolver';
|
||||
import {AotSummaryResolver} from './summary_resolver';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new AotCompiler based on options and a host.
|
||||
*/
|
||||
@ -69,16 +68,10 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
|
||||
new PipeResolver(staticReflector), summaryResolver, elementSchemaRegistry, normalizer,
|
||||
console, symbolCache, staticReflector);
|
||||
// TODO(vicb): do not pass options.i18nFormat here
|
||||
const importResolver = {
|
||||
getImportAs: (symbol: StaticSymbol) => symbolResolver.getImportAs(symbol) !,
|
||||
fileNameToModuleName: (fileName: string, containingFilePath: string) =>
|
||||
compilerHost.fileNameToModuleName(fileName, containingFilePath),
|
||||
getTypeArity: (symbol: StaticSymbol) => symbolResolver.getTypeArity(symbol) !
|
||||
};
|
||||
const viewCompiler = new ViewCompiler(config, elementSchemaRegistry);
|
||||
const compiler = new AotCompiler(
|
||||
config, compilerHost, resolver, tmplParser, new StyleCompiler(urlResolver), viewCompiler,
|
||||
new NgModuleCompiler(), new TypeScriptEmitter(importResolver), summaryResolver,
|
||||
new NgModuleCompiler(), new TypeScriptEmitter(symbolResolver), summaryResolver,
|
||||
options.locale || null, options.i18nFormat || null, options.genFilePreamble || null,
|
||||
symbolResolver);
|
||||
return {compiler, reflector: staticReflector};
|
||||
|
@ -14,14 +14,6 @@ import {AotSummaryResolverHost} from './summary_resolver';
|
||||
* services and from underlying file systems.
|
||||
*/
|
||||
export interface AotCompilerHost extends StaticSymbolResolverHost, AotSummaryResolverHost {
|
||||
/**
|
||||
* Converts a file path to a module name that can be used as an `import.
|
||||
* I.e. `path/to/importedFile.ts` should be imported by `path/to/containingFile.ts`.
|
||||
*
|
||||
* See ImportResolver.
|
||||
*/
|
||||
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string|null;
|
||||
|
||||
/**
|
||||
* Loads a resource (e.g. html / css)
|
||||
*/
|
||||
|
@ -10,7 +10,7 @@ import {SummaryResolver} from '../summary_resolver';
|
||||
import {ValueTransformer, visitValue} from '../util';
|
||||
|
||||
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
|
||||
import {isNgFactoryFile} from './util';
|
||||
import {isGeneratedFile, stripSummaryForJitFileSuffix, stripSummaryForJitNameSuffix, summaryForJitFileName, summaryForJitName} from './util';
|
||||
|
||||
export class ResolvedStaticSymbol {
|
||||
constructor(public symbol: StaticSymbol, public metadata: any) {}
|
||||
@ -39,6 +39,13 @@ export interface StaticSymbolResolverHost {
|
||||
* `path/to/containingFile.ts` containing `import {...} from 'module-name'`.
|
||||
*/
|
||||
moduleNameToFileName(moduleName: string, containingFile?: string): string|null;
|
||||
/**
|
||||
* Converts a file path to a module name that can be used as an `import.
|
||||
* I.e. `path/to/importedFile.ts` should be imported by `path/to/containingFile.ts`.
|
||||
*
|
||||
* See ImportResolver.
|
||||
*/
|
||||
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string|null;
|
||||
}
|
||||
|
||||
const SUPPORTED_SCHEMA_VERSION = 3;
|
||||
@ -60,6 +67,7 @@ export class StaticSymbolResolver {
|
||||
private importAs = new Map<StaticSymbol, StaticSymbol>();
|
||||
private symbolResourcePaths = new Map<StaticSymbol, string>();
|
||||
private symbolFromFile = new Map<string, StaticSymbol[]>();
|
||||
private knownFileNameToModuleNames = new Map<string, string>();
|
||||
|
||||
constructor(
|
||||
private host: StaticSymbolResolverHost, private staticSymbolCache: StaticSymbolCache,
|
||||
@ -103,6 +111,18 @@ export class StaticSymbolResolver {
|
||||
this.getStaticSymbol(baseImportAs.filePath, baseImportAs.name, staticSymbol.members) :
|
||||
null;
|
||||
}
|
||||
const summarizedFileName = stripSummaryForJitFileSuffix(staticSymbol.filePath);
|
||||
if (summarizedFileName !== staticSymbol.filePath) {
|
||||
const summarizedName = stripSummaryForJitNameSuffix(staticSymbol.name);
|
||||
const baseSymbol =
|
||||
this.getStaticSymbol(summarizedFileName, summarizedName, staticSymbol.members);
|
||||
const baseImportAs = this.getImportAs(baseSymbol);
|
||||
return baseImportAs ?
|
||||
this.getStaticSymbol(
|
||||
summaryForJitFileName(baseImportAs.filePath), summaryForJitName(baseImportAs.name),
|
||||
baseSymbol.members) :
|
||||
null;
|
||||
}
|
||||
let result = this.summaryResolver.getImportAs(staticSymbol);
|
||||
if (!result) {
|
||||
result = this.importAs.get(staticSymbol) !;
|
||||
@ -124,11 +144,11 @@ export class StaticSymbolResolver {
|
||||
* has. If the symbol is not a type the result is null.
|
||||
*/
|
||||
getTypeArity(staticSymbol: StaticSymbol): number|null {
|
||||
// If the file is a factory file, don't resolve the symbol as doing so would
|
||||
// cause the metadata for an factory file to be loaded which doesn't exist.
|
||||
// If the file is a factory/ngsummary file, don't resolve the symbol as doing so would
|
||||
// cause the metadata for an factory/ngsummary file to be loaded which doesn't exist.
|
||||
// All references to generated classes must include the correct arity whenever
|
||||
// generating code.
|
||||
if (isNgFactoryFile(staticSymbol.filePath)) {
|
||||
if (isGeneratedFile(staticSymbol.filePath)) {
|
||||
return null;
|
||||
}
|
||||
let resolvedSymbol = this.resolveSymbol(staticSymbol);
|
||||
@ -138,6 +158,17 @@ export class StaticSymbolResolver {
|
||||
return (resolvedSymbol && resolvedSymbol.metadata && resolvedSymbol.metadata.arity) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a file path to a module name that can be used as an `import`.
|
||||
*/
|
||||
fileNameToModuleName(importedFilePath: string, containingFilePath: string): string|null {
|
||||
if (importedFilePath === containingFilePath) {
|
||||
return null;
|
||||
}
|
||||
return this.knownFileNameToModuleNames.get(importedFilePath) ||
|
||||
this.host.fileNameToModuleName(importedFilePath, containingFilePath);
|
||||
}
|
||||
|
||||
recordImportAs(sourceSymbol: StaticSymbol, targetSymbol: StaticSymbol) {
|
||||
sourceSymbol.assertNoMembers();
|
||||
targetSymbol.assertNoMembers();
|
||||
@ -226,6 +257,11 @@ export class StaticSymbolResolver {
|
||||
this.resolvedFilePaths.add(filePath);
|
||||
const resolvedSymbols: ResolvedStaticSymbol[] = [];
|
||||
const metadata = this.getModuleMetadata(filePath);
|
||||
if (metadata['importAs']) {
|
||||
// Index bundle indices should use the importAs module name defined
|
||||
// in the bundle.
|
||||
this.knownFileNameToModuleNames.set(filePath, metadata['importAs']);
|
||||
}
|
||||
if (metadata['metadata']) {
|
||||
// handle direct declarations of the symbol
|
||||
const topLevelSymbolNames =
|
||||
@ -236,13 +272,6 @@ export class StaticSymbolResolver {
|
||||
const name = unescapeIdentifier(metadataKey);
|
||||
|
||||
const symbol = this.getStaticSymbol(filePath, name);
|
||||
let importSymbol: StaticSymbol|undefined = undefined;
|
||||
if (metadata['importAs']) {
|
||||
// Index bundle indexes should use the importAs module name instead of a reference
|
||||
// to the .d.ts file directly.
|
||||
importSymbol = this.getStaticSymbol(metadata['importAs'], name);
|
||||
this.recordImportAs(symbol, importSymbol);
|
||||
}
|
||||
|
||||
const origin = origins.hasOwnProperty(metadataKey) && origins[metadataKey];
|
||||
if (origin) {
|
||||
|
@ -10,7 +10,7 @@ import {Summary, SummaryResolver} from '../summary_resolver';
|
||||
|
||||
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
|
||||
import {deserializeSummaries} from './summary_serializer';
|
||||
import {ngfactoryFilePath, stripNgFactory, summaryFileName} from './util';
|
||||
import {ngfactoryFilePath, stripGeneratedFileSuffix, summaryFileName} from './util';
|
||||
|
||||
export interface AotSummaryResolverHost {
|
||||
/**
|
||||
@ -43,7 +43,7 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
|
||||
// Note: We need to strip the .ngfactory. file path,
|
||||
// so this method also works for generated files
|
||||
// (for which host.isSourceFile will always return false).
|
||||
return !this.host.isSourceFile(stripNgFactory(filePath));
|
||||
return !this.host.isSourceFile(stripGeneratedFileSuffix(filePath));
|
||||
}
|
||||
|
||||
getLibraryFileName(filePath: string) { return this.host.getOutputFileName(filePath); }
|
||||
@ -68,6 +68,8 @@ export class AotSummaryResolver implements SummaryResolver<StaticSymbol> {
|
||||
return this.importAs.get(staticSymbol) !;
|
||||
}
|
||||
|
||||
addSummary(summary: Summary<StaticSymbol>) { this.summaryCache.set(summary.symbol, summary); }
|
||||
|
||||
private _loadSummaryFile(filePath: string) {
|
||||
if (this.loadedFilePaths.has(filePath)) {
|
||||
return;
|
||||
|
@ -5,31 +5,40 @@
|
||||
* 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 {CompileNgModuleSummary, CompileSummaryKind, CompileTypeSummary} from '../compile_metadata';
|
||||
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompileProviderMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary} from '../compile_metadata';
|
||||
import * as o from '../output/output_ast';
|
||||
import {Summary, SummaryResolver} from '../summary_resolver';
|
||||
import {ValueTransformer, visitValue} from '../util';
|
||||
import {ValueTransformer, ValueVisitor, visitValue} from '../util';
|
||||
|
||||
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
|
||||
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
|
||||
|
||||
import {summaryForJitFileName, summaryForJitName} from './util';
|
||||
|
||||
export function serializeSummaries(
|
||||
summaryResolver: SummaryResolver<StaticSymbol>, symbolResolver: StaticSymbolResolver,
|
||||
symbols: ResolvedStaticSymbol[], types: CompileTypeSummary[]):
|
||||
{json: string, exportAs: {symbol: StaticSymbol, exportAs: string}[]} {
|
||||
const serializer = new Serializer(symbolResolver, summaryResolver);
|
||||
symbols: ResolvedStaticSymbol[], types: {
|
||||
summary: CompileTypeSummary,
|
||||
metadata: CompileNgModuleMetadata | CompileDirectiveMetadata | CompilePipeMetadata |
|
||||
CompileTypeMetadata
|
||||
}[]): {
|
||||
json: string,
|
||||
exportAs: {symbol: StaticSymbol, exportAs: string}[],
|
||||
forJit: {statements: o.Statement[], exportedVars: string[]}
|
||||
} {
|
||||
const toJsonSerializer = new ToJsonSerializer(symbolResolver, summaryResolver);
|
||||
const forJitSerializer = new ForJitSerializer(symbolResolver);
|
||||
|
||||
// for symbols, we use everything except for the class metadata itself
|
||||
// (we keep the statics though), as the class metadata is contained in the
|
||||
// CompileTypeSummary.
|
||||
symbols.forEach(
|
||||
(resolvedSymbol) => serializer.addOrMergeSummary(
|
||||
(resolvedSymbol) => toJsonSerializer.addOrMergeSummary(
|
||||
{symbol: resolvedSymbol.symbol, metadata: resolvedSymbol.metadata}));
|
||||
// Add summaries that are referenced by the given symbols (transitively)
|
||||
// Note: the serializer.symbols array might be growing while
|
||||
// we execute the loop!
|
||||
for (let processedIndex = 0; processedIndex < serializer.symbols.length; processedIndex++) {
|
||||
const symbol = serializer.symbols[processedIndex];
|
||||
for (let processedIndex = 0; processedIndex < toJsonSerializer.symbols.length; processedIndex++) {
|
||||
const symbol = toJsonSerializer.symbols[processedIndex];
|
||||
if (summaryResolver.isLibraryFile(symbol.filePath)) {
|
||||
let summary = summaryResolver.resolveSummary(symbol);
|
||||
if (!summary) {
|
||||
@ -42,7 +51,10 @@ export function serializeSummaries(
|
||||
}
|
||||
}
|
||||
if (summary) {
|
||||
serializer.addOrMergeSummary(summary);
|
||||
if (summary.type) {
|
||||
forJitSerializer.addLibType(summary.type);
|
||||
}
|
||||
toJsonSerializer.addOrMergeSummary(summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,32 +63,35 @@ export function serializeSummaries(
|
||||
// Note: We don't add the summaries of all referenced symbols as for the ResolvedSymbols,
|
||||
// as the type summaries already contain the transitive data that they require
|
||||
// (in a minimal way).
|
||||
types.forEach((typeSummary) => {
|
||||
serializer.addOrMergeSummary(
|
||||
{symbol: typeSummary.type.reference, metadata: null, type: typeSummary});
|
||||
if (typeSummary.summaryKind === CompileSummaryKind.NgModule) {
|
||||
const ngModuleSummary = <CompileNgModuleSummary>typeSummary;
|
||||
types.forEach(({summary, metadata}) => {
|
||||
forJitSerializer.addSourceType(summary, metadata);
|
||||
toJsonSerializer.addOrMergeSummary(
|
||||
{symbol: summary.type.reference, metadata: null, type: summary});
|
||||
if (summary.summaryKind === CompileSummaryKind.NgModule) {
|
||||
const ngModuleSummary = <CompileNgModuleSummary>summary;
|
||||
ngModuleSummary.exportedDirectives.concat(ngModuleSummary.exportedPipes).forEach((id) => {
|
||||
const symbol: StaticSymbol = id.reference;
|
||||
if (summaryResolver.isLibraryFile(symbol.filePath)) {
|
||||
const summary = summaryResolver.resolveSummary(symbol);
|
||||
if (summary) {
|
||||
serializer.addOrMergeSummary(summary);
|
||||
toJsonSerializer.addOrMergeSummary(summary);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return serializer.serialize();
|
||||
const {json, exportAs} = toJsonSerializer.serialize();
|
||||
const {statements, exportedVars} = forJitSerializer.serialize(exportAs);
|
||||
return {json, forJit: {statements, exportedVars}, exportAs};
|
||||
}
|
||||
|
||||
export function deserializeSummaries(symbolCache: StaticSymbolCache, json: string):
|
||||
{summaries: Summary<StaticSymbol>[], importAs: {symbol: StaticSymbol, importAs: string}[]} {
|
||||
const deserializer = new Deserializer(symbolCache);
|
||||
const deserializer = new FromJsonDeserializer(symbolCache);
|
||||
return deserializer.deserialize(json);
|
||||
}
|
||||
|
||||
class Serializer extends ValueTransformer {
|
||||
class ToJsonSerializer extends ValueTransformer {
|
||||
// Note: This only contains symbols without members.
|
||||
symbols: StaticSymbol[] = [];
|
||||
private indexBySymbol = new Map<StaticSymbol, number>();
|
||||
@ -169,7 +184,132 @@ class Serializer extends ValueTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
class Deserializer extends ValueTransformer {
|
||||
class ForJitSerializer {
|
||||
private data = new Map<StaticSymbol, {
|
||||
summary: CompileTypeSummary,
|
||||
metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|CompilePipeMetadata|
|
||||
CompileTypeMetadata|null,
|
||||
isLibrary: boolean
|
||||
}>();
|
||||
|
||||
constructor(private symbolResolver: StaticSymbolResolver) {}
|
||||
|
||||
addSourceType(
|
||||
summary: CompileTypeSummary, metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|
|
||||
CompilePipeMetadata|CompileTypeMetadata) {
|
||||
this.data.set(summary.type.reference, {summary, metadata, isLibrary: false});
|
||||
}
|
||||
|
||||
addLibType(summary: CompileTypeSummary) {
|
||||
this.data.set(summary.type.reference, {summary, metadata: null, isLibrary: true});
|
||||
}
|
||||
|
||||
serialize(exportAs: {symbol: StaticSymbol, exportAs: string}[]):
|
||||
{statements: o.Statement[], exportedVars: string[]} {
|
||||
const statements: o.Statement[] = [];
|
||||
const exportedVars: string[] = [];
|
||||
const ngModuleSymbols = new Set<StaticSymbol>();
|
||||
|
||||
Array.from(this.data.values()).forEach(({summary, metadata, isLibrary}) => {
|
||||
if (summary.summaryKind === CompileSummaryKind.NgModule) {
|
||||
// collect the symbols that refer to NgModule classes.
|
||||
// Note: we can't just rely on `summary.type.summaryKind` to determine this as
|
||||
// we don't add the summaries of all referenced symbols when we serialize type summaries.
|
||||
// See serializeSummaries for details.
|
||||
ngModuleSymbols.add(summary.type.reference);
|
||||
const modSummary = <CompileNgModuleSummary>summary;
|
||||
modSummary.modules.forEach((mod) => { ngModuleSymbols.add(mod.reference); });
|
||||
}
|
||||
if (!isLibrary) {
|
||||
const fnName = summaryForJitName(summary.type.reference.name);
|
||||
statements.push(
|
||||
o.fn([], [new o.ReturnStatement(this.serializeSummaryWithDeps(summary, metadata !))],
|
||||
new o.ArrayType(o.DYNAMIC_TYPE))
|
||||
.toDeclStmt(fnName, [o.StmtModifier.Final]));
|
||||
exportedVars.push(fnName);
|
||||
}
|
||||
});
|
||||
|
||||
exportAs.forEach((entry) => {
|
||||
const symbol = entry.symbol;
|
||||
if (ngModuleSymbols.has(symbol)) {
|
||||
const jitExportAsName = summaryForJitName(entry.exportAs);
|
||||
statements.push(
|
||||
o.variable(jitExportAsName).set(this.serializeSummaryRef(symbol)).toDeclStmt());
|
||||
exportedVars.push(jitExportAsName);
|
||||
}
|
||||
});
|
||||
|
||||
return {statements, exportedVars};
|
||||
}
|
||||
|
||||
private serializeSummaryWithDeps(
|
||||
summary: CompileTypeSummary, metadata: CompileNgModuleMetadata|CompileDirectiveMetadata|
|
||||
CompilePipeMetadata|CompileTypeMetadata): o.Expression {
|
||||
const expressions: o.Expression[] = [this.serializeSummary(summary)];
|
||||
let providers: CompileProviderMetadata[] = [];
|
||||
if (metadata instanceof CompileNgModuleMetadata) {
|
||||
expressions.push(...
|
||||
// For directives / pipes, we only add the declared ones,
|
||||
// and rely on transitively importing NgModules to get the transitive
|
||||
// summaries.
|
||||
metadata.declaredDirectives.concat(metadata.declaredPipes)
|
||||
.map(type => type.reference)
|
||||
// For modules,
|
||||
// we also add the summaries for modules
|
||||
// from libraries.
|
||||
// This is ok as we produce reexports for all transitive modules.
|
||||
.concat(metadata.transitiveModule.modules.map(type => type.reference)
|
||||
.filter(ref => ref !== metadata.type.reference))
|
||||
.map((ref) => this.serializeSummaryRef(ref)));
|
||||
// Note: We don't use `NgModuleSummary.providers`, as that one is transitive,
|
||||
// and we already have transitive modules.
|
||||
providers = metadata.providers;
|
||||
} else if (summary.summaryKind === CompileSummaryKind.Directive) {
|
||||
const dirSummary = <CompileDirectiveSummary>summary;
|
||||
providers = dirSummary.providers.concat(dirSummary.viewProviders);
|
||||
}
|
||||
// Note: We can't just refer to the `ngsummary.ts` files for `useClass` providers (as we do for
|
||||
// declaredDirectives / declaredPipes), as we allow
|
||||
// providers without ctor arguments to skip the `@Injectable` decorator,
|
||||
// i.e. we didn't generate .ngsummary.ts files for these.
|
||||
expressions.push(
|
||||
...providers.filter(provider => !!provider.useClass).map(provider => this.serializeSummary({
|
||||
summaryKind: CompileSummaryKind.Injectable, type: provider.useClass
|
||||
} as CompileTypeSummary)));
|
||||
return o.literalArr(expressions);
|
||||
}
|
||||
|
||||
private serializeSummaryRef(typeSymbol: StaticSymbol): o.Expression {
|
||||
const jitImportedSymbol = this.symbolResolver.getStaticSymbol(
|
||||
summaryForJitFileName(typeSymbol.filePath), summaryForJitName(typeSymbol.name));
|
||||
return o.importExpr({reference: jitImportedSymbol});
|
||||
}
|
||||
|
||||
private serializeSummary(data: {[key: string]: any}): o.Expression {
|
||||
class Transformer implements ValueVisitor {
|
||||
visitArray(arr: any[], context: any): any {
|
||||
return o.literalArr(arr.map(entry => visitValue(entry, this, context)));
|
||||
}
|
||||
visitStringMap(map: {[key: string]: any}, context: any): any {
|
||||
return new o.LiteralMapExpr(Object.keys(map).map(
|
||||
(key) => new o.LiteralMapEntry(key, visitValue(map[key], this, context))));
|
||||
}
|
||||
visitPrimitive(value: any, context: any): any { return o.literal(value); }
|
||||
visitOther(value: any, context: any): any {
|
||||
if (value instanceof StaticSymbol) {
|
||||
return o.importExpr({reference: value});
|
||||
} else {
|
||||
throw new Error(`Illegal State: Encountered value ${value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return visitValue(data, new Transformer(), null);
|
||||
}
|
||||
}
|
||||
|
||||
class FromJsonDeserializer extends ValueTransformer {
|
||||
private symbols: StaticSymbol[];
|
||||
|
||||
constructor(private symbolCache: StaticSymbolCache) { super(); }
|
||||
|
@ -7,24 +7,27 @@
|
||||
*/
|
||||
|
||||
const STRIP_SRC_FILE_SUFFIXES = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
|
||||
const NG_FACTORY = /\.ngfactory\./;
|
||||
const GENERATED_FILE = /\.ngfactory\.|\.ngsummary\./;
|
||||
const GENERATED_MODULE = /\.ngfactory$|\.ngsummary$/;
|
||||
const JIT_SUMMARY_FILE = /\.ngsummary\./;
|
||||
const JIT_SUMMARY_NAME = /NgSummary$/;
|
||||
|
||||
export function ngfactoryFilePath(filePath: string): string {
|
||||
const urlWithSuffix = splitTypescriptSuffix(filePath);
|
||||
export function ngfactoryFilePath(filePath: string, forceSourceFile = false): string {
|
||||
const urlWithSuffix = splitTypescriptSuffix(filePath, forceSourceFile);
|
||||
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
|
||||
}
|
||||
|
||||
export function stripNgFactory(filePath: string): string {
|
||||
return filePath.replace(NG_FACTORY, '.');
|
||||
export function stripGeneratedFileSuffix(filePath: string): string {
|
||||
return filePath.replace(GENERATED_FILE, '.');
|
||||
}
|
||||
|
||||
export function isNgFactoryFile(filePath: string): boolean {
|
||||
return NG_FACTORY.test(filePath);
|
||||
export function isGeneratedFile(filePath: string): boolean {
|
||||
return GENERATED_FILE.test(filePath);
|
||||
}
|
||||
|
||||
export function splitTypescriptSuffix(path: string): string[] {
|
||||
export function splitTypescriptSuffix(path: string, forceSourceFile = false): string[] {
|
||||
if (path.endsWith('.d.ts')) {
|
||||
return [path.slice(0, -5), '.ts'];
|
||||
return [path.slice(0, -5), forceSourceFile ? '.ts' : '.d.ts'];
|
||||
}
|
||||
|
||||
const lastDot = path.lastIndexOf('.');
|
||||
@ -40,3 +43,20 @@ export function summaryFileName(fileName: string): string {
|
||||
const fileNameWithoutSuffix = fileName.replace(STRIP_SRC_FILE_SUFFIXES, '');
|
||||
return `${fileNameWithoutSuffix}.ngsummary.json`;
|
||||
}
|
||||
|
||||
export function summaryForJitFileName(fileName: string, forceSourceFile = false): string {
|
||||
const urlWithSuffix = splitTypescriptSuffix(stripGeneratedFileSuffix(fileName), forceSourceFile);
|
||||
return `${urlWithSuffix[0]}.ngsummary${urlWithSuffix[1]}`;
|
||||
}
|
||||
|
||||
export function stripSummaryForJitFileSuffix(filePath: string): string {
|
||||
return filePath.replace(JIT_SUMMARY_FILE, '.');
|
||||
}
|
||||
|
||||
export function summaryForJitName(symbolName: string): string {
|
||||
return `${symbolName}NgSummary`;
|
||||
}
|
||||
|
||||
export function stripSummaryForJitNameSuffix(symbolName: string): string {
|
||||
return symbolName.replace(JIT_SUMMARY_NAME, '');
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
|
||||
import {Compiler, ComponentFactory, Inject, Injector, ModuleWithComponentFactories, NgModuleFactory, Type, ɵConsole as Console, ɵgetComponentViewDefinitionFactory as getComponentViewDefinitionFactory, ɵstringify as stringify} from '@angular/core';
|
||||
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileStylesheetMetadata, ProviderMeta, ProxyClass, createHostComponentMeta, identifierName, ngModuleJitUrl, sharedStylesheetJitUrl, templateJitUrl, templateSourceUrl} from '../compile_metadata';
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileStylesheetMetadata, CompileTypeSummary, ProviderMeta, ProxyClass, createHostComponentMeta, identifierName, ngModuleJitUrl, sharedStylesheetJitUrl, templateJitUrl, templateSourceUrl} from '../compile_metadata';
|
||||
import {CompilerConfig} from '../config';
|
||||
import {CompilerInjectable} from '../injectable';
|
||||
import {CompileMetadataResolver} from '../metadata_resolver';
|
||||
@ -17,6 +17,7 @@ import * as ir from '../output/output_ast';
|
||||
import {interpretStatements} from '../output/output_interpreter';
|
||||
import {jitStatements} from '../output/output_jit';
|
||||
import {CompiledStylesheet, StyleCompiler} from '../style_compiler';
|
||||
import {SummaryResolver} from '../summary_resolver';
|
||||
import {TemplateParser} from '../template_parser/template_parser';
|
||||
import {SyncAsyncResult} from '../util';
|
||||
import {ViewCompiler} from '../view_compiler/view_compiler';
|
||||
@ -44,7 +45,8 @@ export class JitCompiler implements Compiler {
|
||||
private _injector: Injector, private _metadataResolver: CompileMetadataResolver,
|
||||
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
|
||||
private _viewCompiler: ViewCompiler, private _ngModuleCompiler: NgModuleCompiler,
|
||||
private _compilerConfig: CompilerConfig, private _console: Console) {}
|
||||
private _summaryResolver: SummaryResolver<Type<any>>, private _compilerConfig: CompilerConfig,
|
||||
private _console: Console) {}
|
||||
|
||||
get injector(): Injector { return this._injector; }
|
||||
|
||||
@ -75,6 +77,25 @@ export class JitCompiler implements Compiler {
|
||||
return template.compMeta.template !.ngContentSelectors;
|
||||
}
|
||||
|
||||
getComponentFactory<T>(component: Type<T>): ComponentFactory<T> {
|
||||
const summary = this._metadataResolver.getDirectiveSummary(component);
|
||||
return <ComponentFactory<T>>summary.componentFactory;
|
||||
}
|
||||
|
||||
loadAotSummaries(summaries: () => any[]) {
|
||||
this.clearCache();
|
||||
flattenSummaries(summaries).forEach((summary) => {
|
||||
this._summaryResolver.addSummary(
|
||||
{symbol: summary.type.reference, metadata: null, type: summary});
|
||||
});
|
||||
}
|
||||
|
||||
hasAotSummary(ref: Type<any>) { return !!this._summaryResolver.resolveSummary(ref); }
|
||||
|
||||
private _filterJitIdentifiers(ids: CompileIdentifierMetadata[]): any[] {
|
||||
return ids.map(mod => mod.reference).filter((ref) => !this.hasAotSummary(ref));
|
||||
}
|
||||
|
||||
private _compileModuleAndComponents<T>(moduleType: Type<T>, isSync: boolean):
|
||||
SyncAsyncResult<NgModuleFactory<T>> {
|
||||
const loadingPromise = this._loadModules(moduleType, isSync);
|
||||
@ -106,14 +127,21 @@ export class JitCompiler implements Compiler {
|
||||
|
||||
private _loadModules(mainModule: any, isSync: boolean): Promise<any> {
|
||||
const loadingPromises: Promise<any>[] = [];
|
||||
const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule) !;
|
||||
// Note: the loadingPromise for a module only includes the loading of the exported directives
|
||||
// of imported modules.
|
||||
// However, for runtime compilation, we want to transitively compile all modules,
|
||||
// so we also need to call loadNgModuleDirectiveAndPipeMetadata for all nested modules.
|
||||
ngModule.transitiveModule.modules.forEach((localModuleMeta) => {
|
||||
loadingPromises.push(this._metadataResolver.loadNgModuleDirectiveAndPipeMetadata(
|
||||
localModuleMeta.reference, isSync));
|
||||
const mainNgModule = this._metadataResolver.getNgModuleMetadata(mainModule) !;
|
||||
// Note: for runtime compilation, we want to transitively compile all modules,
|
||||
// so we also need to load the declared directives / pipes for all nested modules.
|
||||
this._filterJitIdentifiers(mainNgModule.transitiveModule.modules).forEach((nestedNgModule) => {
|
||||
// getNgModuleMetadata only returns null if the value passed in is not an NgModule
|
||||
const moduleMeta = this._metadataResolver.getNgModuleMetadata(nestedNgModule) !;
|
||||
this._filterJitIdentifiers(moduleMeta.declaredDirectives).forEach((ref) => {
|
||||
const promise =
|
||||
this._metadataResolver.loadDirectiveMetadata(moduleMeta.type.reference, ref, isSync);
|
||||
if (promise) {
|
||||
loadingPromises.push(promise);
|
||||
}
|
||||
});
|
||||
this._filterJitIdentifiers(moduleMeta.declaredPipes)
|
||||
.forEach((ref) => this._metadataResolver.getOrLoadPipeMetadata(ref));
|
||||
});
|
||||
return Promise.all(loadingPromises);
|
||||
}
|
||||
@ -144,15 +172,15 @@ export class JitCompiler implements Compiler {
|
||||
*/
|
||||
_compileComponents(mainModule: Type<any>, allComponentFactories: ComponentFactory<any>[]|null) {
|
||||
const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule) !;
|
||||
const moduleByDirective = new Map<any, CompileNgModuleMetadata>();
|
||||
const moduleByJitDirective = new Map<any, CompileNgModuleMetadata>();
|
||||
const templates = new Set<CompiledTemplate>();
|
||||
|
||||
ngModule.transitiveModule.modules.forEach((localModuleSummary) => {
|
||||
const localModuleMeta =
|
||||
this._metadataResolver.getNgModuleMetadata(localModuleSummary.reference) !;
|
||||
localModuleMeta.declaredDirectives.forEach((dirIdentifier) => {
|
||||
moduleByDirective.set(dirIdentifier.reference, localModuleMeta);
|
||||
const dirMeta = this._metadataResolver.getDirectiveMetadata(dirIdentifier.reference);
|
||||
const transJitModules = this._filterJitIdentifiers(ngModule.transitiveModule.modules);
|
||||
transJitModules.forEach((localMod) => {
|
||||
const localModuleMeta = this._metadataResolver.getNgModuleMetadata(localMod) !;
|
||||
this._filterJitIdentifiers(localModuleMeta.declaredDirectives).forEach((dirRef) => {
|
||||
moduleByJitDirective.set(dirRef, localModuleMeta);
|
||||
const dirMeta = this._metadataResolver.getDirectiveMetadata(dirRef);
|
||||
if (dirMeta.isComponent) {
|
||||
templates.add(this._createCompiledTemplate(dirMeta, localModuleMeta));
|
||||
if (allComponentFactories) {
|
||||
@ -164,23 +192,24 @@ export class JitCompiler implements Compiler {
|
||||
}
|
||||
});
|
||||
});
|
||||
ngModule.transitiveModule.modules.forEach((localModuleSummary) => {
|
||||
const localModuleMeta =
|
||||
this._metadataResolver.getNgModuleMetadata(localModuleSummary.reference) !;
|
||||
localModuleMeta.declaredDirectives.forEach((dirIdentifier) => {
|
||||
const dirMeta = this._metadataResolver.getDirectiveMetadata(dirIdentifier.reference);
|
||||
transJitModules.forEach((localMod) => {
|
||||
const localModuleMeta = this._metadataResolver.getNgModuleMetadata(localMod) !;
|
||||
this._filterJitIdentifiers(localModuleMeta.declaredDirectives).forEach((dirRef) => {
|
||||
const dirMeta = this._metadataResolver.getDirectiveMetadata(dirRef);
|
||||
if (dirMeta.isComponent) {
|
||||
dirMeta.entryComponents.forEach((entryComponentType) => {
|
||||
const moduleMeta = moduleByDirective.get(entryComponentType.componentType) !;
|
||||
const moduleMeta = moduleByJitDirective.get(entryComponentType.componentType) !;
|
||||
templates.add(
|
||||
this._createCompiledHostTemplate(entryComponentType.componentType, moduleMeta));
|
||||
});
|
||||
}
|
||||
});
|
||||
localModuleMeta.entryComponents.forEach((entryComponentType) => {
|
||||
const moduleMeta = moduleByDirective.get(entryComponentType.componentType) !;
|
||||
templates.add(
|
||||
this._createCompiledHostTemplate(entryComponentType.componentType, moduleMeta));
|
||||
if (!this.hasAotSummary(entryComponentType.componentType.reference)) {
|
||||
const moduleMeta = moduleByJitDirective.get(entryComponentType.componentType) !;
|
||||
templates.add(
|
||||
this._createCompiledHostTemplate(entryComponentType.componentType, moduleMeta));
|
||||
}
|
||||
});
|
||||
});
|
||||
templates.forEach((template) => this._compileTemplate(template));
|
||||
@ -353,7 +382,6 @@ class ModuleBoundCompiler implements Compiler {
|
||||
return this._delegate.getNgContentSelectors(component);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears all caches
|
||||
*/
|
||||
@ -364,3 +392,15 @@ class ModuleBoundCompiler implements Compiler {
|
||||
*/
|
||||
clearCacheFor(type: Type<any>) { this._delegate.clearCacheFor(type); }
|
||||
}
|
||||
|
||||
|
||||
function flattenSummaries(fn: () => any[], out: CompileTypeSummary[] = []): CompileTypeSummary[] {
|
||||
fn().forEach((entry) => {
|
||||
if (typeof entry === 'function') {
|
||||
flattenSummaries(entry, out);
|
||||
} else {
|
||||
out.push(entry);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import {COMPILER_OPTIONS, Compiler, CompilerFactory, CompilerOptions, Inject, InjectionToken, MissingTranslationStrategy, Optional, PLATFORM_INITIALIZER, PlatformRef, Provider, ReflectiveInjector, TRANSLATIONS, TRANSLATIONS_FORMAT, Type, ViewEncapsulation, createPlatformFactory, isDevMode, platformCore, ɵConsole as Console, ɵReflectionCapabilities as ReflectionCapabilities, ɵReflector as Reflector, ɵReflectorReader as ReflectorReader, ɵreflector as reflector} from '@angular/core';
|
||||
|
||||
import {CompilerConfig} from '../config';
|
||||
import {DirectiveNormalizer} from '../directive_normalizer';
|
||||
import {DirectiveResolver} from '../directive_resolver';
|
||||
@ -23,7 +24,7 @@ import {ResourceLoader} from '../resource_loader';
|
||||
import {DomElementSchemaRegistry} from '../schema/dom_element_schema_registry';
|
||||
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
|
||||
import {StyleCompiler} from '../style_compiler';
|
||||
import {SummaryResolver} from '../summary_resolver';
|
||||
import {JitSummaryResolver, SummaryResolver} from '../summary_resolver';
|
||||
import {TemplateParser} from '../template_parser/template_parser';
|
||||
import {DEFAULT_PACKAGE_URL_PROVIDER, UrlResolver} from '../url_resolver';
|
||||
import {ViewCompiler} from '../view_compiler/view_compiler';
|
||||
@ -38,13 +39,6 @@ const _NO_RESOURCE_LOADER: ResourceLoader = {
|
||||
|
||||
const baseHtmlParser = new InjectionToken('HtmlParser');
|
||||
|
||||
export function i18nHtmlParserFactory(
|
||||
parser: HtmlParser, translations: string, format: string, config: CompilerConfig,
|
||||
console: Console): i18n.I18NHtmlParser {
|
||||
return new i18n.I18NHtmlParser(
|
||||
parser, translations, format, config.missingTranslation !, console);
|
||||
}
|
||||
|
||||
/**
|
||||
* A set of providers that provide `JitCompiler` and its dependencies to use for
|
||||
* template compilation.
|
||||
@ -53,7 +47,8 @@ export const COMPILER_PROVIDERS: Array<any|Type<any>|{[k: string]: any}|any[]> =
|
||||
{provide: Reflector, useValue: reflector},
|
||||
{provide: ReflectorReader, useExisting: Reflector},
|
||||
{provide: ResourceLoader, useValue: _NO_RESOURCE_LOADER},
|
||||
SummaryResolver,
|
||||
JitSummaryResolver,
|
||||
{provide: SummaryResolver, useExisting: JitSummaryResolver},
|
||||
Console,
|
||||
Lexer,
|
||||
Parser,
|
||||
@ -63,7 +58,10 @@ export const COMPILER_PROVIDERS: Array<any|Type<any>|{[k: string]: any}|any[]> =
|
||||
},
|
||||
{
|
||||
provide: i18n.I18NHtmlParser,
|
||||
useFactory: i18nHtmlParserFactory,
|
||||
useFactory: (parser: HtmlParser, translations: string, format: string, config: CompilerConfig,
|
||||
console: Console) =>
|
||||
new i18n.I18NHtmlParser(
|
||||
parser, translations, format, config.missingTranslation !, console),
|
||||
deps: [
|
||||
baseHtmlParser,
|
||||
[new Optional(), new Inject(TRANSLATIONS)],
|
||||
|
@ -167,8 +167,7 @@ export class CompileMetadataResolver {
|
||||
return typeSummary && typeSummary.summaryKind === kind ? typeSummary : null;
|
||||
}
|
||||
|
||||
private _loadDirectiveMetadata(ngModuleType: any, directiveType: any, isSync: boolean):
|
||||
Promise<any>|null {
|
||||
loadDirectiveMetadata(ngModuleType: any, directiveType: any, isSync: boolean): Promise<any>|null {
|
||||
if (this._directiveCache.has(directiveType)) {
|
||||
return null;
|
||||
}
|
||||
@ -377,9 +376,20 @@ export class CompileMetadataResolver {
|
||||
return dirSummary;
|
||||
}
|
||||
|
||||
isDirective(type: any) { return this._directiveResolver.isDirective(type); }
|
||||
isDirective(type: any) {
|
||||
return !!this._loadSummary(type, cpl.CompileSummaryKind.Directive) ||
|
||||
this._directiveResolver.isDirective(type);
|
||||
}
|
||||
|
||||
isPipe(type: any) { return this._pipeResolver.isPipe(type); }
|
||||
isPipe(type: any) {
|
||||
return !!this._loadSummary(type, cpl.CompileSummaryKind.Pipe) ||
|
||||
this._pipeResolver.isPipe(type);
|
||||
}
|
||||
|
||||
isNgModule(type: any) {
|
||||
return !!this._loadSummary(type, cpl.CompileSummaryKind.NgModule) ||
|
||||
this._ngModuleResolver.isNgModule(type);
|
||||
}
|
||||
|
||||
getNgModuleSummary(moduleType: any): cpl.CompileNgModuleSummary|null {
|
||||
let moduleSummary: cpl.CompileNgModuleSummary|null =
|
||||
@ -403,7 +413,7 @@ export class CompileMetadataResolver {
|
||||
const loading: Promise<any>[] = [];
|
||||
if (ngModule) {
|
||||
ngModule.declaredDirectives.forEach((id) => {
|
||||
const promise = this._loadDirectiveMetadata(moduleType, id.reference, isSync);
|
||||
const promise = this.loadDirectiveMetadata(moduleType, id.reference, isSync);
|
||||
if (promise) {
|
||||
loading.push(promise);
|
||||
}
|
||||
@ -501,11 +511,11 @@ export class CompileMetadataResolver {
|
||||
return;
|
||||
}
|
||||
const declaredIdentifier = this._getIdentifierMetadata(declaredType);
|
||||
if (this._directiveResolver.isDirective(declaredType)) {
|
||||
if (this.isDirective(declaredType)) {
|
||||
transitiveModule.addDirective(declaredIdentifier);
|
||||
declaredDirectives.push(declaredIdentifier);
|
||||
this._addTypeToModule(declaredType, moduleType);
|
||||
} else if (this._pipeResolver.isPipe(declaredType)) {
|
||||
} else if (this.isPipe(declaredType)) {
|
||||
transitiveModule.addPipe(declaredIdentifier);
|
||||
transitiveModule.pipes.push(declaredIdentifier);
|
||||
declaredPipes.push(declaredIdentifier);
|
||||
@ -604,15 +614,15 @@ export class CompileMetadataResolver {
|
||||
}
|
||||
|
||||
private _getTypeDescriptor(type: Type<any>): string {
|
||||
if (this._directiveResolver.isDirective(type)) {
|
||||
if (this.isDirective(type)) {
|
||||
return 'directive';
|
||||
}
|
||||
|
||||
if (this._pipeResolver.isPipe(type)) {
|
||||
if (this.isPipe(type)) {
|
||||
return 'pipe';
|
||||
}
|
||||
|
||||
if (this._ngModuleResolver.isNgModule(type)) {
|
||||
if (this.isNgModule(type)) {
|
||||
return 'module';
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
* 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 {Type} from '@angular/core';
|
||||
import {CompileTypeSummary} from './compile_metadata';
|
||||
import {CompilerInjectable} from './injectable';
|
||||
|
||||
@ -14,11 +15,25 @@ export interface Summary<T> {
|
||||
type?: CompileTypeSummary;
|
||||
}
|
||||
|
||||
export abstract class SummaryResolver<T> {
|
||||
abstract isLibraryFile(fileName: string): boolean;
|
||||
abstract getLibraryFileName(fileName: string): string|null;
|
||||
abstract resolveSummary(reference: T): Summary<T>|null;
|
||||
abstract getSymbolsOf(filePath: string): T[];
|
||||
abstract getImportAs(reference: T): T;
|
||||
abstract addSummary(summary: Summary<T>): void;
|
||||
}
|
||||
|
||||
@CompilerInjectable()
|
||||
export class SummaryResolver<T> {
|
||||
export class JitSummaryResolver implements SummaryResolver<Type<any>> {
|
||||
private _summaries = new Map<Type<any>, Summary<Type<any>>>();
|
||||
|
||||
isLibraryFile(fileName: string): boolean { return false; };
|
||||
getLibraryFileName(fileName: string): string|null { return null; }
|
||||
resolveSummary(reference: T): Summary<T>|null { return null; };
|
||||
getSymbolsOf(filePath: string): T[] { return []; }
|
||||
getImportAs(reference: T): T { return reference; }
|
||||
resolveSummary(reference: Type<any>): Summary<Type<any>>|null {
|
||||
return this._summaries.get(reference) || null;
|
||||
};
|
||||
getSymbolsOf(filePath: string): Type<any>[] { return []; }
|
||||
getImportAs(reference: Type<any>): Type<any> { return reference; }
|
||||
addSummary(summary: Summary<Type<any>>) { this._summaries.set(summary.symbol, summary); };
|
||||
}
|
||||
|
Reference in New Issue
Block a user