746 lines
23 KiB
TypeScript
746 lines
23 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google Inc. 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 {StaticSymbol} from './aot/static_symbol';
|
|
import {ChangeDetectionStrategy, SchemaMetadata, Type, ViewEncapsulation} from './core';
|
|
import {LifecycleHooks} from './lifecycle_reflector';
|
|
import {ParseTreeResult as HtmlParseTreeResult} from './ml_parser/parser';
|
|
import {splitAtColon, stringify} from './util';
|
|
|
|
// group 0: "[prop] or (event) or @trigger"
|
|
// group 1: "prop" from "[prop]"
|
|
// group 2: "event" from "(event)"
|
|
// group 3: "@trigger" from "@trigger"
|
|
const HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))|(\@[-\w]+)$/;
|
|
|
|
export function sanitizeIdentifier(name: string): string {
|
|
return name.replace(/\W/g, '_');
|
|
}
|
|
|
|
let _anonymousTypeIndex = 0;
|
|
|
|
export function identifierName(compileIdentifier: CompileIdentifierMetadata | null | undefined):
|
|
string|null {
|
|
if (!compileIdentifier || !compileIdentifier.reference) {
|
|
return null;
|
|
}
|
|
const ref = compileIdentifier.reference;
|
|
if (ref instanceof StaticSymbol) {
|
|
return ref.name;
|
|
}
|
|
if (ref['__anonymousType']) {
|
|
return ref['__anonymousType'];
|
|
}
|
|
let identifier = stringify(ref);
|
|
if (identifier.indexOf('(') >= 0) {
|
|
// case: anonymous functions!
|
|
identifier = `anonymous_${_anonymousTypeIndex++}`;
|
|
ref['__anonymousType'] = identifier;
|
|
} else {
|
|
identifier = sanitizeIdentifier(identifier);
|
|
}
|
|
return identifier;
|
|
}
|
|
|
|
export function identifierModuleUrl(compileIdentifier: CompileIdentifierMetadata): string {
|
|
const ref = compileIdentifier.reference;
|
|
if (ref instanceof StaticSymbol) {
|
|
return ref.filePath;
|
|
}
|
|
// Runtime type
|
|
return `./${stringify(ref)}`;
|
|
}
|
|
|
|
export function viewClassName(compType: any, embeddedTemplateIndex: number): string {
|
|
return `View_${identifierName({reference: compType})}_${embeddedTemplateIndex}`;
|
|
}
|
|
|
|
export function rendererTypeName(compType: any): string {
|
|
return `RenderType_${identifierName({reference: compType})}`;
|
|
}
|
|
|
|
export function hostViewClassName(compType: any): string {
|
|
return `HostView_${identifierName({reference: compType})}`;
|
|
}
|
|
|
|
export function componentFactoryName(compType: any): string {
|
|
return `${identifierName({reference: compType})}NgFactory`;
|
|
}
|
|
|
|
export interface ProxyClass { setDelegate(delegate: any): void; }
|
|
|
|
export interface CompileIdentifierMetadata { reference: any; }
|
|
|
|
export enum CompileSummaryKind {
|
|
Pipe,
|
|
Directive,
|
|
NgModule,
|
|
Injectable
|
|
}
|
|
|
|
/**
|
|
* A CompileSummary is the data needed to use a directive / pipe / module
|
|
* in other modules / components. However, this data is not enough to compile
|
|
* the directive / module itself.
|
|
*/
|
|
export interface CompileTypeSummary {
|
|
summaryKind: CompileSummaryKind|null;
|
|
type: CompileTypeMetadata;
|
|
}
|
|
|
|
export interface CompileDiDependencyMetadata {
|
|
isAttribute?: boolean;
|
|
isSelf?: boolean;
|
|
isHost?: boolean;
|
|
isSkipSelf?: boolean;
|
|
isOptional?: boolean;
|
|
isValue?: boolean;
|
|
token?: CompileTokenMetadata;
|
|
value?: any;
|
|
}
|
|
|
|
export interface CompileProviderMetadata {
|
|
token: CompileTokenMetadata;
|
|
useClass?: CompileTypeMetadata;
|
|
useValue?: any;
|
|
useExisting?: CompileTokenMetadata;
|
|
useFactory?: CompileFactoryMetadata;
|
|
deps?: CompileDiDependencyMetadata[];
|
|
multi?: boolean;
|
|
}
|
|
|
|
export interface CompileFactoryMetadata extends CompileIdentifierMetadata {
|
|
diDeps: CompileDiDependencyMetadata[];
|
|
reference: any;
|
|
}
|
|
|
|
export function tokenName(token: CompileTokenMetadata) {
|
|
return token.value != null ? sanitizeIdentifier(token.value) : identifierName(token.identifier);
|
|
}
|
|
|
|
export function tokenReference(token: CompileTokenMetadata) {
|
|
if (token.identifier != null) {
|
|
return token.identifier.reference;
|
|
} else {
|
|
return token.value;
|
|
}
|
|
}
|
|
|
|
export interface CompileTokenMetadata {
|
|
value?: any;
|
|
identifier?: CompileIdentifierMetadata|CompileTypeMetadata;
|
|
}
|
|
|
|
export interface CompileInjectableMetadata {
|
|
symbol: StaticSymbol;
|
|
type: CompileTypeMetadata;
|
|
|
|
providedIn?: StaticSymbol;
|
|
|
|
useValue?: any;
|
|
useClass?: StaticSymbol;
|
|
useExisting?: StaticSymbol;
|
|
useFactory?: StaticSymbol;
|
|
deps?: any[];
|
|
}
|
|
|
|
/**
|
|
* Metadata regarding compilation of a type.
|
|
*/
|
|
export interface CompileTypeMetadata extends CompileIdentifierMetadata {
|
|
diDeps: CompileDiDependencyMetadata[];
|
|
lifecycleHooks: LifecycleHooks[];
|
|
reference: any;
|
|
}
|
|
|
|
export interface CompileQueryMetadata {
|
|
selectors: Array<CompileTokenMetadata>;
|
|
descendants: boolean;
|
|
first: boolean;
|
|
propertyName: string;
|
|
read: CompileTokenMetadata;
|
|
static?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Metadata about a stylesheet
|
|
*/
|
|
export class CompileStylesheetMetadata {
|
|
moduleUrl: string|null;
|
|
styles: string[];
|
|
styleUrls: string[];
|
|
constructor(
|
|
{moduleUrl, styles,
|
|
styleUrls}: {moduleUrl?: string, styles?: string[], styleUrls?: string[]} = {}) {
|
|
this.moduleUrl = moduleUrl || null;
|
|
this.styles = _normalizeArray(styles);
|
|
this.styleUrls = _normalizeArray(styleUrls);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Summary Metadata regarding compilation of a template.
|
|
*/
|
|
export interface CompileTemplateSummary {
|
|
ngContentSelectors: string[];
|
|
encapsulation: ViewEncapsulation|null;
|
|
styles: string[];
|
|
animations: any[]|null;
|
|
}
|
|
|
|
/**
|
|
* Metadata regarding compilation of a template.
|
|
*/
|
|
export class CompileTemplateMetadata {
|
|
encapsulation: ViewEncapsulation|null;
|
|
template: string|null;
|
|
templateUrl: string|null;
|
|
htmlAst: HtmlParseTreeResult|null;
|
|
isInline: boolean;
|
|
styles: string[];
|
|
styleUrls: string[];
|
|
externalStylesheets: CompileStylesheetMetadata[];
|
|
animations: any[];
|
|
ngContentSelectors: string[];
|
|
interpolation: [string, string]|null;
|
|
preserveWhitespaces: boolean;
|
|
constructor({encapsulation, template, templateUrl, htmlAst, styles, styleUrls,
|
|
externalStylesheets, animations, ngContentSelectors, interpolation, isInline,
|
|
preserveWhitespaces}: {
|
|
encapsulation: ViewEncapsulation | null,
|
|
template: string|null,
|
|
templateUrl: string|null,
|
|
htmlAst: HtmlParseTreeResult|null,
|
|
styles: string[],
|
|
styleUrls: string[],
|
|
externalStylesheets: CompileStylesheetMetadata[],
|
|
ngContentSelectors: string[],
|
|
animations: any[],
|
|
interpolation: [string, string]|null,
|
|
isInline: boolean,
|
|
preserveWhitespaces: boolean
|
|
}) {
|
|
this.encapsulation = encapsulation;
|
|
this.template = template;
|
|
this.templateUrl = templateUrl;
|
|
this.htmlAst = htmlAst;
|
|
this.styles = _normalizeArray(styles);
|
|
this.styleUrls = _normalizeArray(styleUrls);
|
|
this.externalStylesheets = _normalizeArray(externalStylesheets);
|
|
this.animations = animations ? flatten(animations) : [];
|
|
this.ngContentSelectors = ngContentSelectors || [];
|
|
if (interpolation && interpolation.length != 2) {
|
|
throw new Error(`'interpolation' should have a start and an end symbol.`);
|
|
}
|
|
this.interpolation = interpolation;
|
|
this.isInline = isInline;
|
|
this.preserveWhitespaces = preserveWhitespaces;
|
|
}
|
|
|
|
toSummary(): CompileTemplateSummary {
|
|
return {
|
|
ngContentSelectors: this.ngContentSelectors,
|
|
encapsulation: this.encapsulation,
|
|
styles: this.styles,
|
|
animations: this.animations
|
|
};
|
|
}
|
|
}
|
|
|
|
export interface CompileEntryComponentMetadata {
|
|
componentType: any;
|
|
componentFactory: StaticSymbol|object;
|
|
}
|
|
|
|
// Note: This should only use interfaces as nested data types
|
|
// as we need to be able to serialize this from/to JSON!
|
|
export interface CompileDirectiveSummary extends CompileTypeSummary {
|
|
type: CompileTypeMetadata;
|
|
isComponent: boolean;
|
|
selector: string|null;
|
|
exportAs: string|null;
|
|
inputs: {[key: string]: string};
|
|
outputs: {[key: string]: string};
|
|
hostListeners: {[key: string]: string};
|
|
hostProperties: {[key: string]: string};
|
|
hostAttributes: {[key: string]: string};
|
|
providers: CompileProviderMetadata[];
|
|
viewProviders: CompileProviderMetadata[];
|
|
queries: CompileQueryMetadata[];
|
|
guards: {[key: string]: any};
|
|
viewQueries: CompileQueryMetadata[];
|
|
entryComponents: CompileEntryComponentMetadata[];
|
|
changeDetection: ChangeDetectionStrategy|null;
|
|
template: CompileTemplateSummary|null;
|
|
componentViewType: StaticSymbol|ProxyClass|null;
|
|
rendererType: StaticSymbol|object|null;
|
|
componentFactory: StaticSymbol|object|null;
|
|
}
|
|
|
|
/**
|
|
* Metadata regarding compilation of a directive.
|
|
*/
|
|
export class CompileDirectiveMetadata {
|
|
static create({isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs,
|
|
host, providers, viewProviders, queries, guards, viewQueries, entryComponents,
|
|
template, componentViewType, rendererType, componentFactory}: {
|
|
isHost: boolean,
|
|
type: CompileTypeMetadata,
|
|
isComponent: boolean,
|
|
selector: string|null,
|
|
exportAs: string|null,
|
|
changeDetection: ChangeDetectionStrategy|null,
|
|
inputs: string[],
|
|
outputs: string[],
|
|
host: {[key: string]: string},
|
|
providers: CompileProviderMetadata[],
|
|
viewProviders: CompileProviderMetadata[],
|
|
queries: CompileQueryMetadata[],
|
|
guards: {[key: string]: any};
|
|
viewQueries: CompileQueryMetadata[],
|
|
entryComponents: CompileEntryComponentMetadata[],
|
|
template: CompileTemplateMetadata,
|
|
componentViewType: StaticSymbol|ProxyClass|null,
|
|
rendererType: StaticSymbol|object|null,
|
|
componentFactory: StaticSymbol|object|null,
|
|
}): CompileDirectiveMetadata {
|
|
const hostListeners: {[key: string]: string} = {};
|
|
const hostProperties: {[key: string]: string} = {};
|
|
const hostAttributes: {[key: string]: string} = {};
|
|
if (host != null) {
|
|
Object.keys(host).forEach(key => {
|
|
const value = host[key];
|
|
const matches = key.match(HOST_REG_EXP);
|
|
if (matches === null) {
|
|
hostAttributes[key] = value;
|
|
} else if (matches[1] != null) {
|
|
hostProperties[matches[1]] = value;
|
|
} else if (matches[2] != null) {
|
|
hostListeners[matches[2]] = value;
|
|
}
|
|
});
|
|
}
|
|
const inputsMap: {[key: string]: string} = {};
|
|
if (inputs != null) {
|
|
inputs.forEach((bindConfig: string) => {
|
|
// canonical syntax: `dirProp: elProp`
|
|
// if there is no `:`, use dirProp = elProp
|
|
const parts = splitAtColon(bindConfig, [bindConfig, bindConfig]);
|
|
inputsMap[parts[0]] = parts[1];
|
|
});
|
|
}
|
|
const outputsMap: {[key: string]: string} = {};
|
|
if (outputs != null) {
|
|
outputs.forEach((bindConfig: string) => {
|
|
// canonical syntax: `dirProp: elProp`
|
|
// if there is no `:`, use dirProp = elProp
|
|
const parts = splitAtColon(bindConfig, [bindConfig, bindConfig]);
|
|
outputsMap[parts[0]] = parts[1];
|
|
});
|
|
}
|
|
|
|
return new CompileDirectiveMetadata({
|
|
isHost,
|
|
type,
|
|
isComponent: !!isComponent, selector, exportAs, changeDetection,
|
|
inputs: inputsMap,
|
|
outputs: outputsMap,
|
|
hostListeners,
|
|
hostProperties,
|
|
hostAttributes,
|
|
providers,
|
|
viewProviders,
|
|
queries,
|
|
guards,
|
|
viewQueries,
|
|
entryComponents,
|
|
template,
|
|
componentViewType,
|
|
rendererType,
|
|
componentFactory,
|
|
});
|
|
}
|
|
isHost: boolean;
|
|
type: CompileTypeMetadata;
|
|
isComponent: boolean;
|
|
selector: string|null;
|
|
exportAs: string|null;
|
|
changeDetection: ChangeDetectionStrategy|null;
|
|
inputs: {[key: string]: string};
|
|
outputs: {[key: string]: string};
|
|
hostListeners: {[key: string]: string};
|
|
hostProperties: {[key: string]: string};
|
|
hostAttributes: {[key: string]: string};
|
|
providers: CompileProviderMetadata[];
|
|
viewProviders: CompileProviderMetadata[];
|
|
queries: CompileQueryMetadata[];
|
|
guards: {[key: string]: any};
|
|
viewQueries: CompileQueryMetadata[];
|
|
entryComponents: CompileEntryComponentMetadata[];
|
|
|
|
template: CompileTemplateMetadata|null;
|
|
|
|
componentViewType: StaticSymbol|ProxyClass|null;
|
|
rendererType: StaticSymbol|object|null;
|
|
componentFactory: StaticSymbol|object|null;
|
|
|
|
constructor({isHost,
|
|
type,
|
|
isComponent,
|
|
selector,
|
|
exportAs,
|
|
changeDetection,
|
|
inputs,
|
|
outputs,
|
|
hostListeners,
|
|
hostProperties,
|
|
hostAttributes,
|
|
providers,
|
|
viewProviders,
|
|
queries,
|
|
guards,
|
|
viewQueries,
|
|
entryComponents,
|
|
template,
|
|
componentViewType,
|
|
rendererType,
|
|
componentFactory}: {
|
|
isHost: boolean,
|
|
type: CompileTypeMetadata,
|
|
isComponent: boolean,
|
|
selector: string|null,
|
|
exportAs: string|null,
|
|
changeDetection: ChangeDetectionStrategy|null,
|
|
inputs: {[key: string]: string},
|
|
outputs: {[key: string]: string},
|
|
hostListeners: {[key: string]: string},
|
|
hostProperties: {[key: string]: string},
|
|
hostAttributes: {[key: string]: string},
|
|
providers: CompileProviderMetadata[],
|
|
viewProviders: CompileProviderMetadata[],
|
|
queries: CompileQueryMetadata[],
|
|
guards: {[key: string]: any},
|
|
viewQueries: CompileQueryMetadata[],
|
|
entryComponents: CompileEntryComponentMetadata[],
|
|
template: CompileTemplateMetadata|null,
|
|
componentViewType: StaticSymbol|ProxyClass|null,
|
|
rendererType: StaticSymbol|object|null,
|
|
componentFactory: StaticSymbol|object|null,
|
|
}) {
|
|
this.isHost = !!isHost;
|
|
this.type = type;
|
|
this.isComponent = isComponent;
|
|
this.selector = selector;
|
|
this.exportAs = exportAs;
|
|
this.changeDetection = changeDetection;
|
|
this.inputs = inputs;
|
|
this.outputs = outputs;
|
|
this.hostListeners = hostListeners;
|
|
this.hostProperties = hostProperties;
|
|
this.hostAttributes = hostAttributes;
|
|
this.providers = _normalizeArray(providers);
|
|
this.viewProviders = _normalizeArray(viewProviders);
|
|
this.queries = _normalizeArray(queries);
|
|
this.guards = guards;
|
|
this.viewQueries = _normalizeArray(viewQueries);
|
|
this.entryComponents = _normalizeArray(entryComponents);
|
|
this.template = template;
|
|
|
|
this.componentViewType = componentViewType;
|
|
this.rendererType = rendererType;
|
|
this.componentFactory = componentFactory;
|
|
}
|
|
|
|
toSummary(): CompileDirectiveSummary {
|
|
return {
|
|
summaryKind: CompileSummaryKind.Directive,
|
|
type: this.type,
|
|
isComponent: this.isComponent,
|
|
selector: this.selector,
|
|
exportAs: this.exportAs,
|
|
inputs: this.inputs,
|
|
outputs: this.outputs,
|
|
hostListeners: this.hostListeners,
|
|
hostProperties: this.hostProperties,
|
|
hostAttributes: this.hostAttributes,
|
|
providers: this.providers,
|
|
viewProviders: this.viewProviders,
|
|
queries: this.queries,
|
|
guards: this.guards,
|
|
viewQueries: this.viewQueries,
|
|
entryComponents: this.entryComponents,
|
|
changeDetection: this.changeDetection,
|
|
template: this.template && this.template.toSummary(),
|
|
componentViewType: this.componentViewType,
|
|
rendererType: this.rendererType,
|
|
componentFactory: this.componentFactory
|
|
};
|
|
}
|
|
}
|
|
|
|
export interface CompilePipeSummary extends CompileTypeSummary {
|
|
type: CompileTypeMetadata;
|
|
name: string;
|
|
pure: boolean;
|
|
}
|
|
|
|
export class CompilePipeMetadata {
|
|
type: CompileTypeMetadata;
|
|
name: string;
|
|
pure: boolean;
|
|
|
|
constructor({type, name, pure}: {
|
|
type: CompileTypeMetadata,
|
|
name: string,
|
|
pure: boolean,
|
|
}) {
|
|
this.type = type;
|
|
this.name = name;
|
|
this.pure = !!pure;
|
|
}
|
|
|
|
toSummary(): CompilePipeSummary {
|
|
return {
|
|
summaryKind: CompileSummaryKind.Pipe,
|
|
type: this.type,
|
|
name: this.name,
|
|
pure: this.pure
|
|
};
|
|
}
|
|
}
|
|
|
|
// Note: This should only use interfaces as nested data types
|
|
// as we need to be able to serialize this from/to JSON!
|
|
export interface CompileNgModuleSummary extends CompileTypeSummary {
|
|
type: CompileTypeMetadata;
|
|
|
|
// Note: This is transitive over the exported modules.
|
|
exportedDirectives: CompileIdentifierMetadata[];
|
|
// Note: This is transitive over the exported modules.
|
|
exportedPipes: CompileIdentifierMetadata[];
|
|
|
|
// Note: This is transitive.
|
|
entryComponents: CompileEntryComponentMetadata[];
|
|
// Note: This is transitive.
|
|
providers: {provider: CompileProviderMetadata, module: CompileIdentifierMetadata}[];
|
|
// Note: This is transitive.
|
|
modules: CompileTypeMetadata[];
|
|
}
|
|
|
|
export class CompileShallowModuleMetadata {
|
|
// TODO(issue/24571): remove '!'.
|
|
type !: CompileTypeMetadata;
|
|
|
|
rawExports: any;
|
|
rawImports: any;
|
|
rawProviders: any;
|
|
}
|
|
|
|
/**
|
|
* Metadata regarding compilation of a module.
|
|
*/
|
|
export class CompileNgModuleMetadata {
|
|
type: CompileTypeMetadata;
|
|
declaredDirectives: CompileIdentifierMetadata[];
|
|
exportedDirectives: CompileIdentifierMetadata[];
|
|
declaredPipes: CompileIdentifierMetadata[];
|
|
|
|
exportedPipes: CompileIdentifierMetadata[];
|
|
entryComponents: CompileEntryComponentMetadata[];
|
|
bootstrapComponents: CompileIdentifierMetadata[];
|
|
providers: CompileProviderMetadata[];
|
|
|
|
importedModules: CompileNgModuleSummary[];
|
|
exportedModules: CompileNgModuleSummary[];
|
|
schemas: SchemaMetadata[];
|
|
id: string|null;
|
|
|
|
transitiveModule: TransitiveCompileNgModuleMetadata;
|
|
|
|
constructor({type, providers, declaredDirectives, exportedDirectives, declaredPipes,
|
|
exportedPipes, entryComponents, bootstrapComponents, importedModules,
|
|
exportedModules, schemas, transitiveModule, id}: {
|
|
type: CompileTypeMetadata,
|
|
providers: CompileProviderMetadata[],
|
|
declaredDirectives: CompileIdentifierMetadata[],
|
|
exportedDirectives: CompileIdentifierMetadata[],
|
|
declaredPipes: CompileIdentifierMetadata[],
|
|
exportedPipes: CompileIdentifierMetadata[],
|
|
entryComponents: CompileEntryComponentMetadata[],
|
|
bootstrapComponents: CompileIdentifierMetadata[],
|
|
importedModules: CompileNgModuleSummary[],
|
|
exportedModules: CompileNgModuleSummary[],
|
|
transitiveModule: TransitiveCompileNgModuleMetadata,
|
|
schemas: SchemaMetadata[],
|
|
id: string|null
|
|
}) {
|
|
this.type = type || null;
|
|
this.declaredDirectives = _normalizeArray(declaredDirectives);
|
|
this.exportedDirectives = _normalizeArray(exportedDirectives);
|
|
this.declaredPipes = _normalizeArray(declaredPipes);
|
|
this.exportedPipes = _normalizeArray(exportedPipes);
|
|
this.providers = _normalizeArray(providers);
|
|
this.entryComponents = _normalizeArray(entryComponents);
|
|
this.bootstrapComponents = _normalizeArray(bootstrapComponents);
|
|
this.importedModules = _normalizeArray(importedModules);
|
|
this.exportedModules = _normalizeArray(exportedModules);
|
|
this.schemas = _normalizeArray(schemas);
|
|
this.id = id || null;
|
|
this.transitiveModule = transitiveModule || null;
|
|
}
|
|
|
|
toSummary(): CompileNgModuleSummary {
|
|
const module = this.transitiveModule !;
|
|
return {
|
|
summaryKind: CompileSummaryKind.NgModule,
|
|
type: this.type,
|
|
entryComponents: module.entryComponents,
|
|
providers: module.providers,
|
|
modules: module.modules,
|
|
exportedDirectives: module.exportedDirectives,
|
|
exportedPipes: module.exportedPipes
|
|
};
|
|
}
|
|
}
|
|
|
|
export class TransitiveCompileNgModuleMetadata {
|
|
directivesSet = new Set<any>();
|
|
directives: CompileIdentifierMetadata[] = [];
|
|
exportedDirectivesSet = new Set<any>();
|
|
exportedDirectives: CompileIdentifierMetadata[] = [];
|
|
pipesSet = new Set<any>();
|
|
pipes: CompileIdentifierMetadata[] = [];
|
|
exportedPipesSet = new Set<any>();
|
|
exportedPipes: CompileIdentifierMetadata[] = [];
|
|
modulesSet = new Set<any>();
|
|
modules: CompileTypeMetadata[] = [];
|
|
entryComponentsSet = new Set<any>();
|
|
entryComponents: CompileEntryComponentMetadata[] = [];
|
|
|
|
providers: {provider: CompileProviderMetadata, module: CompileIdentifierMetadata}[] = [];
|
|
|
|
addProvider(provider: CompileProviderMetadata, module: CompileIdentifierMetadata) {
|
|
this.providers.push({provider: provider, module: module});
|
|
}
|
|
|
|
addDirective(id: CompileIdentifierMetadata) {
|
|
if (!this.directivesSet.has(id.reference)) {
|
|
this.directivesSet.add(id.reference);
|
|
this.directives.push(id);
|
|
}
|
|
}
|
|
addExportedDirective(id: CompileIdentifierMetadata) {
|
|
if (!this.exportedDirectivesSet.has(id.reference)) {
|
|
this.exportedDirectivesSet.add(id.reference);
|
|
this.exportedDirectives.push(id);
|
|
}
|
|
}
|
|
addPipe(id: CompileIdentifierMetadata) {
|
|
if (!this.pipesSet.has(id.reference)) {
|
|
this.pipesSet.add(id.reference);
|
|
this.pipes.push(id);
|
|
}
|
|
}
|
|
addExportedPipe(id: CompileIdentifierMetadata) {
|
|
if (!this.exportedPipesSet.has(id.reference)) {
|
|
this.exportedPipesSet.add(id.reference);
|
|
this.exportedPipes.push(id);
|
|
}
|
|
}
|
|
addModule(id: CompileTypeMetadata) {
|
|
if (!this.modulesSet.has(id.reference)) {
|
|
this.modulesSet.add(id.reference);
|
|
this.modules.push(id);
|
|
}
|
|
}
|
|
addEntryComponent(ec: CompileEntryComponentMetadata) {
|
|
if (!this.entryComponentsSet.has(ec.componentType)) {
|
|
this.entryComponentsSet.add(ec.componentType);
|
|
this.entryComponents.push(ec);
|
|
}
|
|
}
|
|
}
|
|
|
|
function _normalizeArray(obj: any[] | undefined | null): any[] {
|
|
return obj || [];
|
|
}
|
|
|
|
export class ProviderMeta {
|
|
token: any;
|
|
useClass: Type|null;
|
|
useValue: any;
|
|
useExisting: any;
|
|
useFactory: Function|null;
|
|
dependencies: Object[]|null;
|
|
multi: boolean;
|
|
|
|
constructor(token: any, {useClass, useValue, useExisting, useFactory, deps, multi}: {
|
|
useClass?: Type,
|
|
useValue?: any,
|
|
useExisting?: any,
|
|
useFactory?: Function|null,
|
|
deps?: Object[]|null,
|
|
multi?: boolean
|
|
}) {
|
|
this.token = token;
|
|
this.useClass = useClass || null;
|
|
this.useValue = useValue;
|
|
this.useExisting = useExisting;
|
|
this.useFactory = useFactory || null;
|
|
this.dependencies = deps || null;
|
|
this.multi = !!multi;
|
|
}
|
|
}
|
|
|
|
export function flatten<T>(list: Array<T|T[]>): T[] {
|
|
return list.reduce((flat: any[], item: T | T[]): T[] => {
|
|
const flatItem = Array.isArray(item) ? flatten(item) : item;
|
|
return (<T[]>flat).concat(flatItem);
|
|
}, []);
|
|
}
|
|
|
|
function jitSourceUrl(url: string) {
|
|
// Note: We need 3 "/" so that ng shows up as a separate domain
|
|
// in the chrome dev tools.
|
|
return url.replace(/(\w+:\/\/[\w:-]+)?(\/+)?/, 'ng:///');
|
|
}
|
|
|
|
export function templateSourceUrl(
|
|
ngModuleType: CompileIdentifierMetadata, compMeta: {type: CompileIdentifierMetadata},
|
|
templateMeta: {isInline: boolean, templateUrl: string | null}) {
|
|
let url: string;
|
|
if (templateMeta.isInline) {
|
|
if (compMeta.type.reference instanceof StaticSymbol) {
|
|
// Note: a .ts file might contain multiple components with inline templates,
|
|
// so we need to give them unique urls, as these will be used for sourcemaps.
|
|
url = `${compMeta.type.reference.filePath}.${compMeta.type.reference.name}.html`;
|
|
} else {
|
|
url = `${identifierName(ngModuleType)}/${identifierName(compMeta.type)}.html`;
|
|
}
|
|
} else {
|
|
url = templateMeta.templateUrl !;
|
|
}
|
|
return compMeta.type.reference instanceof StaticSymbol ? url : jitSourceUrl(url);
|
|
}
|
|
|
|
export function sharedStylesheetJitUrl(meta: CompileStylesheetMetadata, id: number) {
|
|
const pathParts = meta.moduleUrl !.split(/\/\\/g);
|
|
const baseName = pathParts[pathParts.length - 1];
|
|
return jitSourceUrl(`css/${id}${baseName}.ngstyle.js`);
|
|
}
|
|
|
|
export function ngModuleJitUrl(moduleMeta: CompileNgModuleMetadata): string {
|
|
return jitSourceUrl(`${identifierName(moduleMeta.type)}/module.ngfactory.js`);
|
|
}
|
|
|
|
export function templateJitUrl(
|
|
ngModuleType: CompileIdentifierMetadata, compMeta: CompileDirectiveMetadata): string {
|
|
return jitSourceUrl(
|
|
`${identifierName(ngModuleType)}/${identifierName(compMeta.type)}.ngfactory.js`);
|
|
}
|