refactor(core): change module semantics
This contains major changes to the compiler, bootstrap of the platforms and test environment initialization. Main part of #10043 Closes #10164 BREAKING CHANGE: - Semantics and name of `@AppModule` (now `@NgModule`) changed quite a bit. This is actually not breaking as `@AppModules` were not part of rc.4. We will have detailed docs on `@NgModule` separately. - `coreLoadAndBootstrap` and `coreBootstrap` can't be used any more (without migration support). Use `bootstrapModule` / `bootstrapModuleFactory` instead. - All Components listed in routes have to be part of the `declarations` of an NgModule. Either directly on the bootstrap module / lazy loaded module, or in an NgModule imported by them.
This commit is contained in:
@ -22,139 +22,55 @@ import {sanitizeIdentifier, splitAtColon} from './util';
|
||||
// group 1: "prop" from "[prop]"
|
||||
// group 2: "event" from "(event)"
|
||||
// group 3: "@trigger" from "@trigger"
|
||||
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))|(\@[-\w]+)$/g;
|
||||
const HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))|(\@[-\w]+)$/g;
|
||||
const UNDEFINED = new Object();
|
||||
|
||||
export abstract class CompileMetadataWithIdentifier {
|
||||
abstract toJson(): {[key: string]: any};
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return <CompileIdentifierMetadata>unimplemented(); }
|
||||
}
|
||||
|
||||
export abstract class CompileMetadataWithType extends CompileMetadataWithIdentifier {
|
||||
abstract toJson(): {[key: string]: any};
|
||||
get runtimeCacheKey(): any { return unimplemented(); }
|
||||
|
||||
get type(): CompileTypeMetadata { return <CompileTypeMetadata>unimplemented(); }
|
||||
get assetCacheKey(): any { return unimplemented(); }
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return <CompileIdentifierMetadata>unimplemented(); }
|
||||
}
|
||||
|
||||
export function metadataFromJson(data: {[key: string]: any}): any {
|
||||
return (_COMPILE_METADATA_FROM_JSON as any)[data['class']](data);
|
||||
equalsTo(id2: CompileMetadataWithIdentifier): boolean { return unimplemented(); }
|
||||
}
|
||||
|
||||
export class CompileAnimationEntryMetadata {
|
||||
static fromJson(data: {[key: string]: any}): CompileAnimationEntryMetadata {
|
||||
var value = data['value'];
|
||||
var defs = _arrayFromJson(value['definitions'], metadataFromJson);
|
||||
return new CompileAnimationEntryMetadata(value['name'], defs);
|
||||
}
|
||||
|
||||
constructor(
|
||||
public name: string = null, public definitions: CompileAnimationStateMetadata[] = null) {}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'class': 'AnimationEntryMetadata',
|
||||
'value': {'name': this.name, 'definitions': _arrayToJson(this.definitions)}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class CompileAnimationStateMetadata {}
|
||||
|
||||
export class CompileAnimationStateDeclarationMetadata extends CompileAnimationStateMetadata {
|
||||
static fromJson(data: {[key: string]: any}): CompileAnimationStateDeclarationMetadata {
|
||||
var value = data['value'];
|
||||
var styles = _objFromJson(value['styles'], metadataFromJson);
|
||||
return new CompileAnimationStateDeclarationMetadata(value['stateNameExpr'], styles);
|
||||
}
|
||||
|
||||
constructor(public stateNameExpr: string, public styles: CompileAnimationStyleMetadata) {
|
||||
super();
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'class': 'AnimationStateDeclarationMetadata',
|
||||
'value': {'stateNameExpr': this.stateNameExpr, 'styles': this.styles.toJson()}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileAnimationStateTransitionMetadata extends CompileAnimationStateMetadata {
|
||||
static fromJson(data: {[key: string]: any}): CompileAnimationStateTransitionMetadata {
|
||||
var value = data['value'];
|
||||
var steps = _objFromJson(value['steps'], metadataFromJson);
|
||||
return new CompileAnimationStateTransitionMetadata(value['stateChangeExpr'], steps);
|
||||
}
|
||||
|
||||
constructor(public stateChangeExpr: string, public steps: CompileAnimationMetadata) { super(); }
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'class': 'AnimationStateTransitionMetadata',
|
||||
'value': {'stateChangeExpr': this.stateChangeExpr, 'steps': this.steps.toJson()}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class CompileAnimationMetadata { abstract toJson(): {[key: string]: any}; }
|
||||
export abstract class CompileAnimationMetadata {}
|
||||
|
||||
export class CompileAnimationKeyframesSequenceMetadata extends CompileAnimationMetadata {
|
||||
static fromJson(data: {[key: string]: any}): CompileAnimationKeyframesSequenceMetadata {
|
||||
var steps = _arrayFromJson(data['value'], metadataFromJson);
|
||||
return new CompileAnimationKeyframesSequenceMetadata(<CompileAnimationStyleMetadata[]>steps);
|
||||
}
|
||||
|
||||
constructor(public steps: CompileAnimationStyleMetadata[] = []) { super(); }
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {'class': 'AnimationKeyframesSequenceMetadata', 'value': _arrayToJson(this.steps)};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileAnimationStyleMetadata extends CompileAnimationMetadata {
|
||||
static fromJson(data: {[key: string]: any}): CompileAnimationStyleMetadata {
|
||||
var value = data['value'];
|
||||
var offsetVal = value['offset'];
|
||||
var offset = isPresent(offsetVal) ? NumberWrapper.parseFloat(offsetVal) : null;
|
||||
var styles = <Array<string|{[key: string]: string | number}>>value['styles'];
|
||||
return new CompileAnimationStyleMetadata(offset, styles);
|
||||
}
|
||||
|
||||
constructor(
|
||||
public offset: number, public styles: Array<string|{[key: string]: string | number}> = null) {
|
||||
super();
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'class': 'AnimationStyleMetadata',
|
||||
'value': {'offset': this.offset, 'styles': this.styles}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileAnimationAnimateMetadata extends CompileAnimationMetadata {
|
||||
static fromJson(data: {[key: string]: any}): CompileAnimationAnimateMetadata {
|
||||
var value = data['value'];
|
||||
var timings = <string|number>value['timings'];
|
||||
var styles = _objFromJson(value['styles'], metadataFromJson);
|
||||
return new CompileAnimationAnimateMetadata(timings, styles);
|
||||
}
|
||||
|
||||
constructor(
|
||||
public timings: string|number = 0, public styles: CompileAnimationStyleMetadata|
|
||||
CompileAnimationKeyframesSequenceMetadata = null) {
|
||||
super();
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'class': 'AnimationAnimateMetadata',
|
||||
'value': {'timings': this.timings, 'styles': _objToJson(this.styles)}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class CompileAnimationWithStepsMetadata extends CompileAnimationMetadata {
|
||||
@ -162,29 +78,11 @@ export abstract class CompileAnimationWithStepsMetadata extends CompileAnimation
|
||||
}
|
||||
|
||||
export class CompileAnimationSequenceMetadata extends CompileAnimationWithStepsMetadata {
|
||||
static fromJson(data: {[key: string]: any}): CompileAnimationSequenceMetadata {
|
||||
var steps = _arrayFromJson(data['value'], metadataFromJson);
|
||||
return new CompileAnimationSequenceMetadata(steps);
|
||||
}
|
||||
|
||||
constructor(steps: CompileAnimationMetadata[] = null) { super(steps); }
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {'class': 'AnimationSequenceMetadata', 'value': _arrayToJson(this.steps)};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileAnimationGroupMetadata extends CompileAnimationWithStepsMetadata {
|
||||
static fromJson(data: {[key: string]: any}): CompileAnimationGroupMetadata {
|
||||
var steps = _arrayFromJson(data['value'], metadataFromJson);
|
||||
return new CompileAnimationGroupMetadata(steps);
|
||||
}
|
||||
|
||||
constructor(steps: CompileAnimationMetadata[] = null) { super(steps); }
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {'class': 'AnimationGroupMetadata', 'value': _arrayToJson(this.steps)};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileIdentifierMetadata implements CompileMetadataWithIdentifier {
|
||||
@ -193,6 +91,7 @@ export class CompileIdentifierMetadata implements CompileMetadataWithIdentifier
|
||||
prefix: string;
|
||||
moduleUrl: string;
|
||||
value: any;
|
||||
private _assetCacheKey: any = UNDEFINED;
|
||||
|
||||
constructor(
|
||||
{runtime, name, moduleUrl, prefix, value}:
|
||||
@ -204,26 +103,28 @@ export class CompileIdentifierMetadata implements CompileMetadataWithIdentifier
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileIdentifierMetadata {
|
||||
let value = isArray(data['value']) ? _arrayFromJson(data['value'], metadataFromJson) :
|
||||
_objFromJson(data['value'], metadataFromJson);
|
||||
return new CompileIdentifierMetadata(
|
||||
{name: data['name'], prefix: data['prefix'], moduleUrl: data['moduleUrl'], value: value});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
let value = isArray(this.value) ? _arrayToJson(this.value) : _objToJson(this.value);
|
||||
return {
|
||||
// Note: Runtime type can't be serialized...
|
||||
'class': 'Identifier',
|
||||
'name': this.name,
|
||||
'moduleUrl': this.moduleUrl,
|
||||
'prefix': this.prefix,
|
||||
'value': value
|
||||
};
|
||||
}
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return this; }
|
||||
|
||||
get runtimeCacheKey(): any { return this.identifier.runtime; }
|
||||
|
||||
get assetCacheKey(): any {
|
||||
if (this._assetCacheKey === UNDEFINED) {
|
||||
if (isPresent(this.moduleUrl) && isPresent(getUrlScheme(this.moduleUrl))) {
|
||||
var uri = reflector.importUri({'filePath': this.moduleUrl, 'name': this.name});
|
||||
this._assetCacheKey = `${this.name}|${uri}`;
|
||||
} else {
|
||||
this._assetCacheKey = null;
|
||||
}
|
||||
}
|
||||
return this._assetCacheKey;
|
||||
}
|
||||
|
||||
equalsTo(id2: CompileIdentifierMetadata): boolean {
|
||||
var rk = this.runtimeCacheKey;
|
||||
var ak = this.assetCacheKey;
|
||||
return (isPresent(rk) && rk == id2.runtimeCacheKey) ||
|
||||
(isPresent(ak) && ak == id2.assetCacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileDiDependencyMetadata {
|
||||
@ -263,36 +164,6 @@ export class CompileDiDependencyMetadata {
|
||||
this.token = token;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileDiDependencyMetadata {
|
||||
return new CompileDiDependencyMetadata({
|
||||
token: _objFromJson(data['token'], CompileTokenMetadata.fromJson),
|
||||
query: _objFromJson(data['query'], CompileQueryMetadata.fromJson),
|
||||
viewQuery: _objFromJson(data['viewQuery'], CompileQueryMetadata.fromJson),
|
||||
value: data['value'],
|
||||
isAttribute: data['isAttribute'],
|
||||
isSelf: data['isSelf'],
|
||||
isHost: data['isHost'],
|
||||
isSkipSelf: data['isSkipSelf'],
|
||||
isOptional: data['isOptional'],
|
||||
isValue: data['isValue']
|
||||
});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'token': _objToJson(this.token),
|
||||
'query': _objToJson(this.query),
|
||||
'viewQuery': _objToJson(this.viewQuery),
|
||||
'value': this.value,
|
||||
'isAttribute': this.isAttribute,
|
||||
'isSelf': this.isSelf,
|
||||
'isHost': this.isHost,
|
||||
'isSkipSelf': this.isSkipSelf,
|
||||
'isOptional': this.isOptional,
|
||||
'isValue': this.isValue
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileProviderMetadata {
|
||||
@ -321,41 +192,9 @@ export class CompileProviderMetadata {
|
||||
this.deps = normalizeBlank(deps);
|
||||
this.multi = normalizeBool(multi);
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileProviderMetadata {
|
||||
return new CompileProviderMetadata({
|
||||
token: _objFromJson(data['token'], CompileTokenMetadata.fromJson),
|
||||
useClass: _objFromJson(data['useClass'], CompileTypeMetadata.fromJson),
|
||||
useExisting: _objFromJson(data['useExisting'], CompileTokenMetadata.fromJson),
|
||||
useValue: _objFromJson(data['useValue'], CompileIdentifierMetadata.fromJson),
|
||||
useFactory: _objFromJson(data['useFactory'], CompileFactoryMetadata.fromJson),
|
||||
multi: data['multi'],
|
||||
deps: _arrayFromJson(data['deps'], CompileDiDependencyMetadata.fromJson)
|
||||
});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
// Note: Runtime type can't be serialized...
|
||||
'class': 'Provider',
|
||||
'token': _objToJson(this.token),
|
||||
'useClass': _objToJson(this.useClass),
|
||||
'useExisting': _objToJson(this.useExisting),
|
||||
'useValue': _objToJson(this.useValue),
|
||||
'useFactory': _objToJson(this.useFactory),
|
||||
'multi': this.multi,
|
||||
'deps': _arrayToJson(this.deps)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileFactoryMetadata implements CompileIdentifierMetadata,
|
||||
CompileMetadataWithIdentifier {
|
||||
runtime: Function;
|
||||
name: string;
|
||||
prefix: string;
|
||||
moduleUrl: string;
|
||||
value: any;
|
||||
export class CompileFactoryMetadata extends CompileIdentifierMetadata {
|
||||
diDeps: CompileDiDependencyMetadata[];
|
||||
|
||||
constructor({runtime, name, moduleUrl, prefix, diDeps, value}: {
|
||||
@ -366,45 +205,15 @@ export class CompileFactoryMetadata implements CompileIdentifierMetadata,
|
||||
value?: boolean,
|
||||
diDeps?: CompileDiDependencyMetadata[]
|
||||
}) {
|
||||
this.runtime = runtime;
|
||||
this.name = name;
|
||||
this.prefix = prefix;
|
||||
this.moduleUrl = moduleUrl;
|
||||
super({runtime: runtime, name: name, prefix: prefix, moduleUrl: moduleUrl, value: value});
|
||||
this.diDeps = _normalizeArray(diDeps);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return this; }
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileFactoryMetadata {
|
||||
return new CompileFactoryMetadata({
|
||||
name: data['name'],
|
||||
prefix: data['prefix'],
|
||||
moduleUrl: data['moduleUrl'],
|
||||
value: data['value'],
|
||||
diDeps: _arrayFromJson(data['diDeps'], CompileDiDependencyMetadata.fromJson)
|
||||
});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'class': 'Factory',
|
||||
'name': this.name,
|
||||
'prefix': this.prefix,
|
||||
'moduleUrl': this.moduleUrl,
|
||||
'value': this.value,
|
||||
'diDeps': _arrayToJson(this.diDeps)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var UNDEFINED = new Object();
|
||||
|
||||
export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
|
||||
value: any;
|
||||
identifier: CompileIdentifierMetadata;
|
||||
identifierIsInstance: boolean;
|
||||
private _assetCacheKey = UNDEFINED;
|
||||
|
||||
constructor(
|
||||
{value, identifier, identifierIsInstance}:
|
||||
@ -414,46 +223,20 @@ export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
|
||||
this.identifierIsInstance = normalizeBool(identifierIsInstance);
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileTokenMetadata {
|
||||
return new CompileTokenMetadata({
|
||||
value: data['value'],
|
||||
identifier: _objFromJson(data['identifier'], CompileIdentifierMetadata.fromJson),
|
||||
identifierIsInstance: data['identifierIsInstance']
|
||||
});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'value': this.value,
|
||||
'identifier': _objToJson(this.identifier),
|
||||
'identifierIsInstance': this.identifierIsInstance
|
||||
};
|
||||
}
|
||||
|
||||
get runtimeCacheKey(): any {
|
||||
if (isPresent(this.identifier)) {
|
||||
return this.identifier.runtime;
|
||||
return this.identifier.runtimeCacheKey;
|
||||
} else {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
get assetCacheKey(): any {
|
||||
if (this._assetCacheKey === UNDEFINED) {
|
||||
if (isPresent(this.identifier)) {
|
||||
if (isPresent(this.identifier.moduleUrl) &&
|
||||
isPresent(getUrlScheme(this.identifier.moduleUrl))) {
|
||||
var uri = reflector.importUri(
|
||||
{'filePath': this.identifier.moduleUrl, 'name': this.identifier.name});
|
||||
this._assetCacheKey = `${this.identifier.name}|${uri}|${this.identifierIsInstance}`;
|
||||
} else {
|
||||
this._assetCacheKey = null;
|
||||
}
|
||||
} else {
|
||||
this._assetCacheKey = this.value;
|
||||
}
|
||||
if (isPresent(this.identifier)) {
|
||||
return this.identifier.assetCacheKey;
|
||||
} else {
|
||||
return this.value;
|
||||
}
|
||||
return this._assetCacheKey;
|
||||
}
|
||||
|
||||
equalsTo(token2: CompileTokenMetadata): boolean {
|
||||
@ -468,15 +251,24 @@ export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileTokenMap<VALUE> {
|
||||
/**
|
||||
* Note: We only need this in places where we need to support identifiers that
|
||||
* don't have a `runtime` value given by the `StaticReflector`. E.g. see the `identifiers`
|
||||
* file where we have some identifiers hard coded by name/module path.
|
||||
*
|
||||
* TODO(tbosch): Eventually, all of these places should go through the static reflector
|
||||
* as well, providing them with a valid `StaticSymbol` that is again a singleton.
|
||||
*/
|
||||
export class CompileIdentifierMap<KEY extends CompileMetadataWithIdentifier, VALUE> {
|
||||
private _valueMap = new Map<any, VALUE>();
|
||||
private _values: VALUE[] = [];
|
||||
private _tokens: CompileTokenMetadata[] = [];
|
||||
private _tokens: KEY[] = [];
|
||||
|
||||
add(token: CompileTokenMetadata, value: VALUE) {
|
||||
add(token: KEY, value: VALUE) {
|
||||
var existing = this.get(token);
|
||||
if (isPresent(existing)) {
|
||||
throw new BaseException(`Can only add to a TokenMap! Token: ${token.name}`);
|
||||
throw new BaseException(
|
||||
`Cannot overwrite in a CompileIdentifierMap! Token: ${token.identifier.name}`);
|
||||
}
|
||||
this._tokens.push(token);
|
||||
this._values.push(value);
|
||||
@ -489,7 +281,7 @@ export class CompileTokenMap<VALUE> {
|
||||
this._valueMap.set(ak, value);
|
||||
}
|
||||
}
|
||||
get(token: CompileTokenMetadata): VALUE {
|
||||
get(token: KEY): VALUE {
|
||||
var rk = token.runtimeCacheKey;
|
||||
var ak = token.assetCacheKey;
|
||||
var result: VALUE;
|
||||
@ -501,7 +293,7 @@ export class CompileTokenMap<VALUE> {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
keys(): CompileTokenMetadata[] { return this._tokens; }
|
||||
keys(): KEY[] { return this._tokens; }
|
||||
values(): VALUE[] { return this._values; }
|
||||
get size(): number { return this._values.length; }
|
||||
}
|
||||
@ -509,13 +301,8 @@ export class CompileTokenMap<VALUE> {
|
||||
/**
|
||||
* Metadata regarding compilation of a type.
|
||||
*/
|
||||
export class CompileTypeMetadata implements CompileIdentifierMetadata, CompileMetadataWithType {
|
||||
runtime: Type;
|
||||
name: string;
|
||||
prefix: string;
|
||||
moduleUrl: string;
|
||||
export class CompileTypeMetadata extends CompileIdentifierMetadata {
|
||||
isHost: boolean;
|
||||
value: any;
|
||||
diDeps: CompileDiDependencyMetadata[];
|
||||
|
||||
constructor({runtime, name, moduleUrl, prefix, isHost, value, diDeps}: {
|
||||
@ -527,41 +314,10 @@ export class CompileTypeMetadata implements CompileIdentifierMetadata, CompileMe
|
||||
value?: any,
|
||||
diDeps?: CompileDiDependencyMetadata[]
|
||||
} = {}) {
|
||||
this.runtime = runtime;
|
||||
this.name = name;
|
||||
this.moduleUrl = moduleUrl;
|
||||
this.prefix = prefix;
|
||||
super({runtime: runtime, name: name, moduleUrl: moduleUrl, prefix: prefix, value: value});
|
||||
this.isHost = normalizeBool(isHost);
|
||||
this.value = value;
|
||||
this.diDeps = _normalizeArray(diDeps);
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileTypeMetadata {
|
||||
return new CompileTypeMetadata({
|
||||
name: data['name'],
|
||||
moduleUrl: data['moduleUrl'],
|
||||
prefix: data['prefix'],
|
||||
isHost: data['isHost'],
|
||||
value: data['value'],
|
||||
diDeps: _arrayFromJson(data['diDeps'], CompileDiDependencyMetadata.fromJson)
|
||||
});
|
||||
}
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return this; }
|
||||
get type(): CompileTypeMetadata { return this; }
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
// Note: Runtime type can't be serialized...
|
||||
'class': 'Type',
|
||||
'name': this.name,
|
||||
'moduleUrl': this.moduleUrl,
|
||||
'prefix': this.prefix,
|
||||
'isHost': this.isHost,
|
||||
'value': this.value,
|
||||
'diDeps': _arrayToJson(this.diDeps)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileQueryMetadata {
|
||||
@ -584,26 +340,6 @@ export class CompileQueryMetadata {
|
||||
this.propertyName = propertyName;
|
||||
this.read = read;
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileQueryMetadata {
|
||||
return new CompileQueryMetadata({
|
||||
selectors: _arrayFromJson(data['selectors'], CompileTokenMetadata.fromJson),
|
||||
descendants: data['descendants'],
|
||||
first: data['first'],
|
||||
propertyName: data['propertyName'],
|
||||
read: _objFromJson(data['read'], CompileTokenMetadata.fromJson)
|
||||
});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'selectors': _arrayToJson(this.selectors),
|
||||
'descendants': this.descendants,
|
||||
'first': this.first,
|
||||
'propertyName': this.propertyName,
|
||||
'read': _objToJson(this.read)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -620,15 +356,6 @@ export class CompileStylesheetMetadata {
|
||||
this.styles = _normalizeArray(styles);
|
||||
this.styleUrls = _normalizeArray(styleUrls);
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileStylesheetMetadata {
|
||||
return new CompileStylesheetMetadata(
|
||||
{moduleUrl: data['moduleUrl'], styles: data['styles'], styleUrls: data['styleUrls']});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {'moduleUrl': this.moduleUrl, 'styles': this.styles, 'styleUrls': this.styleUrls};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -670,46 +397,12 @@ export class CompileTemplateMetadata {
|
||||
}
|
||||
this.interpolation = interpolation;
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileTemplateMetadata {
|
||||
var animations =
|
||||
<CompileAnimationEntryMetadata[]>_arrayFromJson(data['animations'], metadataFromJson);
|
||||
return new CompileTemplateMetadata({
|
||||
encapsulation: isPresent(data['encapsulation']) ?
|
||||
VIEW_ENCAPSULATION_VALUES[data['encapsulation']] :
|
||||
data['encapsulation'],
|
||||
template: data['template'],
|
||||
templateUrl: data['templateUrl'],
|
||||
styles: data['styles'],
|
||||
styleUrls: data['styleUrls'],
|
||||
externalStylesheets:
|
||||
_arrayFromJson(data['externalStylesheets'], CompileStylesheetMetadata.fromJson),
|
||||
animations: animations,
|
||||
ngContentSelectors: data['ngContentSelectors'],
|
||||
interpolation: data['interpolation']
|
||||
});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'encapsulation': isPresent(this.encapsulation) ? serializeEnum(this.encapsulation) :
|
||||
this.encapsulation,
|
||||
'template': this.template,
|
||||
'templateUrl': this.templateUrl,
|
||||
'styles': this.styles,
|
||||
'styleUrls': this.styleUrls,
|
||||
'externalStylesheets': _objToJson(this.externalStylesheets),
|
||||
'animations': _objToJson(this.animations),
|
||||
'ngContentSelectors': this.ngContentSelectors,
|
||||
'interpolation': this.interpolation
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Metadata regarding compilation of a directive.
|
||||
*/
|
||||
export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
export class CompileDirectiveMetadata implements CompileMetadataWithIdentifier {
|
||||
static create(
|
||||
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
|
||||
lifecycleHooks, providers, viewProviders, queries, viewQueries, precompile, template}: {
|
||||
@ -796,6 +489,7 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
viewProviders: CompileProviderMetadata[];
|
||||
queries: CompileQueryMetadata[];
|
||||
viewQueries: CompileQueryMetadata[];
|
||||
// Note: Need to keep types here to prevent cycles!
|
||||
precompile: CompileTypeMetadata[];
|
||||
template: CompileTemplateMetadata;
|
||||
|
||||
@ -844,68 +538,26 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return this.type; }
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileDirectiveMetadata {
|
||||
return new CompileDirectiveMetadata({
|
||||
isComponent: data['isComponent'],
|
||||
selector: data['selector'],
|
||||
exportAs: data['exportAs'],
|
||||
type: isPresent(data['type']) ? CompileTypeMetadata.fromJson(data['type']) : data['type'],
|
||||
changeDetection: isPresent(data['changeDetection']) ?
|
||||
CHANGE_DETECTION_STRATEGY_VALUES[data['changeDetection']] :
|
||||
data['changeDetection'],
|
||||
inputs: data['inputs'],
|
||||
outputs: data['outputs'],
|
||||
hostListeners: data['hostListeners'],
|
||||
hostProperties: data['hostProperties'],
|
||||
hostAttributes: data['hostAttributes'],
|
||||
lifecycleHooks:
|
||||
(<any[]>data['lifecycleHooks']).map(hookValue => LIFECYCLE_HOOKS_VALUES[hookValue]),
|
||||
template: isPresent(data['template']) ? CompileTemplateMetadata.fromJson(data['template']) :
|
||||
data['template'],
|
||||
providers: _arrayFromJson(data['providers'], metadataFromJson),
|
||||
viewProviders: _arrayFromJson(data['viewProviders'], metadataFromJson),
|
||||
queries: _arrayFromJson(data['queries'], CompileQueryMetadata.fromJson),
|
||||
viewQueries: _arrayFromJson(data['viewQueries'], CompileQueryMetadata.fromJson),
|
||||
precompile: _arrayFromJson(data['precompile'], CompileTypeMetadata.fromJson)
|
||||
});
|
||||
}
|
||||
get runtimeCacheKey(): any { return this.type.runtimeCacheKey; }
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'class': 'Directive',
|
||||
'isComponent': this.isComponent,
|
||||
'selector': this.selector,
|
||||
'exportAs': this.exportAs,
|
||||
'type': isPresent(this.type) ? this.type.toJson() : this.type,
|
||||
'changeDetection': isPresent(this.changeDetection) ? serializeEnum(this.changeDetection) :
|
||||
this.changeDetection,
|
||||
'inputs': this.inputs,
|
||||
'outputs': this.outputs,
|
||||
'hostListeners': this.hostListeners,
|
||||
'hostProperties': this.hostProperties,
|
||||
'hostAttributes': this.hostAttributes,
|
||||
'lifecycleHooks': this.lifecycleHooks.map(hook => serializeEnum(hook)),
|
||||
'template': isPresent(this.template) ? this.template.toJson() : this.template,
|
||||
'providers': _arrayToJson(this.providers),
|
||||
'viewProviders': _arrayToJson(this.viewProviders),
|
||||
'queries': _arrayToJson(this.queries),
|
||||
'viewQueries': _arrayToJson(this.viewQueries),
|
||||
'precompile': _arrayToJson(this.precompile)
|
||||
};
|
||||
get assetCacheKey(): any { return this.type.assetCacheKey; }
|
||||
|
||||
equalsTo(other: CompileMetadataWithIdentifier): boolean {
|
||||
return this.type.equalsTo(other.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct {@link CompileDirectiveMetadata} from {@link ComponentTypeMetadata} and a selector.
|
||||
*/
|
||||
export function createHostComponentMeta(
|
||||
componentType: CompileTypeMetadata, componentSelector: string): CompileDirectiveMetadata {
|
||||
var template = CssSelector.parse(componentSelector)[0].getMatchingElementTemplate();
|
||||
export function createHostComponentMeta(compMeta: CompileDirectiveMetadata):
|
||||
CompileDirectiveMetadata {
|
||||
var template = CssSelector.parse(compMeta.selector)[0].getMatchingElementTemplate();
|
||||
return CompileDirectiveMetadata.create({
|
||||
type: new CompileTypeMetadata({
|
||||
runtime: Object,
|
||||
name: `${componentType.name}_Host`,
|
||||
moduleUrl: componentType.moduleUrl,
|
||||
name: `${compMeta.type.name}_Host`,
|
||||
moduleUrl: compMeta.type.moduleUrl,
|
||||
isHost: true
|
||||
}),
|
||||
template: new CompileTemplateMetadata({
|
||||
@ -931,7 +583,7 @@ export function createHostComponentMeta(
|
||||
}
|
||||
|
||||
|
||||
export class CompilePipeMetadata implements CompileMetadataWithType {
|
||||
export class CompilePipeMetadata implements CompileMetadataWithIdentifier {
|
||||
type: CompileTypeMetadata;
|
||||
name: string;
|
||||
pure: boolean;
|
||||
@ -949,114 +601,91 @@ export class CompilePipeMetadata implements CompileMetadataWithType {
|
||||
this.lifecycleHooks = _normalizeArray(lifecycleHooks);
|
||||
}
|
||||
get identifier(): CompileIdentifierMetadata { return this.type; }
|
||||
get runtimeCacheKey(): any { return this.type.runtimeCacheKey; }
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompilePipeMetadata {
|
||||
return new CompilePipeMetadata({
|
||||
type: isPresent(data['type']) ? CompileTypeMetadata.fromJson(data['type']) : data['type'],
|
||||
name: data['name'],
|
||||
pure: data['pure']
|
||||
});
|
||||
}
|
||||
get assetCacheKey(): any { return this.type.assetCacheKey; }
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'class': 'Pipe',
|
||||
'type': isPresent(this.type) ? this.type.toJson() : null,
|
||||
'name': this.name,
|
||||
'pure': this.pure
|
||||
};
|
||||
equalsTo(other: CompileMetadataWithIdentifier): boolean {
|
||||
return this.type.equalsTo(other.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Metadata regarding compilation of a directive.
|
||||
*/
|
||||
export class CompileAppModuleMetadata implements CompileMetadataWithType {
|
||||
export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
|
||||
type: CompileTypeMetadata;
|
||||
providers: CompileProviderMetadata[];
|
||||
directives: CompileTypeMetadata[];
|
||||
pipes: CompileTypeMetadata[];
|
||||
declaredDirectives: CompileDirectiveMetadata[];
|
||||
exportedDirectives: CompileDirectiveMetadata[];
|
||||
declaredPipes: CompilePipeMetadata[];
|
||||
exportedPipes: CompilePipeMetadata[];
|
||||
// Note: See CompileDirectiveMetadata.precompile why this has to be a type.
|
||||
precompile: CompileTypeMetadata[];
|
||||
modules: CompileTypeMetadata[];
|
||||
providers: CompileProviderMetadata[];
|
||||
|
||||
constructor({type, providers, directives, pipes, precompile, modules}: {
|
||||
type?: CompileTypeMetadata,
|
||||
providers?: Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
|
||||
directives?: CompileTypeMetadata[],
|
||||
pipes?: CompileTypeMetadata[],
|
||||
precompile?: CompileTypeMetadata[],
|
||||
modules?: CompileTypeMetadata[]
|
||||
} = {}) {
|
||||
importedModules: CompileNgModuleMetadata[];
|
||||
exportedModules: CompileNgModuleMetadata[];
|
||||
|
||||
transitiveModule: TransitiveCompileNgModuleMetadata;
|
||||
|
||||
constructor(
|
||||
{type, providers, declaredDirectives, exportedDirectives, declaredPipes, exportedPipes,
|
||||
precompile, importedModules, exportedModules, transitiveModule}: {
|
||||
type?: CompileTypeMetadata,
|
||||
providers?:
|
||||
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
|
||||
declaredDirectives?: CompileDirectiveMetadata[],
|
||||
exportedDirectives?: CompileDirectiveMetadata[],
|
||||
declaredPipes?: CompilePipeMetadata[],
|
||||
exportedPipes?: CompilePipeMetadata[],
|
||||
precompile?: CompileTypeMetadata[],
|
||||
importedModules?: CompileNgModuleMetadata[],
|
||||
exportedModules?: CompileNgModuleMetadata[],
|
||||
transitiveModule?: TransitiveCompileNgModuleMetadata
|
||||
} = {}) {
|
||||
this.type = type;
|
||||
this.directives = _normalizeArray(directives);
|
||||
this.pipes = _normalizeArray(pipes);
|
||||
this.declaredDirectives = _normalizeArray(declaredDirectives);
|
||||
this.exportedDirectives = _normalizeArray(exportedDirectives);
|
||||
this.declaredPipes = _normalizeArray(declaredPipes);
|
||||
this.exportedPipes = _normalizeArray(exportedPipes);
|
||||
this.providers = _normalizeArray(providers);
|
||||
this.precompile = _normalizeArray(precompile);
|
||||
this.modules = _normalizeArray(modules);
|
||||
this.importedModules = _normalizeArray(importedModules);
|
||||
this.exportedModules = _normalizeArray(exportedModules);
|
||||
this.transitiveModule = transitiveModule;
|
||||
}
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return this.type; }
|
||||
get runtimeCacheKey(): any { return this.type.runtimeCacheKey; }
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileAppModuleMetadata {
|
||||
return new CompileAppModuleMetadata({
|
||||
type: isPresent(data['type']) ? CompileTypeMetadata.fromJson(data['type']) : data['type'],
|
||||
providers: _arrayFromJson(data['providers'], metadataFromJson),
|
||||
directives: _arrayFromJson(data['directives'], metadataFromJson),
|
||||
pipes: _arrayFromJson(data['pipes'], metadataFromJson),
|
||||
precompile: _arrayFromJson(data['precompile'], CompileTypeMetadata.fromJson),
|
||||
modules: _arrayFromJson(data['modules'], CompileTypeMetadata.fromJson)
|
||||
});
|
||||
}
|
||||
get assetCacheKey(): any { return this.type.assetCacheKey; }
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
'class': 'AppModule',
|
||||
'type': isPresent(this.type) ? this.type.toJson() : this.type,
|
||||
'providers': _arrayToJson(this.providers),
|
||||
'directives': _arrayToJson(this.directives),
|
||||
'pipes': _arrayToJson(this.pipes),
|
||||
'precompile': _arrayToJson(this.precompile),
|
||||
'modules': _arrayToJson(this.modules)
|
||||
};
|
||||
equalsTo(other: CompileMetadataWithIdentifier): boolean {
|
||||
return this.type.equalsTo(other.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
var _COMPILE_METADATA_FROM_JSON = {
|
||||
'AppModule': CompileAppModuleMetadata.fromJson,
|
||||
'Directive': CompileDirectiveMetadata.fromJson,
|
||||
'Pipe': CompilePipeMetadata.fromJson,
|
||||
'Type': CompileTypeMetadata.fromJson,
|
||||
'Provider': CompileProviderMetadata.fromJson,
|
||||
'Identifier': CompileIdentifierMetadata.fromJson,
|
||||
'Factory': CompileFactoryMetadata.fromJson,
|
||||
'AnimationEntryMetadata': CompileAnimationEntryMetadata.fromJson,
|
||||
'AnimationStateDeclarationMetadata': CompileAnimationStateDeclarationMetadata.fromJson,
|
||||
'AnimationStateTransitionMetadata': CompileAnimationStateTransitionMetadata.fromJson,
|
||||
'AnimationSequenceMetadata': CompileAnimationSequenceMetadata.fromJson,
|
||||
'AnimationGroupMetadata': CompileAnimationGroupMetadata.fromJson,
|
||||
'AnimationAnimateMetadata': CompileAnimationAnimateMetadata.fromJson,
|
||||
'AnimationStyleMetadata': CompileAnimationStyleMetadata.fromJson,
|
||||
'AnimationKeyframesSequenceMetadata': CompileAnimationKeyframesSequenceMetadata.fromJson
|
||||
};
|
||||
|
||||
function _arrayFromJson(obj: any[], fn: (a: {[key: string]: any}) => any): any {
|
||||
return isBlank(obj) ? null : obj.map(o => _objFromJson(o, fn));
|
||||
export class TransitiveCompileNgModuleMetadata {
|
||||
directivesSet = new Set<Type>();
|
||||
pipesSet = new Set<Type>();
|
||||
constructor(
|
||||
public modules: CompileNgModuleMetadata[], public providers: CompileProviderMetadata[],
|
||||
public precompile: CompileTypeMetadata[], public directives: CompileDirectiveMetadata[],
|
||||
public pipes: CompilePipeMetadata[]) {
|
||||
directives.forEach(dir => this.directivesSet.add(dir.type.runtime));
|
||||
pipes.forEach(pipe => this.pipesSet.add(pipe.type.runtime));
|
||||
}
|
||||
}
|
||||
|
||||
function _arrayToJson(obj: any[]): string|{[key: string]: any} {
|
||||
return isBlank(obj) ? null : obj.map(_objToJson);
|
||||
}
|
||||
|
||||
function _objFromJson(obj: any, fn: (a: {[key: string]: any}) => any): any {
|
||||
if (isArray(obj)) return _arrayFromJson(obj, fn);
|
||||
if (isString(obj) || isBlank(obj) || isBoolean(obj) || isNumber(obj)) return obj;
|
||||
return fn(obj);
|
||||
}
|
||||
|
||||
function _objToJson(obj: any): string|{[key: string]: any} {
|
||||
if (isArray(obj)) return _arrayToJson(obj);
|
||||
if (isString(obj) || isBlank(obj) || isBoolean(obj) || isNumber(obj)) return obj;
|
||||
return obj.toJson();
|
||||
export function removeIdentifierDuplicates<T extends CompileMetadataWithIdentifier>(items: T[]):
|
||||
T[] {
|
||||
const map = new CompileIdentifierMap<T, T>();
|
||||
items.forEach((item) => {
|
||||
if (!map.get(item)) {
|
||||
map.add(item, item);
|
||||
}
|
||||
});
|
||||
return map.keys();
|
||||
}
|
||||
|
||||
function _normalizeArray(obj: any[]): any[] {
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Compiler, CompilerFactory, CompilerOptions, ComponentResolver, Injectable, PLATFORM_DIRECTIVES, PLATFORM_PIPES, ReflectiveInjector, Type, ViewEncapsulation, isDevMode} from '@angular/core';
|
||||
import {Compiler, CompilerFactory, CompilerOptions, Component, ComponentResolver, Inject, Injectable, NgModule, PLATFORM_DIRECTIVES, PLATFORM_INITIALIZER, PLATFORM_PIPES, PlatformRef, ReflectiveInjector, Type, ViewEncapsulation, corePlatform, createPlatformFactory, disposePlatform, isDevMode} from '@angular/core';
|
||||
|
||||
export * from './template_ast';
|
||||
export {TEMPLATE_TRANSFORMS} from './template_parser';
|
||||
@ -20,14 +20,17 @@ export * from './xhr';
|
||||
export {ViewResolver} from './view_resolver';
|
||||
export {DirectiveResolver} from './directive_resolver';
|
||||
export {PipeResolver} from './pipe_resolver';
|
||||
export {NgModuleResolver} from './ng_module_resolver';
|
||||
|
||||
import {stringify} from './facade/lang';
|
||||
import {ListWrapper} from './facade/collection';
|
||||
import {TemplateParser} from './template_parser';
|
||||
import {HtmlParser} from './html_parser';
|
||||
import {DirectiveNormalizer} from './directive_normalizer';
|
||||
import {CompileMetadataResolver} from './metadata_resolver';
|
||||
import {StyleCompiler} from './style_compiler';
|
||||
import {ViewCompiler} from './view_compiler/view_compiler';
|
||||
import {AppModuleCompiler} from './app_module_compiler';
|
||||
import {NgModuleCompiler} from './ng_module_compiler';
|
||||
import {CompilerConfig} from './config';
|
||||
import {RuntimeCompiler} from './runtime_compiler';
|
||||
import {ElementSchemaRegistry} from './schema/element_schema_registry';
|
||||
@ -38,19 +41,24 @@ import {Lexer} from './expression_parser/lexer';
|
||||
import {ViewResolver} from './view_resolver';
|
||||
import {DirectiveResolver} from './directive_resolver';
|
||||
import {PipeResolver} from './pipe_resolver';
|
||||
import {Console, Reflector, reflector, ReflectorReader} from '../core_private';
|
||||
import {NgModuleResolver} from './ng_module_resolver';
|
||||
import {Console, Reflector, reflector, ReflectorReader, ReflectionCapabilities} from '../core_private';
|
||||
import {XHR} from './xhr';
|
||||
|
||||
const _NO_XHR: XHR = {
|
||||
get(url: string): Promise<string>{
|
||||
throw new Error(`No XHR implementation has been provided. Can't read the url "${url}"`);}
|
||||
};
|
||||
|
||||
/**
|
||||
* A set of providers that provide `RuntimeCompiler` and its dependencies to use for
|
||||
* template compilation.
|
||||
*/
|
||||
export const COMPILER_PROVIDERS: Array<any|Type|{[k: string]: any}|any[]> =
|
||||
/*@ts2dart_const*/[
|
||||
{provide: PLATFORM_DIRECTIVES, useValue: [], multi: true},
|
||||
{provide: PLATFORM_PIPES, useValue: [], multi: true},
|
||||
{provide: Reflector, useValue: reflector},
|
||||
{provide: ReflectorReader, useExisting: Reflector},
|
||||
{provide: XHR, useValue: _NO_XHR},
|
||||
Console,
|
||||
Lexer,
|
||||
Parser,
|
||||
@ -61,112 +69,153 @@ export const COMPILER_PROVIDERS: Array<any|Type|{[k: string]: any}|any[]> =
|
||||
DEFAULT_PACKAGE_URL_PROVIDER,
|
||||
StyleCompiler,
|
||||
ViewCompiler,
|
||||
AppModuleCompiler,
|
||||
NgModuleCompiler,
|
||||
/*@ts2dart_Provider*/ {provide: CompilerConfig, useValue: new CompilerConfig()},
|
||||
RuntimeCompiler,
|
||||
/*@ts2dart_Provider*/ {provide: ComponentResolver, useExisting: RuntimeCompiler},
|
||||
/*@ts2dart_Provider*/ {provide: Compiler, useExisting: RuntimeCompiler},
|
||||
DomElementSchemaRegistry,
|
||||
/*@ts2dart_Provider*/ {provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry},
|
||||
UrlResolver,
|
||||
ViewResolver,
|
||||
DirectiveResolver,
|
||||
PipeResolver
|
||||
PipeResolver,
|
||||
NgModuleResolver
|
||||
];
|
||||
|
||||
|
||||
export function analyzeAppProvidersForDeprecatedConfiguration(appProviders: any[] = []):
|
||||
{compilerOptions: CompilerOptions, moduleDeclarations: Type[], deprecationMessages: string[]} {
|
||||
let platformDirectives: any[] = [];
|
||||
let platformPipes: any[] = [];
|
||||
|
||||
let compilerProviders: any[] = [];
|
||||
let useDebug: boolean;
|
||||
let useJit: boolean;
|
||||
let defaultEncapsulation: ViewEncapsulation;
|
||||
const deprecationMessages: string[] = [];
|
||||
|
||||
// Note: This is a hack to still support the old way
|
||||
// of configuring platform directives / pipes and the compiler xhr.
|
||||
// This will soon be deprecated!
|
||||
const tempInj = ReflectiveInjector.resolveAndCreate(appProviders);
|
||||
const compilerConfig: CompilerConfig = tempInj.get(CompilerConfig, null);
|
||||
if (compilerConfig) {
|
||||
platformDirectives = compilerConfig.platformDirectives;
|
||||
platformPipes = compilerConfig.platformPipes;
|
||||
useJit = compilerConfig.useJit;
|
||||
useDebug = compilerConfig.genDebugInfo;
|
||||
defaultEncapsulation = compilerConfig.defaultEncapsulation;
|
||||
deprecationMessages.push(
|
||||
`Passing CompilerConfig as a regular provider is deprecated. Use the "compilerOptions" parameter of "bootstrap()" or use a custom "CompilerFactory" platform provider instead.`);
|
||||
} else {
|
||||
// If nobody provided a CompilerConfig, use the
|
||||
// PLATFORM_DIRECTIVES / PLATFORM_PIPES values directly if existing
|
||||
platformDirectives = tempInj.get(PLATFORM_DIRECTIVES, []);
|
||||
platformPipes = tempInj.get(PLATFORM_PIPES, []);
|
||||
}
|
||||
platformDirectives = ListWrapper.flatten(platformDirectives);
|
||||
platformPipes = ListWrapper.flatten(platformPipes);
|
||||
const xhr = tempInj.get(XHR, null);
|
||||
if (xhr) {
|
||||
compilerProviders.push([{provide: XHR, useValue: xhr}]);
|
||||
deprecationMessages.push(
|
||||
`Passing XHR as regular provider is deprecated. Pass the provider via "compilerOptions" instead.`);
|
||||
}
|
||||
|
||||
if (platformDirectives.length > 0) {
|
||||
deprecationMessages.push(
|
||||
`The PLATFORM_DIRECTIVES provider and CompilerConfig.platformDirectives is deprecated. Add the directives to an NgModule instead! ` +
|
||||
`(Directives: ${platformDirectives.map(type => stringify(type))})`);
|
||||
}
|
||||
if (platformPipes.length > 0) {
|
||||
deprecationMessages.push(
|
||||
`The PLATFORM_PIPES provider and CompilerConfig.platformPipes is deprecated. Add the pipes to an NgModule instead! ` +
|
||||
`(Pipes: ${platformPipes.map(type => stringify(type))})`);
|
||||
}
|
||||
const compilerOptions: CompilerOptions = {
|
||||
useJit: useJit,
|
||||
useDebug: useDebug,
|
||||
defaultEncapsulation: defaultEncapsulation,
|
||||
providers: compilerProviders
|
||||
};
|
||||
|
||||
// Declare a component that uses @Component.directives / pipes as these
|
||||
// will be added to the module declarations only if they are not already
|
||||
// imported by other modules.
|
||||
@Component({directives: platformDirectives, pipes: platformPipes, template: ''})
|
||||
class DynamicComponent {
|
||||
}
|
||||
|
||||
return {
|
||||
compilerOptions,
|
||||
moduleDeclarations: [DynamicComponent],
|
||||
deprecationMessages: deprecationMessages
|
||||
};
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class _RuntimeCompilerFactory extends CompilerFactory {
|
||||
createCompiler(options: CompilerOptions): Compiler {
|
||||
const deprecationMessages: string[] = [];
|
||||
let platformDirectivesFromAppProviders: any[] = [];
|
||||
let platformPipesFromAppProviders: any[] = [];
|
||||
let compilerProvidersFromAppProviders: any[] = [];
|
||||
let useDebugFromAppProviders: boolean;
|
||||
let useJitFromAppProviders: boolean;
|
||||
let defaultEncapsulationFromAppProviders: ViewEncapsulation;
|
||||
|
||||
if (options.deprecatedAppProviders && options.deprecatedAppProviders.length > 0) {
|
||||
// Note: This is a hack to still support the old way
|
||||
// of configuring platform directives / pipes and the compiler xhr.
|
||||
// This will soon be deprecated!
|
||||
const inj = ReflectiveInjector.resolveAndCreate(options.deprecatedAppProviders);
|
||||
const compilerConfig: CompilerConfig = inj.get(CompilerConfig, null);
|
||||
if (compilerConfig) {
|
||||
platformDirectivesFromAppProviders = compilerConfig.deprecatedPlatformDirectives;
|
||||
platformPipesFromAppProviders = compilerConfig.deprecatedPlatformPipes;
|
||||
useJitFromAppProviders = compilerConfig.useJit;
|
||||
useDebugFromAppProviders = compilerConfig.genDebugInfo;
|
||||
defaultEncapsulationFromAppProviders = compilerConfig.defaultEncapsulation;
|
||||
deprecationMessages.push(
|
||||
`Passing a CompilerConfig to "bootstrap()" as provider is deprecated. Pass the provider via the new parameter "compilerOptions" of "bootstrap()" instead.`);
|
||||
} else {
|
||||
// If nobody provided a CompilerConfig, use the
|
||||
// PLATFORM_DIRECTIVES / PLATFORM_PIPES values directly if existing
|
||||
platformDirectivesFromAppProviders = inj.get(PLATFORM_DIRECTIVES, []);
|
||||
if (platformDirectivesFromAppProviders.length > 0) {
|
||||
deprecationMessages.push(
|
||||
`Passing PLATFORM_DIRECTIVES to "bootstrap()" as provider is deprecated. Use the new parameter "directives" of "bootstrap()" instead.`);
|
||||
}
|
||||
platformPipesFromAppProviders = inj.get(PLATFORM_PIPES, []);
|
||||
if (platformPipesFromAppProviders.length > 0) {
|
||||
deprecationMessages.push(
|
||||
`Passing PLATFORM_PIPES to "bootstrap()" as provider is deprecated. Use the new parameter "pipes" of "bootstrap()" instead.`);
|
||||
}
|
||||
}
|
||||
const xhr = inj.get(XHR, null);
|
||||
if (xhr) {
|
||||
compilerProvidersFromAppProviders.push([{provide: XHR, useValue: xhr}]);
|
||||
deprecationMessages.push(
|
||||
`Passing an instance of XHR to "bootstrap()" as provider is deprecated. Pass the provider via the new parameter "compilerOptions" of "bootstrap()" instead.`);
|
||||
}
|
||||
// Need to copy console from deprecatedAppProviders to compiler providers
|
||||
// as well so that we can test the above deprecation messages in old style bootstrap
|
||||
// where we only have app providers!
|
||||
const console = inj.get(Console, null);
|
||||
if (console) {
|
||||
compilerProvidersFromAppProviders.push([{provide: Console, useValue: console}]);
|
||||
}
|
||||
}
|
||||
|
||||
export class RuntimeCompilerFactory implements CompilerFactory {
|
||||
private _defaultOptions: CompilerOptions[];
|
||||
constructor(@Inject(CompilerOptions) defaultOptions: CompilerOptions[]) {
|
||||
this._defaultOptions = [<CompilerOptions>{
|
||||
useDebug: isDevMode(),
|
||||
useJit: true,
|
||||
defaultEncapsulation: ViewEncapsulation.Emulated
|
||||
}].concat(defaultOptions);
|
||||
}
|
||||
createCompiler(options: CompilerOptions[] = []): Compiler {
|
||||
const mergedOptions = _mergeOptions(this._defaultOptions.concat(options));
|
||||
const injector = ReflectiveInjector.resolveAndCreate([
|
||||
COMPILER_PROVIDERS, {
|
||||
provide: CompilerConfig,
|
||||
useFactory: (platformDirectives: any[], platformPipes: any[]) => {
|
||||
useFactory: () => {
|
||||
return new CompilerConfig({
|
||||
deprecatedPlatformDirectives:
|
||||
_mergeArrays(platformDirectivesFromAppProviders, platformDirectives),
|
||||
deprecatedPlatformPipes: _mergeArrays(platformPipesFromAppProviders, platformPipes),
|
||||
// let explicit values from the compiler options overwrite options
|
||||
// from the app providers. E.g. important for the testing platform.
|
||||
genDebugInfo: _firstDefined(options.useDebug, useDebugFromAppProviders, isDevMode()),
|
||||
genDebugInfo: mergedOptions.useDebug,
|
||||
// let explicit values from the compiler options overwrite options
|
||||
// from the app providers
|
||||
useJit: _firstDefined(options.useJit, useJitFromAppProviders, true),
|
||||
useJit: mergedOptions.useJit,
|
||||
// let explicit values from the compiler options overwrite options
|
||||
// from the app providers
|
||||
defaultEncapsulation: _firstDefined(
|
||||
options.defaultEncapsulation, defaultEncapsulationFromAppProviders,
|
||||
ViewEncapsulation.Emulated)
|
||||
defaultEncapsulation: mergedOptions.defaultEncapsulation,
|
||||
logBindingUpdate: mergedOptions.useDebug
|
||||
});
|
||||
},
|
||||
deps: [PLATFORM_DIRECTIVES, PLATFORM_PIPES]
|
||||
deps: []
|
||||
},
|
||||
// options.providers will always contain a provider for XHR as well
|
||||
// (added by platforms). So allow compilerProvidersFromAppProviders to overwrite this
|
||||
_mergeArrays(options.providers, compilerProvidersFromAppProviders)
|
||||
mergedOptions.providers
|
||||
]);
|
||||
const console: Console = injector.get(Console);
|
||||
deprecationMessages.forEach((msg) => { console.warn(msg); });
|
||||
|
||||
return injector.get(Compiler);
|
||||
}
|
||||
}
|
||||
|
||||
function _initReflector() {
|
||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||
}
|
||||
|
||||
export const RUNTIME_COMPILER_FACTORY = new _RuntimeCompilerFactory();
|
||||
/**
|
||||
* A platform that included corePlatform and the compiler.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export const coreDynamicPlatform = createPlatformFactory(corePlatform, 'coreDynamic', [
|
||||
{provide: CompilerOptions, useValue: {}, multi: true},
|
||||
{provide: CompilerFactory, useClass: RuntimeCompilerFactory},
|
||||
{provide: PLATFORM_INITIALIZER, useValue: _initReflector, multi: true},
|
||||
]);
|
||||
|
||||
function _firstDefined<T>(...args: T[]): T {
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
function _mergeOptions(optionsArr: CompilerOptions[]): CompilerOptions {
|
||||
return {
|
||||
useDebug: _lastDefined(optionsArr.map(options => options.useDebug)),
|
||||
useJit: _lastDefined(optionsArr.map(options => options.useJit)),
|
||||
defaultEncapsulation: _lastDefined(optionsArr.map(options => options.defaultEncapsulation)),
|
||||
providers: _mergeArrays(optionsArr.map(options => options.providers))
|
||||
};
|
||||
}
|
||||
|
||||
function _lastDefined<T>(args: T[]): T {
|
||||
for (var i = args.length - 1; i >= 0; i--) {
|
||||
if (args[i] !== undefined) {
|
||||
return args[i];
|
||||
}
|
||||
@ -174,7 +223,7 @@ function _firstDefined<T>(...args: T[]): T {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function _mergeArrays(...parts: any[][]): any[] {
|
||||
function _mergeArrays(parts: any[][]): any[] {
|
||||
let result: any[] = [];
|
||||
parts.forEach((part) => result.push(...part));
|
||||
return result;
|
||||
|
@ -20,17 +20,15 @@ export class CompilerConfig {
|
||||
private _logBindingUpdate: boolean;
|
||||
public useJit: boolean;
|
||||
/**
|
||||
* @deprecated Providing platform directives via the {@link CompilerConfig} deprecated. Provide
|
||||
* platform
|
||||
* directives via an {@link AppModule} instead.
|
||||
* @deprecated Providing platform directives via the {@link CompilerConfig} is deprecated. Provide
|
||||
* platform directives via an {@link NgModule} instead.
|
||||
*/
|
||||
public deprecatedPlatformDirectives: any[];
|
||||
public platformDirectives: any[];
|
||||
/**
|
||||
* @deprecated Providing platform pipes via the {@link CompilerConfig} deprecated. Provide
|
||||
* platform pipes
|
||||
* via an {@link AppModule} instead.
|
||||
* @deprecated Providing platform pipes via the {@link CompilerConfig} is deprecated. Provide
|
||||
* platform pipes via an {@link NgModule} instead.
|
||||
*/
|
||||
public deprecatedPlatformPipes: any[];
|
||||
public platformPipes: any[];
|
||||
|
||||
constructor(
|
||||
{renderTypes = new DefaultRenderTypes(), defaultEncapsulation = ViewEncapsulation.Emulated,
|
||||
@ -49,8 +47,8 @@ export class CompilerConfig {
|
||||
this._genDebugInfo = genDebugInfo;
|
||||
this._logBindingUpdate = logBindingUpdate;
|
||||
this.useJit = useJit;
|
||||
this.deprecatedPlatformDirectives = deprecatedPlatformDirectives;
|
||||
this.deprecatedPlatformPipes = deprecatedPlatformPipes;
|
||||
this.platformDirectives = deprecatedPlatformDirectives;
|
||||
this.platformPipes = deprecatedPlatformPipes;
|
||||
}
|
||||
|
||||
get genDebugInfo(): boolean {
|
||||
|
@ -33,7 +33,7 @@ export class DirectiveResolver {
|
||||
/**
|
||||
* Return {@link DirectiveMetadata} for a given `Type`.
|
||||
*/
|
||||
resolve(type: Type): DirectiveMetadata {
|
||||
resolve(type: Type, throwIfNotFound = true): DirectiveMetadata {
|
||||
var typeMetadata = this._reflector.annotations(resolveForwardRef(type));
|
||||
if (isPresent(typeMetadata)) {
|
||||
var metadata = typeMetadata.find(_isDirectiveMetadata);
|
||||
@ -42,8 +42,10 @@ export class DirectiveResolver {
|
||||
return this._mergeWithPropertyMetadata(metadata, propertyMetadata, type);
|
||||
}
|
||||
}
|
||||
|
||||
throw new BaseException(`No Directive annotation found on ${stringify(type)}`);
|
||||
if (throwIfNotFound) {
|
||||
throw new BaseException(`No Directive annotation found on ${stringify(type)}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private _mergeWithPropertyMetadata(
|
||||
|
@ -6,9 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ANALYZE_FOR_PRECOMPILE, AppModuleFactory, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
||||
import {ANALYZE_FOR_PRECOMPILE, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
||||
|
||||
import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppModuleInjector, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles} from '../core_private';
|
||||
import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NgModuleInjector, NoOpAnimationPlayer as NoOpAnimationPlayer_, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles as impBalanceAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles} from '../core_private';
|
||||
|
||||
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
|
||||
import {assetUrl} from './util';
|
||||
@ -118,15 +118,15 @@ export class Identifiers {
|
||||
runtime: ComponentFactory,
|
||||
moduleUrl: assetUrl('core', 'linker/component_factory')
|
||||
});
|
||||
static AppModuleFactory = new CompileIdentifierMetadata({
|
||||
name: 'AppModuleFactory',
|
||||
runtime: AppModuleFactory,
|
||||
moduleUrl: assetUrl('core', 'linker/app_module_factory')
|
||||
static NgModuleFactory = new CompileIdentifierMetadata({
|
||||
name: 'NgModuleFactory',
|
||||
runtime: NgModuleFactory,
|
||||
moduleUrl: assetUrl('core', 'linker/ng_module_factory')
|
||||
});
|
||||
static AppModuleInjector = new CompileIdentifierMetadata({
|
||||
name: 'AppModuleInjector',
|
||||
runtime: AppModuleInjector,
|
||||
moduleUrl: assetUrl('core', 'linker/app_module_factory')
|
||||
static NgModuleInjector = new CompileIdentifierMetadata({
|
||||
name: 'NgModuleInjector',
|
||||
runtime: NgModuleInjector,
|
||||
moduleUrl: assetUrl('core', 'linker/ng_module_factory')
|
||||
});
|
||||
static ValueUnwrapper = new CompileIdentifierMetadata(
|
||||
{name: 'ValueUnwrapper', moduleUrl: CD_MODULE_URL, runtime: impValueUnwrapper});
|
||||
|
@ -6,10 +6,10 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, AppModuleMetadata, AttributeMetadata, ChangeDetectionStrategy, ComponentMetadata, HostMetadata, Inject, InjectMetadata, Injectable, Optional, OptionalMetadata, Provider, QueryMetadata, SelfMetadata, SkipSelfMetadata, ViewMetadata, ViewQueryMetadata, resolveForwardRef} from '@angular/core';
|
||||
import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, AttributeMetadata, ChangeDetectionStrategy, ComponentMetadata, HostMetadata, Inject, InjectMetadata, Injectable, NgModule, NgModuleMetadata, Optional, OptionalMetadata, Provider, QueryMetadata, SelfMetadata, SkipSelfMetadata, ViewMetadata, ViewQueryMetadata, resolveForwardRef} from '@angular/core';
|
||||
|
||||
import {LIFECYCLE_HOOKS_VALUES, ReflectorReader, createProvider, isProviderLiteral, reflector} from '../core_private';
|
||||
import {StringMapWrapper} from '../src/facade/collection';
|
||||
import {Console, LIFECYCLE_HOOKS_VALUES, ReflectorReader, createProvider, isProviderLiteral, reflector} from '../core_private';
|
||||
import {MapWrapper, StringMapWrapper} from '../src/facade/collection';
|
||||
import {BaseException} from '../src/facade/exceptions';
|
||||
import {Type, isArray, isBlank, isPresent, isString, isStringMap, stringify} from '../src/facade/lang';
|
||||
|
||||
@ -19,6 +19,7 @@ import {CompilerConfig} from './config';
|
||||
import {hasLifecycleHook} from './directive_lifecycle_reflector';
|
||||
import {DirectiveResolver} from './directive_resolver';
|
||||
import {Identifiers, identifierToken} from './identifiers';
|
||||
import {NgModuleResolver} from './ng_module_resolver';
|
||||
import {PipeResolver} from './pipe_resolver';
|
||||
import {getUrlScheme} from './url_resolver';
|
||||
import {MODULE_SUFFIX, ValueTransformer, sanitizeIdentifier, visitValue} from './util';
|
||||
@ -28,13 +29,15 @@ import {ViewResolver} from './view_resolver';
|
||||
export class CompileMetadataResolver {
|
||||
private _directiveCache = new Map<Type, cpl.CompileDirectiveMetadata>();
|
||||
private _pipeCache = new Map<Type, cpl.CompilePipeMetadata>();
|
||||
private _appModuleCache = new Map<Type, cpl.CompileAppModuleMetadata>();
|
||||
private _ngModuleCache = new Map<Type, cpl.CompileNgModuleMetadata>();
|
||||
private _ngModuleOfTypes = new Map<Type, Type>();
|
||||
private _anonymousTypes = new Map<Object, number>();
|
||||
private _anonymousTypeIndex = 0;
|
||||
|
||||
constructor(
|
||||
private _directiveResolver: DirectiveResolver, private _pipeResolver: PipeResolver,
|
||||
private _viewResolver: ViewResolver, private _config: CompilerConfig,
|
||||
private _ngModuleResolver: NgModuleResolver, private _directiveResolver: DirectiveResolver,
|
||||
private _pipeResolver: PipeResolver, private _viewResolver: ViewResolver,
|
||||
private _config: CompilerConfig, private _console: Console,
|
||||
private _reflector: ReflectorReader = reflector) {}
|
||||
|
||||
private sanitizeTokenName(token: any): string {
|
||||
@ -54,13 +57,16 @@ export class CompileMetadataResolver {
|
||||
clearCacheFor(type: Type) {
|
||||
this._directiveCache.delete(type);
|
||||
this._pipeCache.delete(type);
|
||||
this._appModuleCache.delete(type);
|
||||
this._ngModuleOfTypes.delete(type);
|
||||
// Clear all of the NgModuleMetadata as they contain transitive information!
|
||||
this._ngModuleCache.clear();
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
this._directiveCache.clear();
|
||||
this._pipeCache.clear();
|
||||
this._appModuleCache.clear();
|
||||
this._ngModuleCache.clear();
|
||||
this._ngModuleOfTypes.clear();
|
||||
}
|
||||
|
||||
getAnimationEntryMetadata(entry: AnimationEntryMetadata): cpl.CompileAnimationEntryMetadata {
|
||||
@ -105,11 +111,14 @@ export class CompileMetadataResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
getDirectiveMetadata(directiveType: Type): cpl.CompileDirectiveMetadata {
|
||||
getDirectiveMetadata(directiveType: Type, throwIfNotFound = true): cpl.CompileDirectiveMetadata {
|
||||
directiveType = resolveForwardRef(directiveType);
|
||||
var meta = this._directiveCache.get(directiveType);
|
||||
if (isBlank(meta)) {
|
||||
var dirMeta = this._directiveResolver.resolve(directiveType);
|
||||
var dirMeta = this._directiveResolver.resolve(directiveType, throwIfNotFound);
|
||||
if (!dirMeta) {
|
||||
return null;
|
||||
}
|
||||
var templateMeta: cpl.CompileTemplateMetadata = null;
|
||||
var changeDetectionStrategy: ChangeDetectionStrategy = null;
|
||||
var viewProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = [];
|
||||
@ -182,83 +191,254 @@ export class CompileMetadataResolver {
|
||||
return meta;
|
||||
}
|
||||
|
||||
getAppModuleMetadata(moduleType: any, meta: AppModuleMetadata = null):
|
||||
cpl.CompileAppModuleMetadata {
|
||||
// Only cache if we read the metadata via the reflector,
|
||||
// as we use the moduleType as cache key.
|
||||
let useCache = !meta;
|
||||
getNgModuleMetadata(moduleType: any, throwIfNotFound = true): cpl.CompileNgModuleMetadata {
|
||||
moduleType = resolveForwardRef(moduleType);
|
||||
var compileMeta = this._appModuleCache.get(moduleType);
|
||||
if (isBlank(compileMeta) || !useCache) {
|
||||
var compileMeta = this._ngModuleCache.get(moduleType);
|
||||
if (!compileMeta) {
|
||||
const meta = this._ngModuleResolver.resolve(moduleType, throwIfNotFound);
|
||||
if (!meta) {
|
||||
meta = this._reflector.annotations(moduleType)
|
||||
.find((meta) => meta instanceof AppModuleMetadata);
|
||||
return null;
|
||||
}
|
||||
if (!meta) {
|
||||
throw new BaseException(
|
||||
`Could not compile '${stringify(moduleType)}' because it is not an AppModule.`);
|
||||
}
|
||||
let modules: cpl.CompileTypeMetadata[] = [];
|
||||
let providers: any[] = [];
|
||||
let directives: cpl.CompileTypeMetadata[] = [];
|
||||
let pipes: cpl.CompileTypeMetadata[] = [];
|
||||
let precompile: cpl.CompileTypeMetadata[] = [];
|
||||
if (meta.modules) {
|
||||
flattenArray(meta.modules).forEach((moduleType) => {
|
||||
var meta = this.getAppModuleMetadata(moduleType);
|
||||
providers.push(...meta.providers);
|
||||
directives.push(...meta.directives);
|
||||
pipes.push(...meta.pipes);
|
||||
precompile.push(...meta.precompile);
|
||||
modules.push(meta.type);
|
||||
modules.push(...meta.modules);
|
||||
const declaredDirectives: cpl.CompileDirectiveMetadata[] = [];
|
||||
const exportedDirectives: cpl.CompileDirectiveMetadata[] = [];
|
||||
const declaredPipes: cpl.CompilePipeMetadata[] = [];
|
||||
const exportedPipes: cpl.CompilePipeMetadata[] = [];
|
||||
const importedModules: cpl.CompileNgModuleMetadata[] = [];
|
||||
const exportedModules: cpl.CompileNgModuleMetadata[] = [];
|
||||
|
||||
if (meta.imports) {
|
||||
flattenArray(meta.imports).forEach((importedType) => {
|
||||
if (!isValidType(importedType)) {
|
||||
throw new BaseException(
|
||||
`Unexpected value '${stringify(importedType)}' imported by the module '${stringify(moduleType)}'`);
|
||||
}
|
||||
let importedModuleMeta: cpl.CompileNgModuleMetadata;
|
||||
if (importedModuleMeta = this.getNgModuleMetadata(importedType, false)) {
|
||||
importedModules.push(importedModuleMeta);
|
||||
} else {
|
||||
throw new BaseException(
|
||||
`Unexpected value '${stringify(importedType)}' imported by the module '${stringify(moduleType)}'`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (meta.exports) {
|
||||
flattenArray(meta.exports).forEach((exportedType) => {
|
||||
if (!isValidType(exportedType)) {
|
||||
throw new BaseException(
|
||||
`Unexpected value '${stringify(exportedType)}' exported by the module '${stringify(moduleType)}'`);
|
||||
}
|
||||
let exportedDirMeta: cpl.CompileDirectiveMetadata;
|
||||
let exportedPipeMeta: cpl.CompilePipeMetadata;
|
||||
let exportedModuleMeta: cpl.CompileNgModuleMetadata;
|
||||
if (exportedDirMeta = this.getDirectiveMetadata(exportedType, false)) {
|
||||
exportedDirectives.push(exportedDirMeta);
|
||||
} else if (exportedPipeMeta = this.getPipeMetadata(exportedType, false)) {
|
||||
exportedPipes.push(exportedPipeMeta);
|
||||
} else if (exportedModuleMeta = this.getNgModuleMetadata(exportedType, false)) {
|
||||
exportedModules.push(exportedModuleMeta);
|
||||
} else {
|
||||
throw new BaseException(
|
||||
`Unexpected value '${stringify(exportedType)}' exported by the module '${stringify(moduleType)}'`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Note: This will be modified later, so we rely on
|
||||
// getting a new instance every time!
|
||||
const transitiveModule =
|
||||
this._getTransitiveNgModuleMetadata(importedModules, exportedModules);
|
||||
if (meta.declarations) {
|
||||
flattenArray(meta.declarations).forEach((declaredType) => {
|
||||
if (!isValidType(declaredType)) {
|
||||
throw new BaseException(
|
||||
`Unexpected value '${stringify(declaredType)}' declared by the module '${stringify(moduleType)}'`);
|
||||
}
|
||||
let declaredDirMeta: cpl.CompileDirectiveMetadata;
|
||||
let declaredPipeMeta: cpl.CompilePipeMetadata;
|
||||
if (declaredDirMeta = this.getDirectiveMetadata(declaredType, false)) {
|
||||
this._addDirectiveToModule(
|
||||
declaredDirMeta, moduleType, transitiveModule, declaredDirectives, true);
|
||||
// Collect @Component.directives/pipes/precompile into our declared directives/pipes.
|
||||
this._getTransitiveViewDirectivesAndPipes(
|
||||
declaredDirMeta, moduleType, transitiveModule, declaredDirectives, declaredPipes);
|
||||
} else if (declaredPipeMeta = this.getPipeMetadata(declaredType, false)) {
|
||||
this._addPipeToModule(
|
||||
declaredPipeMeta, moduleType, transitiveModule, declaredPipes, true);
|
||||
} else {
|
||||
throw new BaseException(
|
||||
`Unexpected value '${stringify(declaredType)}' declared by the module '${stringify(moduleType)}'`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const providers: any[] = [];
|
||||
const precompile: cpl.CompileTypeMetadata[] = [];
|
||||
if (meta.providers) {
|
||||
providers.push(...this.getProvidersMetadata(meta.providers, precompile));
|
||||
}
|
||||
if (meta.directives) {
|
||||
directives.push(...flattenArray(meta.directives)
|
||||
.map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
|
||||
}
|
||||
if (meta.pipes) {
|
||||
pipes.push(...flattenArray(meta.pipes)
|
||||
.map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
|
||||
}
|
||||
if (meta.precompile) {
|
||||
precompile.push(...flattenArray(meta.precompile)
|
||||
.map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
|
||||
}
|
||||
|
||||
compileMeta = new cpl.CompileAppModuleMetadata({
|
||||
transitiveModule.precompile.push(...precompile);
|
||||
transitiveModule.providers.push(...providers);
|
||||
|
||||
compileMeta = new cpl.CompileNgModuleMetadata({
|
||||
type: this.getTypeMetadata(moduleType, staticTypeModuleUrl(moduleType)),
|
||||
providers: providers,
|
||||
directives: directives,
|
||||
pipes: pipes,
|
||||
precompile: precompile,
|
||||
modules: modules
|
||||
declaredDirectives: declaredDirectives,
|
||||
exportedDirectives: exportedDirectives,
|
||||
declaredPipes: declaredPipes,
|
||||
exportedPipes: exportedPipes,
|
||||
importedModules: importedModules,
|
||||
exportedModules: exportedModules,
|
||||
transitiveModule: transitiveModule
|
||||
});
|
||||
if (useCache) {
|
||||
this._appModuleCache.set(moduleType, compileMeta);
|
||||
}
|
||||
transitiveModule.modules.push(compileMeta);
|
||||
this._verifyModule(compileMeta);
|
||||
this._ngModuleCache.set(moduleType, compileMeta);
|
||||
}
|
||||
return compileMeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param someType a symbol which may or may not be a directive type
|
||||
* @returns {cpl.CompileDirectiveMetadata} if possible, otherwise null.
|
||||
*/
|
||||
maybeGetDirectiveMetadata(someType: Type): cpl.CompileDirectiveMetadata {
|
||||
try {
|
||||
return this.getDirectiveMetadata(someType);
|
||||
} catch (e) {
|
||||
if (e.message.indexOf('No Directive annotation') !== -1) {
|
||||
return null;
|
||||
addComponentToModule(moduleType: Type, compType: Type) {
|
||||
const moduleMeta = this.getNgModuleMetadata(moduleType);
|
||||
// Collect @Component.directives/pipes/precompile into our declared directives/pipes.
|
||||
const compMeta = this.getDirectiveMetadata(compType, false);
|
||||
this._addDirectiveToModule(
|
||||
compMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
||||
moduleMeta.declaredDirectives);
|
||||
this._getTransitiveViewDirectivesAndPipes(
|
||||
compMeta, moduleMeta.type.runtime, moduleMeta.transitiveModule,
|
||||
moduleMeta.declaredDirectives, moduleMeta.declaredPipes);
|
||||
|
||||
moduleMeta.transitiveModule.precompile.push(compMeta.type);
|
||||
moduleMeta.precompile.push(compMeta.type);
|
||||
|
||||
this._verifyModule(moduleMeta);
|
||||
}
|
||||
|
||||
private _verifyModule(moduleMeta: cpl.CompileNgModuleMetadata) {
|
||||
moduleMeta.exportedDirectives.forEach((dirMeta) => {
|
||||
if (!moduleMeta.transitiveModule.directivesSet.has(dirMeta.type.runtime)) {
|
||||
throw new BaseException(
|
||||
`Can't export directive ${stringify(dirMeta.type.runtime)} from ${stringify(moduleMeta.type.runtime)} as it was neither declared nor imported!`);
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
moduleMeta.exportedPipes.forEach((pipeMeta) => {
|
||||
if (!moduleMeta.transitiveModule.pipesSet.has(pipeMeta.type.runtime)) {
|
||||
throw new BaseException(
|
||||
`Can't export pipe ${stringify(pipeMeta.type.runtime)} from ${stringify(moduleMeta.type.runtime)} as it was neither declared nor imported!`);
|
||||
}
|
||||
});
|
||||
moduleMeta.declaredDirectives.forEach((dirMeta) => {
|
||||
dirMeta.precompile.forEach((precompileComp) => {
|
||||
if (!moduleMeta.transitiveModule.directivesSet.has(precompileComp.runtime)) {
|
||||
throw new BaseException(
|
||||
`Component ${stringify(dirMeta.type.runtime)} in NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(precompileComp.runtime)} via "precompile" but it was neither declared nor imported into the module!`);
|
||||
}
|
||||
});
|
||||
});
|
||||
moduleMeta.precompile.forEach((precompileType) => {
|
||||
if (!moduleMeta.transitiveModule.directivesSet.has(precompileType.runtime)) {
|
||||
throw new BaseException(
|
||||
`NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(precompileType.runtime)} via "precompile" but it was neither declared nor imported!`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _addTypeToModule(type: Type, moduleType: Type) {
|
||||
const oldModule = this._ngModuleOfTypes.get(type);
|
||||
if (oldModule && oldModule !== moduleType) {
|
||||
throw new BaseException(
|
||||
`Type ${stringify(type)} is part of the declarations of 2 modules: ${stringify(oldModule)} and ${stringify(moduleType)}!`);
|
||||
}
|
||||
this._ngModuleOfTypes.set(type, moduleType);
|
||||
}
|
||||
|
||||
|
||||
private _getTransitiveViewDirectivesAndPipes(
|
||||
compMeta: cpl.CompileDirectiveMetadata, moduleType: any,
|
||||
transitiveModule: cpl.TransitiveCompileNgModuleMetadata,
|
||||
declaredDirectives: cpl.CompileDirectiveMetadata[],
|
||||
declaredPipes: cpl.CompilePipeMetadata[]) {
|
||||
if (!compMeta.isComponent) {
|
||||
return;
|
||||
}
|
||||
const addPipe = (pipeType: Type) => {
|
||||
if (!pipeType) {
|
||||
throw new BaseException(
|
||||
`Unexpected pipe value '${pipeType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
|
||||
}
|
||||
const pipeMeta = this.getPipeMetadata(pipeType);
|
||||
this._addPipeToModule(pipeMeta, moduleType, transitiveModule, declaredPipes);
|
||||
};
|
||||
|
||||
const addDirective = (dirType: Type) => {
|
||||
if (!dirType) {
|
||||
throw new BaseException(
|
||||
`Unexpected directive value '${dirType}' on the View of component '${stringify(compMeta.type.runtime)}'`);
|
||||
}
|
||||
const dirMeta = this.getDirectiveMetadata(dirType);
|
||||
if (this._addDirectiveToModule(dirMeta, moduleType, transitiveModule, declaredDirectives)) {
|
||||
this._getTransitiveViewDirectivesAndPipes(
|
||||
dirMeta, moduleType, transitiveModule, declaredDirectives, declaredPipes);
|
||||
}
|
||||
};
|
||||
const view = this._viewResolver.resolve(compMeta.type.runtime);
|
||||
if (view.pipes) {
|
||||
flattenArray(view.pipes).forEach(addPipe);
|
||||
}
|
||||
if (view.directives) {
|
||||
flattenArray(view.directives).forEach(addDirective);
|
||||
}
|
||||
}
|
||||
|
||||
private _getTransitiveNgModuleMetadata(
|
||||
importedModules: cpl.CompileNgModuleMetadata[],
|
||||
exportedModules: cpl.CompileNgModuleMetadata[]): cpl.TransitiveCompileNgModuleMetadata {
|
||||
// collect `providers` / `precompile` from all imported and all exported modules
|
||||
const transitiveModules = getTransitiveModules(importedModules.concat(exportedModules), true);
|
||||
const providers = flattenArray(transitiveModules.map((ngModule) => ngModule.providers));
|
||||
const precompile = flattenArray(transitiveModules.map((ngModule) => ngModule.precompile));
|
||||
|
||||
const transitiveExportedModules = getTransitiveModules(importedModules, false);
|
||||
const directives =
|
||||
flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedDirectives));
|
||||
const pipes = flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedPipes));
|
||||
return new cpl.TransitiveCompileNgModuleMetadata(
|
||||
transitiveModules, providers, precompile, directives, pipes);
|
||||
}
|
||||
|
||||
private _addDirectiveToModule(
|
||||
dirMeta: cpl.CompileDirectiveMetadata, moduleType: any,
|
||||
transitiveModule: cpl.TransitiveCompileNgModuleMetadata,
|
||||
declaredDirectives: cpl.CompileDirectiveMetadata[], force: boolean = false): boolean {
|
||||
if (force || !transitiveModule.directivesSet.has(dirMeta.type.runtime)) {
|
||||
transitiveModule.directivesSet.add(dirMeta.type.runtime);
|
||||
transitiveModule.directives.push(dirMeta);
|
||||
declaredDirectives.push(dirMeta);
|
||||
this._addTypeToModule(dirMeta.type.runtime, moduleType);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private _addPipeToModule(
|
||||
pipeMeta: cpl.CompilePipeMetadata, moduleType: any,
|
||||
transitiveModule: cpl.TransitiveCompileNgModuleMetadata,
|
||||
declaredPipes: cpl.CompilePipeMetadata[], force: boolean = false): boolean {
|
||||
if (force || !transitiveModule.pipesSet.has(pipeMeta.type.runtime)) {
|
||||
transitiveModule.pipesSet.add(pipeMeta.type.runtime);
|
||||
transitiveModule.pipes.push(pipeMeta);
|
||||
declaredPipes.push(pipeMeta);
|
||||
this._addTypeToModule(pipeMeta.type.runtime, moduleType);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getTypeMetadata(type: Type, moduleUrl: string, dependencies: any[] = null):
|
||||
@ -283,11 +463,14 @@ export class CompileMetadataResolver {
|
||||
});
|
||||
}
|
||||
|
||||
getPipeMetadata(pipeType: Type): cpl.CompilePipeMetadata {
|
||||
getPipeMetadata(pipeType: Type, throwIfNotFound = true): cpl.CompilePipeMetadata {
|
||||
pipeType = resolveForwardRef(pipeType);
|
||||
var meta = this._pipeCache.get(pipeType);
|
||||
if (isBlank(meta)) {
|
||||
var pipeMeta = this._pipeResolver.resolve(pipeType);
|
||||
var pipeMeta = this._pipeResolver.resolve(pipeType, throwIfNotFound);
|
||||
if (!pipeMeta) {
|
||||
return null;
|
||||
}
|
||||
meta = new cpl.CompilePipeMetadata({
|
||||
type: this.getTypeMetadata(pipeType, staticTypeModuleUrl(pipeType)),
|
||||
name: pipeMeta.name,
|
||||
@ -299,30 +482,6 @@ export class CompileMetadataResolver {
|
||||
return meta;
|
||||
}
|
||||
|
||||
getViewDirectivesMetadata(component: Type): cpl.CompileDirectiveMetadata[] {
|
||||
var view = this._viewResolver.resolve(component);
|
||||
var directives = flattenDirectives(view, this._config.deprecatedPlatformDirectives);
|
||||
for (var i = 0; i < directives.length; i++) {
|
||||
if (!isValidType(directives[i])) {
|
||||
throw new BaseException(
|
||||
`Unexpected directive value '${stringify(directives[i])}' on the View of component '${stringify(component)}'`);
|
||||
}
|
||||
}
|
||||
return directives.map(type => this.getDirectiveMetadata(type));
|
||||
}
|
||||
|
||||
getViewPipesMetadata(component: Type): cpl.CompilePipeMetadata[] {
|
||||
var view = this._viewResolver.resolve(component);
|
||||
var pipes = flattenPipes(view, this._config.deprecatedPlatformPipes);
|
||||
for (var i = 0; i < pipes.length; i++) {
|
||||
if (!isValidType(pipes[i])) {
|
||||
throw new BaseException(
|
||||
`Unexpected piped value '${stringify(pipes[i])}' on the View of component '${stringify(component)}'`);
|
||||
}
|
||||
}
|
||||
return pipes.map(type => this.getPipeMetadata(type));
|
||||
}
|
||||
|
||||
getDependenciesMetadata(typeOrFunc: Type|Function, dependencies: any[]):
|
||||
cpl.CompileDiDependencyMetadata[] {
|
||||
let hasUnknownDeps = false;
|
||||
@ -454,7 +613,7 @@ export class CompileMetadataResolver {
|
||||
}
|
||||
convertToCompileValue(provider.useValue, collectedIdentifiers);
|
||||
collectedIdentifiers.forEach((identifier) => {
|
||||
let dirMeta = this.maybeGetDirectiveMetadata(identifier.runtime);
|
||||
let dirMeta = this.getDirectiveMetadata(identifier.runtime, false);
|
||||
if (dirMeta) {
|
||||
components.push(dirMeta.type);
|
||||
}
|
||||
@ -523,35 +682,35 @@ export class CompileMetadataResolver {
|
||||
}
|
||||
}
|
||||
|
||||
function flattenDirectives(view: ViewMetadata, platformDirectives: any[]): Type[] {
|
||||
let directives: Type[] = [];
|
||||
if (isPresent(platformDirectives)) {
|
||||
flattenArray(platformDirectives, directives);
|
||||
}
|
||||
if (isPresent(view.directives)) {
|
||||
flattenArray(view.directives, directives);
|
||||
}
|
||||
return directives;
|
||||
function getTransitiveModules(
|
||||
modules: cpl.CompileNgModuleMetadata[], includeImports: boolean,
|
||||
targetModules: cpl.CompileNgModuleMetadata[] = [],
|
||||
visitedModules = new Set<Type>()): cpl.CompileNgModuleMetadata[] {
|
||||
modules.forEach((ngModule) => {
|
||||
if (!visitedModules.has(ngModule.type.runtime)) {
|
||||
visitedModules.add(ngModule.type.runtime);
|
||||
const nestedModules = includeImports ?
|
||||
ngModule.importedModules.concat(ngModule.exportedModules) :
|
||||
ngModule.exportedModules;
|
||||
getTransitiveModules(nestedModules, includeImports, targetModules, visitedModules);
|
||||
// Add after recursing so imported/exported modules are before the module itself.
|
||||
// This is important for overwriting providers of imported modules!
|
||||
targetModules.push(ngModule);
|
||||
}
|
||||
});
|
||||
return targetModules;
|
||||
}
|
||||
|
||||
function flattenPipes(view: ViewMetadata, platformPipes: any[]): Type[] {
|
||||
let pipes: Type[] = [];
|
||||
if (isPresent(platformPipes)) {
|
||||
flattenArray(platformPipes, pipes);
|
||||
}
|
||||
if (isPresent(view.pipes)) {
|
||||
flattenArray(view.pipes, pipes);
|
||||
}
|
||||
return pipes;
|
||||
}
|
||||
|
||||
function flattenArray(tree: any[], out: Array<Type> = []): Array<Type> {
|
||||
for (var i = 0; i < tree.length; i++) {
|
||||
var item = resolveForwardRef(tree[i]);
|
||||
if (isArray(item)) {
|
||||
flattenArray(item, out);
|
||||
} else {
|
||||
out.push(item);
|
||||
function flattenArray(tree: any[], out: Array<any> = []): Array<any> {
|
||||
if (tree) {
|
||||
for (var i = 0; i < tree.length; i++) {
|
||||
var item = resolveForwardRef(tree[i]);
|
||||
if (isArray(item)) {
|
||||
flattenArray(item, out);
|
||||
} else {
|
||||
out.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
@ -8,13 +8,13 @@
|
||||
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
import {CompileAppModuleMetadata, CompileDiDependencyMetadata, CompileIdentifierMetadata, CompileProviderMetadata, CompileTokenMap, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
|
||||
import {CompileDiDependencyMetadata, CompileIdentifierMap, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileProviderMetadata, CompileTokenMetadata} from './compile_metadata';
|
||||
import {isBlank, isPresent} from './facade/lang';
|
||||
import {Identifiers, identifierToken} from './identifiers';
|
||||
import * as o from './output/output_ast';
|
||||
import {convertValueToOutputAst} from './output/value_util';
|
||||
import {ParseLocation, ParseSourceFile, ParseSourceSpan} from './parse_util';
|
||||
import {AppModuleProviderParser} from './provider_parser';
|
||||
import {NgModuleProviderAnalyzer} from './provider_analyzer';
|
||||
import {ProviderAst, ProviderAstType} from './template_ast';
|
||||
import {createDiTokenExpression} from './util';
|
||||
|
||||
@ -23,57 +23,58 @@ export class ComponentFactoryDependency {
|
||||
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
|
||||
}
|
||||
|
||||
export class AppModuleCompileResult {
|
||||
export class NgModuleCompileResult {
|
||||
constructor(
|
||||
public statements: o.Statement[], public appModuleFactoryVar: string,
|
||||
public statements: o.Statement[], public ngModuleFactoryVar: string,
|
||||
public dependencies: ComponentFactoryDependency[]) {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AppModuleCompiler {
|
||||
compile(appModuleMeta: CompileAppModuleMetadata): AppModuleCompileResult {
|
||||
var sourceFileName = isPresent(appModuleMeta.type.moduleUrl) ?
|
||||
`in AppModule ${appModuleMeta.type.name} in ${appModuleMeta.type.moduleUrl}` :
|
||||
`in AppModule ${appModuleMeta.type.name}`;
|
||||
export class NgModuleCompiler {
|
||||
compile(ngModuleMeta: CompileNgModuleMetadata, extraProviders: CompileProviderMetadata[]):
|
||||
NgModuleCompileResult {
|
||||
var sourceFileName = isPresent(ngModuleMeta.type.moduleUrl) ?
|
||||
`in NgModule ${ngModuleMeta.type.name} in ${ngModuleMeta.type.moduleUrl}` :
|
||||
`in NgModule ${ngModuleMeta.type.name}`;
|
||||
var sourceFile = new ParseSourceFile('', sourceFileName);
|
||||
var sourceSpan = new ParseSourceSpan(
|
||||
new ParseLocation(sourceFile, null, null, null),
|
||||
new ParseLocation(sourceFile, null, null, null));
|
||||
var deps: ComponentFactoryDependency[] = [];
|
||||
var precompileComponents = appModuleMeta.precompile.map((precompileComp) => {
|
||||
var precompileComponents = ngModuleMeta.transitiveModule.precompile.map((precompileComp) => {
|
||||
var id = new CompileIdentifierMetadata({name: precompileComp.name});
|
||||
deps.push(new ComponentFactoryDependency(precompileComp, id));
|
||||
return id;
|
||||
});
|
||||
var builder = new _InjectorBuilder(appModuleMeta, precompileComponents, sourceSpan);
|
||||
var builder = new _InjectorBuilder(ngModuleMeta, precompileComponents, sourceSpan);
|
||||
|
||||
var providerParser = new AppModuleProviderParser(appModuleMeta, sourceSpan);
|
||||
var providerParser = new NgModuleProviderAnalyzer(ngModuleMeta, extraProviders, sourceSpan);
|
||||
providerParser.parse().forEach((provider) => builder.addProvider(provider));
|
||||
var injectorClass = builder.build();
|
||||
var appModuleFactoryVar = `${appModuleMeta.type.name}NgFactory`;
|
||||
var appModuleFactoryStmt =
|
||||
o.variable(appModuleFactoryVar)
|
||||
.set(o.importExpr(Identifiers.AppModuleFactory)
|
||||
var ngModuleFactoryVar = `${ngModuleMeta.type.name}NgFactory`;
|
||||
var ngModuleFactoryStmt =
|
||||
o.variable(ngModuleFactoryVar)
|
||||
.set(o.importExpr(Identifiers.NgModuleFactory)
|
||||
.instantiate(
|
||||
[o.variable(injectorClass.name), o.importExpr(appModuleMeta.type)],
|
||||
[o.variable(injectorClass.name), o.importExpr(ngModuleMeta.type)],
|
||||
o.importType(
|
||||
Identifiers.AppModuleFactory, [o.importType(appModuleMeta.type)],
|
||||
Identifiers.NgModuleFactory, [o.importType(ngModuleMeta.type)],
|
||||
[o.TypeModifier.Const])))
|
||||
.toDeclStmt(null, [o.StmtModifier.Final]);
|
||||
|
||||
return new AppModuleCompileResult(
|
||||
[injectorClass, appModuleFactoryStmt], appModuleFactoryVar, deps);
|
||||
return new NgModuleCompileResult(
|
||||
[injectorClass, ngModuleFactoryStmt], ngModuleFactoryVar, deps);
|
||||
}
|
||||
}
|
||||
|
||||
class _InjectorBuilder {
|
||||
private _instances = new CompileTokenMap<o.Expression>();
|
||||
private _instances = new CompileIdentifierMap<CompileTokenMetadata, o.Expression>();
|
||||
private _fields: o.ClassField[] = [];
|
||||
private _createStmts: o.Statement[] = [];
|
||||
private _getters: o.ClassGetter[] = [];
|
||||
|
||||
constructor(
|
||||
private _appModuleMeta: CompileAppModuleMetadata,
|
||||
private _ngModuleMeta: CompileNgModuleMetadata,
|
||||
private _precompileComponents: CompileIdentifierMetadata[],
|
||||
private _sourceSpan: ParseSourceSpan) {}
|
||||
|
||||
@ -97,8 +98,8 @@ class _InjectorBuilder {
|
||||
var methods = [
|
||||
new o.ClassMethod(
|
||||
'createInternal', [], this._createStmts.concat(
|
||||
new o.ReturnStatement(this._instances.get(identifierToken(this._appModuleMeta.type)))
|
||||
), o.importType(this._appModuleMeta.type)
|
||||
new o.ReturnStatement(this._instances.get(identifierToken(this._ngModuleMeta.type)))
|
||||
), o.importType(this._ngModuleMeta.type)
|
||||
),
|
||||
new o.ClassMethod(
|
||||
'getInternal',
|
||||
@ -120,10 +121,10 @@ class _InjectorBuilder {
|
||||
])
|
||||
.toStmt()]);
|
||||
|
||||
var injClassName = `${this._appModuleMeta.type.name}Injector`;
|
||||
var injClassName = `${this._ngModuleMeta.type.name}Injector`;
|
||||
return new o.ClassStmt(
|
||||
injClassName,
|
||||
o.importExpr(Identifiers.AppModuleInjector, [o.importType(this._appModuleMeta.type)]),
|
||||
o.importExpr(Identifiers.NgModuleInjector, [o.importType(this._ngModuleMeta.type)]),
|
||||
this._fields, this._getters, ctor, methods);
|
||||
}
|
||||
|
39
modules/@angular/compiler/src/ng_module_resolver.ts
Normal file
39
modules/@angular/compiler/src/ng_module_resolver.ts
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @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 {Injectable, NgModuleMetadata} from '@angular/core';
|
||||
|
||||
import {ReflectorReader, reflector} from '../core_private';
|
||||
import {BaseException} from '../src/facade/exceptions';
|
||||
import {Type, isBlank, isPresent, stringify} from '../src/facade/lang';
|
||||
|
||||
function _isNgModuleMetadata(obj: any): obj is NgModuleMetadata {
|
||||
return obj instanceof NgModuleMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves types to {@link NgModuleMetadata}.
|
||||
*/
|
||||
@Injectable()
|
||||
export class NgModuleResolver {
|
||||
constructor(private _reflector: ReflectorReader = reflector) {}
|
||||
|
||||
resolve(type: Type, throwIfNotFound = true): NgModuleMetadata {
|
||||
const ngModuleMeta: NgModuleMetadata =
|
||||
this._reflector.annotations(type).find(_isNgModuleMetadata);
|
||||
|
||||
if (isPresent(ngModuleMeta)) {
|
||||
return ngModuleMeta;
|
||||
} else {
|
||||
if (throwIfNotFound) {
|
||||
throw new BaseException(`No NgModule metadata found for '${stringify(type)}'.`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,13 +6,13 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AppModuleCompiler} from './app_module_compiler';
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeMetadata, StaticSymbol, createHostComponentMeta} from './compile_metadata';
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, StaticSymbol, createHostComponentMeta} from './compile_metadata';
|
||||
import {DirectiveNormalizer} from './directive_normalizer';
|
||||
import {ListWrapper} from './facade/collection';
|
||||
import {BaseException} from './facade/exceptions';
|
||||
import {Identifiers} from './identifiers';
|
||||
import {CompileMetadataResolver} from './metadata_resolver';
|
||||
import {NgModuleCompiler} from './ng_module_compiler';
|
||||
import {OutputEmitter} from './output/abstract_emitter';
|
||||
import * as o from './output/output_ast';
|
||||
import {CompiledStylesheet, StyleCompiler} from './style_compiler';
|
||||
@ -23,61 +23,29 @@ export class SourceModule {
|
||||
constructor(public moduleUrl: string, public source: string) {}
|
||||
}
|
||||
|
||||
export class AppModulesSummary {
|
||||
private _compAppModule = new Map<string, StaticSymbol>();
|
||||
private _hashKey(type: StaticSymbol) { return `${type.filePath}#${type.name}`; }
|
||||
|
||||
hasComponent(component: StaticSymbol): boolean {
|
||||
return this._compAppModule.has(this._hashKey(component));
|
||||
}
|
||||
|
||||
addComponent(module: StaticSymbol, component: StaticSymbol) {
|
||||
this._compAppModule.set(this._hashKey(component), module);
|
||||
}
|
||||
|
||||
getModule(comp: StaticSymbol): StaticSymbol {
|
||||
return this._compAppModule.get(this._hashKey(comp));
|
||||
}
|
||||
export class NgModulesSummary {
|
||||
constructor(public ngModuleByComponent: Map<StaticSymbol, CompileNgModuleMetadata>) {}
|
||||
}
|
||||
|
||||
export class OfflineCompiler {
|
||||
constructor(
|
||||
private _metadataResolver: CompileMetadataResolver,
|
||||
private _directiveNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
|
||||
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
|
||||
private _appModuleCompiler: AppModuleCompiler, private _outputEmitter: OutputEmitter) {}
|
||||
private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter) {}
|
||||
|
||||
analyzeModules(appModules: StaticSymbol[]): AppModulesSummary {
|
||||
let result = new AppModulesSummary();
|
||||
appModules.forEach((appModule) => {
|
||||
let appModuleMeta = this._metadataResolver.getAppModuleMetadata(appModule);
|
||||
appModuleMeta.precompile.forEach(
|
||||
(precompileComp) =>
|
||||
this._getTransitiveComponents(appModule, <any>precompileComp.runtime, result));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
analyzeModules(ngModules: StaticSymbol[]): NgModulesSummary {
|
||||
const ngModuleByComponent = new Map<StaticSymbol, CompileNgModuleMetadata>();
|
||||
|
||||
private _getTransitiveComponents(
|
||||
appModule: StaticSymbol, component: StaticSymbol,
|
||||
target: AppModulesSummary = new AppModulesSummary()): AppModulesSummary {
|
||||
var compMeta = this._metadataResolver.getDirectiveMetadata(<any>component);
|
||||
// TODO(tbosch): preserve all modules per component, not just one.
|
||||
// Then run the template parser with the union and the intersection of the modules (regarding
|
||||
// directives/pipes)
|
||||
// and report an error if some directives/pipes are only matched with the union but not with the
|
||||
// intersection!
|
||||
// -> this means that a component is used in the wrong way!
|
||||
if (!compMeta.isComponent || target.hasComponent(component)) {
|
||||
return target;
|
||||
}
|
||||
target.addComponent(appModule, component);
|
||||
this._metadataResolver.getViewDirectivesMetadata(<any>component).forEach((dirMeta) => {
|
||||
this._getTransitiveComponents(appModule, <any>dirMeta.type.runtime);
|
||||
ngModules.forEach((ngModule) => {
|
||||
const ngModuleMeta = this._metadataResolver.getNgModuleMetadata(<any>ngModule);
|
||||
ngModuleMeta.declaredDirectives.forEach((dirMeta) => {
|
||||
if (dirMeta.isComponent) {
|
||||
ngModuleByComponent.set(dirMeta.type.runtime, ngModuleMeta);
|
||||
}
|
||||
});
|
||||
});
|
||||
compMeta.precompile.forEach((precompileComp) => {
|
||||
this._getTransitiveComponents(appModule, <any>precompileComp.type.runtime);
|
||||
});
|
||||
return target;
|
||||
return new NgModulesSummary(ngModuleByComponent);
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
@ -86,55 +54,45 @@ export class OfflineCompiler {
|
||||
}
|
||||
|
||||
compile(
|
||||
moduleUrl: string, appModulesSummary: AppModulesSummary, components: StaticSymbol[],
|
||||
appModules: StaticSymbol[]): Promise<SourceModule[]> {
|
||||
moduleUrl: string, ngModulesSummary: NgModulesSummary, components: StaticSymbol[],
|
||||
ngModules: StaticSymbol[]): Promise<SourceModule[]> {
|
||||
let fileSuffix = _splitLastSuffix(moduleUrl)[1];
|
||||
let statements: o.Statement[] = [];
|
||||
let exportedVars: string[] = [];
|
||||
let outputSourceModules: SourceModule[] = [];
|
||||
|
||||
// compile app modules
|
||||
// compile all ng modules
|
||||
exportedVars.push(
|
||||
...appModules.map((appModule) => this._compileAppModule(appModule, statements)));
|
||||
...ngModules.map((ngModuleType) => this._compileModule(ngModuleType, statements)));
|
||||
|
||||
// compile components
|
||||
return Promise
|
||||
.all(components.map((compType) => {
|
||||
let appModule = appModulesSummary.getModule(compType);
|
||||
let appModuleDirectives: CompileDirectiveMetadata[] = [];
|
||||
let appModulePipes: CompilePipeMetadata[] = [];
|
||||
if (appModule) {
|
||||
let appModuleMeta = this._metadataResolver.getAppModuleMetadata(appModule);
|
||||
appModuleDirectives.push(...appModuleMeta.directives.map(
|
||||
type => this._metadataResolver.getDirectiveMetadata(type.runtime)));
|
||||
appModulePipes.push(...appModuleMeta.pipes.map(
|
||||
type => this._metadataResolver.getPipeMetadata(type.runtime)));
|
||||
const compMeta = this._metadataResolver.getDirectiveMetadata(<any>compType);
|
||||
let ngModule = ngModulesSummary.ngModuleByComponent.get(compType);
|
||||
if (!ngModule) {
|
||||
throw new BaseException(
|
||||
`Cannot determine the module for component ${compMeta.type.name}!`);
|
||||
}
|
||||
return Promise
|
||||
.all([
|
||||
this._metadataResolver.getDirectiveMetadata(<any>compType), ...appModuleDirectives,
|
||||
...this._metadataResolver.getViewDirectivesMetadata(<any>compType)
|
||||
].map(dirMeta => this._directiveNormalizer.normalizeDirective(dirMeta).asyncResult))
|
||||
.all([compMeta, ...ngModule.transitiveModule.directives].map(
|
||||
dirMeta => this._directiveNormalizer.normalizeDirective(dirMeta).asyncResult))
|
||||
.then((normalizedCompWithDirectives) => {
|
||||
let compMeta = normalizedCompWithDirectives[0];
|
||||
let dirMetas = normalizedCompWithDirectives.slice(1);
|
||||
const compMeta = normalizedCompWithDirectives[0];
|
||||
const dirMetas = normalizedCompWithDirectives.slice(1);
|
||||
_assertComponent(compMeta);
|
||||
|
||||
// compile styles
|
||||
let stylesCompileResults = this._styleCompiler.compileComponent(compMeta);
|
||||
const stylesCompileResults = this._styleCompiler.compileComponent(compMeta);
|
||||
stylesCompileResults.externalStylesheets.forEach((compiledStyleSheet) => {
|
||||
outputSourceModules.push(this._codgenStyles(compiledStyleSheet, fileSuffix));
|
||||
});
|
||||
|
||||
// compile components
|
||||
exportedVars.push(this._compileComponentFactory(compMeta, fileSuffix, statements));
|
||||
let pipeMetas = [
|
||||
...appModulePipes,
|
||||
...this._metadataResolver.getViewPipesMetadata(compMeta.type.runtime)
|
||||
];
|
||||
exportedVars.push(this._compileComponent(
|
||||
compMeta, dirMetas, pipeMetas, stylesCompileResults.componentStylesheet,
|
||||
fileSuffix, statements));
|
||||
compMeta, dirMetas, ngModule.transitiveModule.pipes,
|
||||
stylesCompileResults.componentStylesheet, fileSuffix, statements));
|
||||
});
|
||||
}))
|
||||
.then(() => {
|
||||
@ -146,21 +104,21 @@ export class OfflineCompiler {
|
||||
});
|
||||
}
|
||||
|
||||
private _compileAppModule(appModuleType: StaticSymbol, targetStatements: o.Statement[]): string {
|
||||
let appModuleMeta = this._metadataResolver.getAppModuleMetadata(appModuleType);
|
||||
let appCompileResult = this._appModuleCompiler.compile(appModuleMeta);
|
||||
private _compileModule(ngModuleType: StaticSymbol, targetStatements: o.Statement[]): string {
|
||||
const ngModule = this._metadataResolver.getNgModuleMetadata(<any>ngModuleType);
|
||||
let appCompileResult = this._ngModuleCompiler.compile(ngModule, []);
|
||||
appCompileResult.dependencies.forEach((dep) => {
|
||||
dep.placeholder.name = _componentFactoryName(dep.comp);
|
||||
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp.moduleUrl);
|
||||
});
|
||||
targetStatements.push(...appCompileResult.statements);
|
||||
return appCompileResult.appModuleFactoryVar;
|
||||
return appCompileResult.ngModuleFactoryVar;
|
||||
}
|
||||
|
||||
private _compileComponentFactory(
|
||||
compMeta: CompileDirectiveMetadata, fileSuffix: string,
|
||||
targetStatements: o.Statement[]): string {
|
||||
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||
var hostMeta = createHostComponentMeta(compMeta);
|
||||
var hostViewFactoryVar =
|
||||
this._compileComponent(hostMeta, [compMeta], [], null, fileSuffix, targetStatements);
|
||||
var compFactoryVar = _componentFactoryName(compMeta.type);
|
||||
|
@ -30,7 +30,7 @@ export class PipeResolver {
|
||||
/**
|
||||
* Return {@link PipeMetadata} for a given `Type`.
|
||||
*/
|
||||
resolve(type: Type): PipeMetadata {
|
||||
resolve(type: Type, throwIfNotFound = true): PipeMetadata {
|
||||
var metas = this._reflector.annotations(resolveForwardRef(type));
|
||||
if (isPresent(metas)) {
|
||||
var annotation = metas.find(_isPipeMetadata);
|
||||
@ -38,6 +38,9 @@ export class PipeResolver {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
throw new BaseException(`No Pipe decorator found on ${stringify(type)}`);
|
||||
if (throwIfNotFound) {
|
||||
throw new BaseException(`No Pipe decorator found on ${stringify(type)}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import {ListWrapper} from '../src/facade/collection';
|
||||
import {BaseException} from '../src/facade/exceptions';
|
||||
import {isArray, isBlank, isPresent, normalizeBlank} from '../src/facade/lang';
|
||||
|
||||
import {CompileAppModuleMetadata, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMap, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
|
||||
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileIdentifierMap, CompileNgModuleMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
|
||||
import {Identifiers, identifierToken} from './identifiers';
|
||||
import {ParseError, ParseSourceSpan} from './parse_util';
|
||||
import {AttrAst, DirectiveAst, ProviderAst, ProviderAstType, ReferenceAst, VariableAst} from './template_ast';
|
||||
@ -23,16 +23,16 @@ export class ProviderViewContext {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
viewQueries: CompileTokenMap<CompileQueryMetadata[]>;
|
||||
viewQueries: CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]>;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
viewProviders: CompileTokenMap<boolean>;
|
||||
viewProviders: CompileIdentifierMap<CompileTokenMetadata, boolean>;
|
||||
errors: ProviderError[] = [];
|
||||
|
||||
constructor(public component: CompileDirectiveMetadata, public sourceSpan: ParseSourceSpan) {
|
||||
this.viewQueries = _getViewQueries(component);
|
||||
this.viewProviders = new CompileTokenMap<boolean>();
|
||||
this.viewProviders = new CompileIdentifierMap<CompileTokenMetadata, boolean>();
|
||||
_normalizeProviders(component.viewProviders, sourceSpan, this.errors).forEach((provider) => {
|
||||
if (isBlank(this.viewProviders.get(provider.token))) {
|
||||
this.viewProviders.add(provider.token, true);
|
||||
@ -42,11 +42,11 @@ export class ProviderViewContext {
|
||||
}
|
||||
|
||||
export class ProviderElementContext {
|
||||
private _contentQueries: CompileTokenMap<CompileQueryMetadata[]>;
|
||||
private _contentQueries: CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]>;
|
||||
|
||||
private _transformedProviders = new CompileTokenMap<ProviderAst>();
|
||||
private _seenProviders = new CompileTokenMap<boolean>();
|
||||
private _allProviders: CompileTokenMap<ProviderAst>;
|
||||
private _transformedProviders = new CompileIdentifierMap<CompileTokenMetadata, ProviderAst>();
|
||||
private _seenProviders = new CompileIdentifierMap<CompileTokenMetadata, boolean>();
|
||||
private _allProviders: CompileIdentifierMap<CompileTokenMetadata, ProviderAst>;
|
||||
private _attrs: {[key: string]: string};
|
||||
private _hasViewContainer: boolean = false;
|
||||
|
||||
@ -60,7 +60,7 @@ export class ProviderElementContext {
|
||||
this._allProviders =
|
||||
_resolveProvidersFromDirectives(directivesMeta, _sourceSpan, _viewContext.errors);
|
||||
this._contentQueries = _getContentQueries(directivesMeta);
|
||||
var queriedTokens = new CompileTokenMap<boolean>();
|
||||
var queriedTokens = new CompileIdentifierMap<CompileTokenMetadata, boolean>();
|
||||
this._allProviders.values().forEach(
|
||||
(provider) => { this._addQueryReadsTo(provider.token, queriedTokens); });
|
||||
refs.forEach((refAst) => {
|
||||
@ -100,7 +100,9 @@ export class ProviderElementContext {
|
||||
|
||||
get transformedHasViewContainer(): boolean { return this._hasViewContainer; }
|
||||
|
||||
private _addQueryReadsTo(token: CompileTokenMetadata, queryReadTokens: CompileTokenMap<boolean>) {
|
||||
private _addQueryReadsTo(
|
||||
token: CompileTokenMetadata,
|
||||
queryReadTokens: CompileIdentifierMap<CompileTokenMetadata, boolean>) {
|
||||
this._getQueriesFor(token).forEach((query) => {
|
||||
const queryReadToken = isPresent(query.read) ? query.read : token;
|
||||
if (isBlank(queryReadTokens.get(queryReadToken))) {
|
||||
@ -272,24 +274,28 @@ export class ProviderElementContext {
|
||||
}
|
||||
|
||||
|
||||
export class AppModuleProviderParser {
|
||||
private _transformedProviders = new CompileTokenMap<ProviderAst>();
|
||||
private _seenProviders = new CompileTokenMap<boolean>();
|
||||
export class NgModuleProviderAnalyzer {
|
||||
private _transformedProviders = new CompileIdentifierMap<CompileTokenMetadata, ProviderAst>();
|
||||
private _seenProviders = new CompileIdentifierMap<CompileTokenMetadata, boolean>();
|
||||
private _unparsedProviders: any[] = [];
|
||||
private _allProviders: CompileTokenMap<ProviderAst>;
|
||||
private _allProviders: CompileIdentifierMap<CompileTokenMetadata, ProviderAst>;
|
||||
private _errors: ProviderError[] = [];
|
||||
|
||||
constructor(appModule: CompileAppModuleMetadata, sourceSpan: ParseSourceSpan) {
|
||||
this._allProviders = new CompileTokenMap<ProviderAst>();
|
||||
[appModule.type].concat(appModule.modules).forEach((appModuleType: CompileTypeMetadata) => {
|
||||
const appModuleProvider = new CompileProviderMetadata(
|
||||
{token: new CompileTokenMetadata({identifier: appModuleType}), useClass: appModuleType});
|
||||
constructor(
|
||||
ngModule: CompileNgModuleMetadata, extraProviders: CompileProviderMetadata[],
|
||||
sourceSpan: ParseSourceSpan) {
|
||||
this._allProviders = new CompileIdentifierMap<CompileTokenMetadata, ProviderAst>();
|
||||
const ngModuleTypes = ngModule.transitiveModule.modules.map((moduleMeta) => moduleMeta.type);
|
||||
ngModuleTypes.forEach((ngModuleType: CompileTypeMetadata) => {
|
||||
const ngModuleProvider = new CompileProviderMetadata(
|
||||
{token: new CompileTokenMetadata({identifier: ngModuleType}), useClass: ngModuleType});
|
||||
_resolveProviders(
|
||||
[appModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors,
|
||||
[ngModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors,
|
||||
this._allProviders);
|
||||
});
|
||||
_resolveProviders(
|
||||
_normalizeProviders(appModule.providers, sourceSpan, this._errors),
|
||||
_normalizeProviders(
|
||||
ngModule.transitiveModule.providers.concat(extraProviders), sourceSpan, this._errors),
|
||||
ProviderAstType.PublicService, false, sourceSpan, this._errors, this._allProviders);
|
||||
}
|
||||
|
||||
@ -436,8 +442,8 @@ function _normalizeProviders(
|
||||
|
||||
function _resolveProvidersFromDirectives(
|
||||
directives: CompileDirectiveMetadata[], sourceSpan: ParseSourceSpan,
|
||||
targetErrors: ParseError[]): CompileTokenMap<ProviderAst> {
|
||||
var providersByToken = new CompileTokenMap<ProviderAst>();
|
||||
targetErrors: ParseError[]): CompileIdentifierMap<CompileTokenMetadata, ProviderAst> {
|
||||
var providersByToken = new CompileIdentifierMap<CompileTokenMetadata, ProviderAst>();
|
||||
directives.forEach((directive) => {
|
||||
var dirProvider = new CompileProviderMetadata(
|
||||
{token: new CompileTokenMetadata({identifier: directive.type}), useClass: directive.type});
|
||||
@ -464,7 +470,7 @@ function _resolveProvidersFromDirectives(
|
||||
function _resolveProviders(
|
||||
providers: CompileProviderMetadata[], providerType: ProviderAstType, eager: boolean,
|
||||
sourceSpan: ParseSourceSpan, targetErrors: ParseError[],
|
||||
targetProvidersByToken: CompileTokenMap<ProviderAst>) {
|
||||
targetProvidersByToken: CompileIdentifierMap<CompileTokenMetadata, ProviderAst>) {
|
||||
providers.forEach((provider) => {
|
||||
var resolvedProvider = targetProvidersByToken.get(provider.token);
|
||||
if (isPresent(resolvedProvider) && resolvedProvider.multiProvider !== provider.multi) {
|
||||
@ -487,8 +493,8 @@ function _resolveProviders(
|
||||
|
||||
|
||||
function _getViewQueries(component: CompileDirectiveMetadata):
|
||||
CompileTokenMap<CompileQueryMetadata[]> {
|
||||
var viewQueries = new CompileTokenMap<CompileQueryMetadata[]>();
|
||||
CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]> {
|
||||
var viewQueries = new CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]>();
|
||||
if (isPresent(component.viewQueries)) {
|
||||
component.viewQueries.forEach((query) => _addQueryToTokenMap(viewQueries, query));
|
||||
}
|
||||
@ -501,8 +507,8 @@ function _getViewQueries(component: CompileDirectiveMetadata):
|
||||
}
|
||||
|
||||
function _getContentQueries(directives: CompileDirectiveMetadata[]):
|
||||
CompileTokenMap<CompileQueryMetadata[]> {
|
||||
var contentQueries = new CompileTokenMap<CompileQueryMetadata[]>();
|
||||
CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]> {
|
||||
var contentQueries = new CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]>();
|
||||
directives.forEach(directive => {
|
||||
if (isPresent(directive.queries)) {
|
||||
directive.queries.forEach((query) => _addQueryToTokenMap(contentQueries, query));
|
||||
@ -517,7 +523,8 @@ function _getContentQueries(directives: CompileDirectiveMetadata[]):
|
||||
}
|
||||
|
||||
function _addQueryToTokenMap(
|
||||
map: CompileTokenMap<CompileQueryMetadata[]>, query: CompileQueryMetadata) {
|
||||
map: CompileIdentifierMap<CompileTokenMetadata, CompileQueryMetadata[]>,
|
||||
query: CompileQueryMetadata) {
|
||||
query.selectors.forEach((token: CompileTokenMetadata) => {
|
||||
var entry = map.get(token);
|
||||
if (isBlank(entry)) {
|
@ -6,19 +6,19 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AppModuleFactory, AppModuleMetadata, Compiler, ComponentFactory, ComponentResolver, ComponentStillLoadingError, Injectable, Injector, OptionalMetadata, Provider, SkipSelfMetadata} from '@angular/core';
|
||||
import {Console} from '../core_private';
|
||||
import {Compiler, ComponentFactory, ComponentResolver, ComponentStillLoadingError, Injectable, Injector, NgModule, NgModuleFactory, NgModuleMetadata, OptionalMetadata, Provider, SkipSelfMetadata} from '@angular/core';
|
||||
|
||||
import {Console} from '../core_private';
|
||||
import {BaseException} from '../src/facade/exceptions';
|
||||
import {ConcreteType, IS_DART, Type, isBlank, isString, stringify} from '../src/facade/lang';
|
||||
|
||||
import {ListWrapper,} from '../src/facade/collection';
|
||||
import {PromiseWrapper} from '../src/facade/async';
|
||||
import {createHostComponentMeta, CompileDirectiveMetadata, CompilePipeMetadata, CompileIdentifierMetadata} from './compile_metadata';
|
||||
import {createHostComponentMeta, CompileDirectiveMetadata, CompilePipeMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata} from './compile_metadata';
|
||||
import {TemplateAst,} from './template_ast';
|
||||
import {StyleCompiler, StylesCompileDependency, CompiledStylesheet} from './style_compiler';
|
||||
import {ViewCompiler, ViewCompileResult, ViewFactoryDependency, ComponentFactoryDependency} from './view_compiler/view_compiler';
|
||||
import {AppModuleCompiler} from './app_module_compiler';
|
||||
import {NgModuleCompiler} from './ng_module_compiler';
|
||||
import {TemplateParser} from './template_parser';
|
||||
import {DirectiveNormalizer} from './directive_normalizer';
|
||||
import {CompileMetadataResolver} from './metadata_resolver';
|
||||
@ -38,122 +38,123 @@ import {SyncAsyncResult} from './util';
|
||||
* application to XSS risks. For more detail, see the [Security Guide](http://g.co/ng/security).
|
||||
*/
|
||||
@Injectable()
|
||||
export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
export class RuntimeCompiler implements Compiler {
|
||||
private _compiledTemplateCache = new Map<Type, CompiledTemplate>();
|
||||
private _compiledHostTemplateCache = new Map<Type, CompiledTemplate>();
|
||||
private _compiledAppModuleCache = new Map<Type, AppModuleFactory<any>>();
|
||||
|
||||
private _warnOnComponentResolver = true;
|
||||
private _compiledNgModuleCache = new Map<Type, NgModuleFactory<any>>();
|
||||
|
||||
constructor(
|
||||
private _injector: Injector, private _metadataResolver: CompileMetadataResolver,
|
||||
private _templateNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
|
||||
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
|
||||
private _appModuleCompiler: AppModuleCompiler, private _genConfig: CompilerConfig,
|
||||
private _console: Console) {
|
||||
const flatDeprecatedPlatformDirectives =
|
||||
ListWrapper.flatten(_genConfig.deprecatedPlatformDirectives);
|
||||
if (flatDeprecatedPlatformDirectives.length > 0) {
|
||||
this._console.warn(
|
||||
`Providing platform directives via the PLATFORM_DIRECTIVES provider or the "CompilerConfig" is deprecated. Provide platform directives via an @AppModule instead. Directives: ` +
|
||||
flatDeprecatedPlatformDirectives.map(stringify));
|
||||
}
|
||||
const flatDeprecatedPlatformPipes = ListWrapper.flatten(_genConfig.deprecatedPlatformPipes);
|
||||
if (flatDeprecatedPlatformPipes.length > 0) {
|
||||
this._console.warn(
|
||||
`Providing platform pipes via the PLATFORM_PIPES provider or the "CompilerConfig" is deprecated. Provide platform pipes via an @AppModule instead. Pipes: ` +
|
||||
flatDeprecatedPlatformPipes.map(stringify));
|
||||
}
|
||||
}
|
||||
private _ngModuleCompiler: NgModuleCompiler, private _compilerConfig: CompilerConfig,
|
||||
private _console: Console) {}
|
||||
|
||||
get injector(): Injector { return this._injector; }
|
||||
|
||||
resolveComponent(component: Type|string): Promise<ComponentFactory<any>> {
|
||||
if (isString(component)) {
|
||||
return PromiseWrapper.reject(
|
||||
new BaseException(`Cannot resolve component using '${component}'.`), null);
|
||||
compileModuleSync<T>(moduleType: ConcreteType<T>): NgModuleFactory<T> {
|
||||
return this._compileModuleAndComponents(moduleType, true).syncResult;
|
||||
}
|
||||
|
||||
compileModuleAsync<T>(moduleType: ConcreteType<T>): Promise<NgModuleFactory<T>> {
|
||||
return this._compileModuleAndComponents(moduleType, false).asyncResult;
|
||||
}
|
||||
|
||||
compileComponentAsync<T>(compType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
|
||||
Promise<ComponentFactory<T>> {
|
||||
if (!ngModule) {
|
||||
throw new BaseException(
|
||||
`Calling compileComponentAsync on the root compiler without a module is not allowed! (Compiling component ${stringify(compType)})`);
|
||||
}
|
||||
if (this._warnOnComponentResolver) {
|
||||
this._console.warn(ComponentResolver.DynamicCompilationDeprecationMsg);
|
||||
this._warnOnComponentResolver = false;
|
||||
return this._compileComponentInModule(compType, false, ngModule).asyncResult;
|
||||
}
|
||||
|
||||
compileComponentSync<T>(compType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
|
||||
ComponentFactory<T> {
|
||||
if (!ngModule) {
|
||||
throw new BaseException(
|
||||
`Calling compileComponentSync on the root compiler without a module is not allowed! (Compiling component ${stringify(compType)})`);
|
||||
}
|
||||
return this.compileComponentAsync(<ConcreteType<any>>component);
|
||||
return this._compileComponentInModule(compType, true, ngModule).syncResult;
|
||||
}
|
||||
|
||||
compileAppModuleSync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
|
||||
AppModuleFactory<T> {
|
||||
return this._compileAppModule(moduleType, true, metadata).syncResult;
|
||||
private _compileModuleAndComponents<T>(moduleType: ConcreteType<T>, isSync: boolean):
|
||||
SyncAsyncResult<NgModuleFactory<T>> {
|
||||
const componentPromise = this._compileComponents(moduleType, isSync);
|
||||
const ngModuleFactory = this._compileModule(moduleType);
|
||||
return new SyncAsyncResult(ngModuleFactory, componentPromise.then(() => ngModuleFactory));
|
||||
}
|
||||
|
||||
compileAppModuleAsync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
|
||||
Promise<AppModuleFactory<T>> {
|
||||
return this._compileAppModule(moduleType, false, metadata).asyncResult;
|
||||
}
|
||||
|
||||
private _compileAppModule<T>(
|
||||
moduleType: ConcreteType<T>, isSync: boolean,
|
||||
metadata: AppModuleMetadata = null): SyncAsyncResult<AppModuleFactory<T>> {
|
||||
// Only cache if we read the metadata via the reflector,
|
||||
// as we use the moduleType as cache key.
|
||||
let useCache = !metadata;
|
||||
let appModuleFactory = this._compiledAppModuleCache.get(moduleType);
|
||||
let componentCompilePromises: Promise<any>[] = [];
|
||||
if (!appModuleFactory || !useCache) {
|
||||
var compileModuleMeta = this._metadataResolver.getAppModuleMetadata(moduleType, metadata);
|
||||
let boundCompilerFactory = (parentResolver: ComponentResolver) => new BoundCompiler(
|
||||
this, compileModuleMeta.directives.map(dir => dir.type.runtime),
|
||||
compileModuleMeta.pipes.map((pipe) => pipe.type.runtime), parentResolver);
|
||||
private _compileModule<T>(moduleType: ConcreteType<T>): NgModuleFactory<T> {
|
||||
let ngModuleFactory = this._compiledNgModuleCache.get(moduleType);
|
||||
if (!ngModuleFactory) {
|
||||
const moduleMeta = this._metadataResolver.getNgModuleMetadata(moduleType);
|
||||
const transitiveModuleMeta = moduleMeta.transitiveModule;
|
||||
let boundCompilerFactory = (parentResolver: ComponentResolver) =>
|
||||
new ModuleBoundCompiler(this, moduleMeta.type.runtime, parentResolver, this._console);
|
||||
// Always provide a bound Compiler and ComponentResolver
|
||||
compileModuleMeta.providers.push(
|
||||
this._metadataResolver.getProviderMetadata(new Provider(Compiler, {
|
||||
useFactory: boundCompilerFactory,
|
||||
deps: [[new OptionalMetadata(), new SkipSelfMetadata(), ComponentResolver]]
|
||||
})));
|
||||
compileModuleMeta.providers.push(this._metadataResolver.getProviderMetadata(
|
||||
new Provider(ComponentResolver, {useExisting: Compiler})));
|
||||
var compileResult = this._appModuleCompiler.compile(compileModuleMeta);
|
||||
const extraProviders = [
|
||||
this._metadataResolver.getProviderMetadata(new Provider(Compiler, {
|
||||
useFactory: boundCompilerFactory,
|
||||
deps: [[new OptionalMetadata(), new SkipSelfMetadata(), ComponentResolver]]
|
||||
})),
|
||||
this._metadataResolver.getProviderMetadata(
|
||||
new Provider(ComponentResolver, {useExisting: Compiler}))
|
||||
];
|
||||
var compileResult = this._ngModuleCompiler.compile(moduleMeta, extraProviders);
|
||||
compileResult.dependencies.forEach((dep) => {
|
||||
let compileResult = this._compileComponent(
|
||||
dep.comp.runtime, isSync,
|
||||
compileModuleMeta.directives.map(compileType => <any>compileType.runtime),
|
||||
compileModuleMeta.pipes.map(compileType => <any>compileType.runtime));
|
||||
dep.placeholder.runtime = compileResult.syncResult;
|
||||
componentCompilePromises.push(compileResult.asyncResult);
|
||||
dep.placeholder.runtime =
|
||||
this._assertComponentKnown(dep.comp.runtime, true).proxyComponentFactory;
|
||||
dep.placeholder.name = `compFactory_${dep.comp.name}`;
|
||||
});
|
||||
if (IS_DART || !this._genConfig.useJit) {
|
||||
appModuleFactory =
|
||||
interpretStatements(compileResult.statements, compileResult.appModuleFactoryVar);
|
||||
if (IS_DART || !this._compilerConfig.useJit) {
|
||||
ngModuleFactory =
|
||||
interpretStatements(compileResult.statements, compileResult.ngModuleFactoryVar);
|
||||
} else {
|
||||
appModuleFactory = jitStatements(
|
||||
`${compileModuleMeta.type.name}.ngfactory.js`, compileResult.statements,
|
||||
compileResult.appModuleFactoryVar);
|
||||
}
|
||||
if (useCache) {
|
||||
this._compiledAppModuleCache.set(moduleType, appModuleFactory);
|
||||
ngModuleFactory = jitStatements(
|
||||
`${moduleMeta.type.name}.ngfactory.js`, compileResult.statements,
|
||||
compileResult.ngModuleFactoryVar);
|
||||
}
|
||||
this._compiledNgModuleCache.set(moduleMeta.type.runtime, ngModuleFactory);
|
||||
}
|
||||
return new SyncAsyncResult(
|
||||
appModuleFactory, Promise.all(componentCompilePromises).then(() => appModuleFactory));
|
||||
return ngModuleFactory;
|
||||
}
|
||||
|
||||
compileComponentAsync<T>(compType: ConcreteType<T>): Promise<ComponentFactory<T>> {
|
||||
return this._compileComponent(compType, false, [], []).asyncResult;
|
||||
}
|
||||
private _compileComponentInModule<T>(
|
||||
compType: ConcreteType<T>, isSync: boolean,
|
||||
moduleType: ConcreteType<any>): SyncAsyncResult<ComponentFactory<T>> {
|
||||
this._metadataResolver.addComponentToModule(moduleType, compType);
|
||||
|
||||
compileComponentSync<T>(compType: ConcreteType<T>): ComponentFactory<T> {
|
||||
return this._compileComponent(compType, true, [], []).syncResult;
|
||||
const componentPromise = this._compileComponents(moduleType, isSync);
|
||||
const componentFactory: ComponentFactory<T> =
|
||||
this._assertComponentKnown(compType, true).proxyComponentFactory;
|
||||
|
||||
return new SyncAsyncResult(componentFactory, componentPromise.then(() => componentFactory));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
_compileComponent<T>(
|
||||
compType: ConcreteType<T>, isSync: boolean, moduleDirectives: ConcreteType<any>[],
|
||||
modulePipes: ConcreteType<any>[]): SyncAsyncResult<ComponentFactory<T>> {
|
||||
var templates =
|
||||
this._getTransitiveCompiledTemplates(compType, true, moduleDirectives, modulePipes);
|
||||
_compileComponents(mainModule: Type, isSync: boolean): Promise<any> {
|
||||
const templates = new Set<CompiledTemplate>();
|
||||
var loadingPromises: Promise<any>[] = [];
|
||||
|
||||
const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule);
|
||||
ngModule.transitiveModule.modules.forEach((localModuleMeta) => {
|
||||
localModuleMeta.declaredDirectives.forEach((dirMeta) => {
|
||||
if (dirMeta.isComponent) {
|
||||
templates.add(this._createCompiledTemplate(
|
||||
dirMeta, localModuleMeta.transitiveModule.directives,
|
||||
localModuleMeta.transitiveModule.pipes));
|
||||
dirMeta.precompile.forEach((precompileType) => {
|
||||
templates.add(this._createCompiledHostTemplate(precompileType.runtime));
|
||||
});
|
||||
}
|
||||
});
|
||||
localModuleMeta.precompile.forEach((precompileType) => {
|
||||
templates.add(this._createCompiledHostTemplate(precompileType.runtime));
|
||||
});
|
||||
});
|
||||
templates.forEach((template) => {
|
||||
if (template.loading) {
|
||||
if (isSync) {
|
||||
@ -167,16 +168,14 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
() => { templates.forEach((template) => { this._compileTemplate(template); }); };
|
||||
if (isSync) {
|
||||
compile();
|
||||
return Promise.resolve(null);
|
||||
} else {
|
||||
return Promise.all(loadingPromises).then(compile);
|
||||
}
|
||||
let result = this._compiledHostTemplateCache.get(compType).proxyComponentFactory;
|
||||
return new SyncAsyncResult(result, Promise.all(loadingPromises).then(() => {
|
||||
compile();
|
||||
return result;
|
||||
}));
|
||||
}
|
||||
|
||||
clearCacheFor(type: Type) {
|
||||
this._compiledAppModuleCache.delete(type);
|
||||
this._compiledNgModuleCache.delete(type);
|
||||
this._metadataResolver.clearCacheFor(type);
|
||||
this._compiledHostTemplateCache.delete(type);
|
||||
var compiledTemplate = this._compiledTemplateCache.get(type);
|
||||
@ -191,71 +190,54 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
this._compiledTemplateCache.clear();
|
||||
this._compiledHostTemplateCache.clear();
|
||||
this._templateNormalizer.clearCache();
|
||||
this._compiledAppModuleCache.clear();
|
||||
this._compiledNgModuleCache.clear();
|
||||
}
|
||||
|
||||
private _createCompiledHostTemplate(type: Type): CompiledTemplate {
|
||||
var compiledTemplate = this._compiledHostTemplateCache.get(type);
|
||||
private _createCompiledHostTemplate(compType: Type): CompiledTemplate {
|
||||
var compiledTemplate = this._compiledHostTemplateCache.get(compType);
|
||||
if (isBlank(compiledTemplate)) {
|
||||
var compMeta = this._metadataResolver.getDirectiveMetadata(type);
|
||||
var compMeta = this._metadataResolver.getDirectiveMetadata(compType);
|
||||
assertComponent(compMeta);
|
||||
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||
var hostMeta = createHostComponentMeta(compMeta);
|
||||
compiledTemplate = new CompiledTemplate(
|
||||
true, compMeta.selector, compMeta.type, [], [type], [], [],
|
||||
true, compMeta.selector, compMeta.type, [compMeta], [],
|
||||
this._templateNormalizer.normalizeDirective(hostMeta));
|
||||
this._compiledHostTemplateCache.set(type, compiledTemplate);
|
||||
this._compiledHostTemplateCache.set(compType, compiledTemplate);
|
||||
}
|
||||
return compiledTemplate;
|
||||
}
|
||||
|
||||
private _createCompiledTemplate(
|
||||
type: Type, moduleDirectives: ConcreteType<any>[],
|
||||
modulePipes: ConcreteType<any>[]): CompiledTemplate {
|
||||
var compiledTemplate = this._compiledTemplateCache.get(type);
|
||||
compMeta: CompileDirectiveMetadata, directives: CompileDirectiveMetadata[],
|
||||
pipes: CompilePipeMetadata[]): CompiledTemplate {
|
||||
var compiledTemplate = this._compiledTemplateCache.get(compMeta.type.runtime);
|
||||
if (isBlank(compiledTemplate)) {
|
||||
const compMeta = this._metadataResolver.getDirectiveMetadata(type);
|
||||
assertComponent(compMeta);
|
||||
const viewDirectives: CompileDirectiveMetadata[] = [];
|
||||
moduleDirectives.forEach(
|
||||
(type) => viewDirectives.push(this._metadataResolver.getDirectiveMetadata(type)));
|
||||
const viewComponentTypes: Type[] = [];
|
||||
this._metadataResolver.getViewDirectivesMetadata(type).forEach(dirOrComp => {
|
||||
if (dirOrComp.isComponent) {
|
||||
viewComponentTypes.push(dirOrComp.type.runtime);
|
||||
} else {
|
||||
viewDirectives.push(dirOrComp);
|
||||
}
|
||||
});
|
||||
const precompileComponentTypes = compMeta.precompile.map((typeMeta) => typeMeta.runtime);
|
||||
const pipes = [
|
||||
...modulePipes.map((type) => this._metadataResolver.getPipeMetadata(type)),
|
||||
...this._metadataResolver.getViewPipesMetadata(type)
|
||||
];
|
||||
compiledTemplate = new CompiledTemplate(
|
||||
false, compMeta.selector, compMeta.type, viewDirectives, viewComponentTypes,
|
||||
precompileComponentTypes, pipes, this._templateNormalizer.normalizeDirective(compMeta));
|
||||
this._compiledTemplateCache.set(type, compiledTemplate);
|
||||
false, compMeta.selector, compMeta.type, directives, pipes,
|
||||
this._templateNormalizer.normalizeDirective(compMeta));
|
||||
this._compiledTemplateCache.set(compMeta.type.runtime, compiledTemplate);
|
||||
}
|
||||
return compiledTemplate;
|
||||
}
|
||||
|
||||
private _getTransitiveCompiledTemplates(
|
||||
compType: Type, isHost: boolean, moduleDirectives: ConcreteType<any>[],
|
||||
modulePipes: ConcreteType<any>[],
|
||||
target: Set<CompiledTemplate> = new Set<CompiledTemplate>()): Set<CompiledTemplate> {
|
||||
const template = isHost ? this._createCompiledHostTemplate(compType) :
|
||||
this._createCompiledTemplate(compType, moduleDirectives, modulePipes);
|
||||
if (!target.has(template)) {
|
||||
target.add(template);
|
||||
template.viewComponentTypes.forEach((compType) => {
|
||||
this._getTransitiveCompiledTemplates(
|
||||
compType, false, moduleDirectives, modulePipes, target);
|
||||
});
|
||||
template.precompileHostComponentTypes.forEach((compType) => {
|
||||
this._getTransitiveCompiledTemplates(compType, true, moduleDirectives, modulePipes, target);
|
||||
});
|
||||
private _assertComponentKnown(compType: any, isHost: boolean): CompiledTemplate {
|
||||
const compiledTemplate = isHost ? this._compiledHostTemplateCache.get(compType) :
|
||||
this._compiledTemplateCache.get(compType);
|
||||
if (!compiledTemplate) {
|
||||
throw new BaseException(
|
||||
`Illegal state: CompiledTemplate for ${stringify(compType)} (isHost: ${isHost}) does not exist!`);
|
||||
}
|
||||
return target;
|
||||
return compiledTemplate;
|
||||
}
|
||||
|
||||
private _assertComponentLoaded(compType: any, isHost: boolean): CompiledTemplate {
|
||||
const compiledTemplate = this._assertComponentKnown(compType, isHost);
|
||||
if (compiledTemplate.loading) {
|
||||
throw new BaseException(
|
||||
`Illegal state: CompiledTemplate for ${stringify(compType)} (isHost: ${isHost}) is still loading!`);
|
||||
}
|
||||
return compiledTemplate;
|
||||
}
|
||||
|
||||
private _compileTemplate(template: CompiledTemplate) {
|
||||
@ -270,7 +252,7 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
this._resolveStylesCompileResult(
|
||||
stylesCompileResult.componentStylesheet, externalStylesheetsByModuleUrl);
|
||||
const viewCompMetas = template.viewComponentTypes.map(
|
||||
(compType) => this._compiledTemplateCache.get(compType).normalizedCompMeta);
|
||||
(compType) => this._assertComponentLoaded(compType, false).normalizedCompMeta);
|
||||
const parsedTemplate = this._templateParser.parse(
|
||||
compMeta, compMeta.template.template, template.viewDirectives.concat(viewCompMetas),
|
||||
template.viewPipes, compMeta.type.name);
|
||||
@ -281,12 +263,12 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
let depTemplate: CompiledTemplate;
|
||||
if (dep instanceof ViewFactoryDependency) {
|
||||
let vfd = <ViewFactoryDependency>dep;
|
||||
depTemplate = this._compiledTemplateCache.get(vfd.comp.runtime);
|
||||
depTemplate = this._assertComponentLoaded(vfd.comp.runtime, false);
|
||||
vfd.placeholder.runtime = depTemplate.proxyViewFactory;
|
||||
vfd.placeholder.name = `viewFactory_${vfd.comp.name}`;
|
||||
} else if (dep instanceof ComponentFactoryDependency) {
|
||||
let cfd = <ComponentFactoryDependency>dep;
|
||||
depTemplate = this._compiledHostTemplateCache.get(cfd.comp.runtime);
|
||||
depTemplate = this._assertComponentLoaded(cfd.comp.runtime, true);
|
||||
cfd.placeholder.runtime = depTemplate.proxyComponentFactory;
|
||||
cfd.placeholder.name = `compFactory_${cfd.comp.name}`;
|
||||
}
|
||||
@ -294,7 +276,7 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
const statements =
|
||||
stylesCompileResult.componentStylesheet.statements.concat(compileResult.statements);
|
||||
let factory: any;
|
||||
if (IS_DART || !this._genConfig.useJit) {
|
||||
if (IS_DART || !this._compilerConfig.useJit) {
|
||||
factory = interpretStatements(statements, compileResult.viewFactoryVar);
|
||||
} else {
|
||||
factory = jitStatements(
|
||||
@ -318,7 +300,7 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
result: CompiledStylesheet,
|
||||
externalStylesheetsByModuleUrl: Map<string, CompiledStylesheet>): string[] {
|
||||
this._resolveStylesCompileResult(result, externalStylesheetsByModuleUrl);
|
||||
if (IS_DART || !this._genConfig.useJit) {
|
||||
if (IS_DART || !this._compilerConfig.useJit) {
|
||||
return interpretStatements(result.statements, result.stylesVar);
|
||||
} else {
|
||||
return jitStatements(`${result.meta.moduleUrl}.css.js`, result.statements, result.stylesVar);
|
||||
@ -334,13 +316,28 @@ class CompiledTemplate {
|
||||
private _normalizedCompMeta: CompileDirectiveMetadata = null;
|
||||
isCompiled = false;
|
||||
isCompiledWithDeps = false;
|
||||
viewComponentTypes: Type[] = [];
|
||||
viewDirectives: CompileDirectiveMetadata[] = [];
|
||||
|
||||
constructor(
|
||||
public isHost: boolean, selector: string, public compType: CompileIdentifierMetadata,
|
||||
public viewDirectives: CompileDirectiveMetadata[], public viewComponentTypes: Type[],
|
||||
public precompileHostComponentTypes: Type[], public viewPipes: CompilePipeMetadata[],
|
||||
viewDirectivesAndComponents: CompileDirectiveMetadata[],
|
||||
public viewPipes: CompilePipeMetadata[],
|
||||
_normalizeResult: SyncAsyncResult<CompileDirectiveMetadata>) {
|
||||
this.proxyViewFactory = (...args: any[]) => this._viewFactory.apply(null, args);
|
||||
viewDirectivesAndComponents.forEach((dirMeta) => {
|
||||
if (dirMeta.isComponent) {
|
||||
this.viewComponentTypes.push(dirMeta.type.runtime);
|
||||
} else {
|
||||
this.viewDirectives.push(dirMeta);
|
||||
}
|
||||
});
|
||||
this.proxyViewFactory = (...args: any[]) => {
|
||||
if (!this._viewFactory) {
|
||||
throw new BaseException(
|
||||
`Illegal state: CompiledTemplate for ${stringify(this.compType)} is not compiled yet!`);
|
||||
}
|
||||
return this._viewFactory.apply(null, args);
|
||||
};
|
||||
this.proxyComponentFactory = isHost ?
|
||||
new ComponentFactory<any>(selector, this.proxyViewFactory, compType.runtime) :
|
||||
null;
|
||||
@ -376,13 +373,15 @@ function assertComponent(meta: CompileDirectiveMetadata) {
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper around `Compiler` and `ComponentResolver` that
|
||||
* provides default patform directives / pipes.
|
||||
* Implements `Compiler` and `ComponentResolver` by delegating
|
||||
* to the RuntimeCompiler using a known module.
|
||||
*/
|
||||
class BoundCompiler implements Compiler, ComponentResolver {
|
||||
class ModuleBoundCompiler implements Compiler, ComponentResolver {
|
||||
private _warnOnComponentResolver = true;
|
||||
|
||||
constructor(
|
||||
private _delegate: RuntimeCompiler, private _directives: any[], private _pipes: any[],
|
||||
private _parentComponentResolver: ComponentResolver) {}
|
||||
private _delegate: RuntimeCompiler, private _ngModule: ConcreteType<any>,
|
||||
private _parentComponentResolver: ComponentResolver, private _console: Console) {}
|
||||
|
||||
get injector(): Injector { return this._delegate.injector; }
|
||||
|
||||
@ -395,27 +394,29 @@ class BoundCompiler implements Compiler, ComponentResolver {
|
||||
new BaseException(`Cannot resolve component using '${component}'.`), null);
|
||||
}
|
||||
}
|
||||
if (this._warnOnComponentResolver) {
|
||||
this._console.warn(ComponentResolver.DynamicCompilationDeprecationMsg);
|
||||
this._warnOnComponentResolver = false;
|
||||
}
|
||||
return this.compileComponentAsync(<ConcreteType<any>>component);
|
||||
}
|
||||
|
||||
compileComponentAsync<T>(compType: ConcreteType<T>): Promise<ComponentFactory<T>> {
|
||||
return this._delegate._compileComponent(compType, false, this._directives, this._pipes)
|
||||
.asyncResult;
|
||||
compileComponentAsync<T>(compType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
|
||||
Promise<ComponentFactory<T>> {
|
||||
return this._delegate.compileComponentAsync(compType, ngModule ? ngModule : this._ngModule);
|
||||
}
|
||||
|
||||
compileComponentSync<T>(compType: ConcreteType<T>): ComponentFactory<T> {
|
||||
return this._delegate._compileComponent(compType, true, this._directives, this._pipes)
|
||||
.syncResult;
|
||||
compileComponentSync<T>(compType: ConcreteType<T>, ngModule: ConcreteType<any> = null):
|
||||
ComponentFactory<T> {
|
||||
return this._delegate.compileComponentSync(compType, ngModule ? ngModule : this._ngModule);
|
||||
}
|
||||
|
||||
compileAppModuleSync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
|
||||
AppModuleFactory<T> {
|
||||
return this._delegate.compileAppModuleSync(moduleType, metadata);
|
||||
compileModuleSync<T>(moduleType: ConcreteType<T>): NgModuleFactory<T> {
|
||||
return this._delegate.compileModuleSync(moduleType);
|
||||
}
|
||||
|
||||
compileAppModuleAsync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
|
||||
Promise<AppModuleFactory<T>> {
|
||||
return this._delegate.compileAppModuleAsync(moduleType, metadata);
|
||||
compileModuleAsync<T>(moduleType: ConcreteType<T>): Promise<NgModuleFactory<T>> {
|
||||
return this._delegate.compileModuleAsync(moduleType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -429,7 +430,7 @@ class BoundCompiler implements Compiler, ComponentResolver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache for the given component/appModule.
|
||||
* Clears the cache for the given component/ngModule.
|
||||
*/
|
||||
clearCacheFor(type: Type) { this._delegate.clearCacheFor(type); }
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import {RegExpWrapper, isPresent, StringWrapper, isBlank} from '../src/facade/la
|
||||
import {BaseException} from '../src/facade/exceptions';
|
||||
import {AST, Interpolation, ASTWithSource, TemplateBinding, RecursiveAstVisitor, BindingPipe, ParserError} from './expression_parser/ast';
|
||||
import {Parser} from './expression_parser/parser';
|
||||
import {CompileDirectiveMetadata, CompilePipeMetadata, CompileMetadataWithType, CompileTokenMetadata,} from './compile_metadata';
|
||||
import {CompileDirectiveMetadata, CompilePipeMetadata, CompileMetadataWithIdentifier, CompileTokenMetadata, CompileIdentifierMap, removeIdentifierDuplicates} from './compile_metadata';
|
||||
import {HtmlParser, HtmlParseTreeResult} from './html_parser';
|
||||
import {splitNsName, mergeNsAndName} from './html_tags';
|
||||
import {ParseSourceSpan, ParseError, ParseErrorLevel} from './parse_util';
|
||||
@ -27,7 +27,7 @@ import {HtmlAstVisitor, HtmlElementAst, HtmlAttrAst, HtmlTextAst, HtmlCommentAst
|
||||
import {splitAtColon} from './util';
|
||||
import {identifierToken, Identifiers} from './identifiers';
|
||||
import {expandNodes} from './expander';
|
||||
import {ProviderElementContext, ProviderViewContext} from './provider_parser';
|
||||
import {ProviderElementContext, ProviderViewContext} from './provider_analyzer';
|
||||
|
||||
// Group 1 = "bind-"
|
||||
// Group 2 = "var-"
|
||||
@ -118,8 +118,8 @@ export class TemplateParser {
|
||||
}
|
||||
|
||||
if (htmlAstWithErrors.rootNodes.length > 0) {
|
||||
const uniqDirectives = <CompileDirectiveMetadata[]>removeDuplicates(directives);
|
||||
const uniqPipes = <CompilePipeMetadata[]>removeDuplicates(pipes);
|
||||
const uniqDirectives = removeIdentifierDuplicates(directives);
|
||||
const uniqPipes = removeIdentifierDuplicates(pipes);
|
||||
const providerViewContext =
|
||||
new ProviderViewContext(component, htmlAstWithErrors.rootNodes[0].sourceSpan);
|
||||
const parseVisitor = new TemplateParseVisitor(
|
||||
@ -181,7 +181,6 @@ class TemplateParseVisitor implements HtmlAstVisitor {
|
||||
|
||||
const tempMeta = providerViewContext.component.template;
|
||||
|
||||
// TODO
|
||||
if (isPresent(tempMeta) && isPresent(tempMeta.interpolation)) {
|
||||
this._interpolationConfig = {
|
||||
start: tempMeta.interpolation[0],
|
||||
@ -1015,18 +1014,3 @@ export class PipeCollector extends RecursiveAstVisitor {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function removeDuplicates(items: CompileMetadataWithType[]): CompileMetadataWithType[] {
|
||||
let res: CompileMetadataWithType[] = [];
|
||||
items.forEach(item => {
|
||||
let hasMatch =
|
||||
res.filter(
|
||||
r => r.type.name == item.type.name && r.type.moduleUrl == item.type.moduleUrl &&
|
||||
r.type.runtime == item.type.runtime)
|
||||
.length > 0;
|
||||
if (!hasMatch) {
|
||||
res.push(item);
|
||||
}
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import {ProviderAst, ProviderAstType, ReferenceAst, TemplateAst} from '../templa
|
||||
import {CompileView} from './compile_view';
|
||||
import {InjectMethodVars} from './constants';
|
||||
|
||||
import {CompileTokenMap, CompileDirectiveMetadata, CompileTokenMetadata, CompileQueryMetadata, CompileProviderMetadata, CompileDiDependencyMetadata, CompileIdentifierMetadata,} from '../compile_metadata';
|
||||
import {CompileIdentifierMap, CompileDirectiveMetadata, CompileTokenMetadata, CompileQueryMetadata, CompileProviderMetadata, CompileDiDependencyMetadata, CompileIdentifierMetadata,} from '../compile_metadata';
|
||||
import {getPropertyInView, injectFromViewParentInjector} from './util';
|
||||
import {CompileQuery, createQueryList, addQueryToTokenMap} from './compile_query';
|
||||
import {CompileMethod} from './compile_method';
|
||||
@ -43,11 +43,11 @@ export class CompileElement extends CompileNode {
|
||||
public appElement: o.ReadPropExpr;
|
||||
public elementRef: o.Expression;
|
||||
public injector: o.Expression;
|
||||
private _instances = new CompileTokenMap<o.Expression>();
|
||||
private _resolvedProviders: CompileTokenMap<ProviderAst>;
|
||||
private _instances = new CompileIdentifierMap<CompileTokenMetadata, o.Expression>();
|
||||
private _resolvedProviders: CompileIdentifierMap<CompileTokenMetadata, ProviderAst>;
|
||||
|
||||
private _queryCount = 0;
|
||||
private _queries = new CompileTokenMap<CompileQuery[]>();
|
||||
private _queries = new CompileIdentifierMap<CompileTokenMetadata, CompileQuery[]>();
|
||||
private _componentConstructorViewQueryLists: o.Expression[] = [];
|
||||
|
||||
public contentNodesByNgContentIndex: Array<o.Expression>[] = null;
|
||||
@ -144,7 +144,7 @@ export class CompileElement extends CompileNode {
|
||||
identifierToken(Identifiers.ViewContainerRef), this.appElement.prop('vcRef'));
|
||||
}
|
||||
|
||||
this._resolvedProviders = new CompileTokenMap<ProviderAst>();
|
||||
this._resolvedProviders = new CompileIdentifierMap<CompileTokenMetadata, ProviderAst>();
|
||||
this._resolvedProvidersArray.forEach(
|
||||
provider => this._resolvedProviders.add(provider.token, provider));
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {CompileQueryMetadata, CompileTokenMap} from '../compile_metadata';
|
||||
import {CompileIdentifierMap, CompileQueryMetadata, CompileTokenMetadata} from '../compile_metadata';
|
||||
import {ListWrapper} from '../facade/collection';
|
||||
import {isBlank, isPresent} from '../facade/lang';
|
||||
import {Identifiers} from '../identifiers';
|
||||
@ -125,7 +125,8 @@ export function createQueryList(
|
||||
return expr;
|
||||
}
|
||||
|
||||
export function addQueryToTokenMap(map: CompileTokenMap<CompileQuery[]>, query: CompileQuery) {
|
||||
export function addQueryToTokenMap(
|
||||
map: CompileIdentifierMap<CompileTokenMetadata, CompileQuery[]>, query: CompileQuery) {
|
||||
query.meta.selectors.forEach((selector) => {
|
||||
var entry = map.get(selector);
|
||||
if (isBlank(entry)) {
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import {ViewType} from '../../core_private';
|
||||
import {CompiledAnimation} from '../animation/animation_compiler';
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeMetadata, CompileTokenMap} from '../compile_metadata';
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMap, CompileIdentifierMetadata, CompilePipeMetadata, CompileTokenMetadata} from '../compile_metadata';
|
||||
import {CompilerConfig} from '../config';
|
||||
import {ListWrapper} from '../facade/collection';
|
||||
import {isBlank, isPresent} from '../facade/lang';
|
||||
@ -27,7 +27,7 @@ import {createPureProxy, getPropertyInView, getViewFactoryName, injectFromViewPa
|
||||
|
||||
export class CompileView implements NameResolver {
|
||||
public viewType: ViewType;
|
||||
public viewQueries: CompileTokenMap<CompileQuery[]>;
|
||||
public viewQueries: CompileIdentifierMap<CompileTokenMetadata, CompileQuery[]>;
|
||||
|
||||
public nodes: CompileNode[] = [];
|
||||
// root nodes or AppElements for ViewContainers
|
||||
@ -98,7 +98,7 @@ export class CompileView implements NameResolver {
|
||||
this.componentContext =
|
||||
getPropertyInView(o.THIS_EXPR.prop('context'), this, this.componentView);
|
||||
|
||||
var viewQueries = new CompileTokenMap<CompileQuery[]>();
|
||||
var viewQueries = new CompileIdentifierMap<CompileTokenMetadata, CompileQuery[]>();
|
||||
if (this.viewType === ViewType.COMPONENT) {
|
||||
var directiveInstance = o.THIS_EXPR.prop('context');
|
||||
ListWrapper.forEachWithIndex(this.component.viewQueries, (queryMeta, queryIndex) => {
|
||||
|
@ -22,7 +22,7 @@ function _isComponentMetadata(obj: any): obj is ComponentMetadata {
|
||||
export class ViewResolver {
|
||||
constructor(private _reflector: ReflectorReader = reflector) {}
|
||||
|
||||
resolve(component: Type): ViewMetadata {
|
||||
resolve(component: Type, throwIfNotFound = true): ViewMetadata {
|
||||
const compMeta: ComponentMetadata =
|
||||
this._reflector.annotations(component).find(_isComponentMetadata);
|
||||
|
||||
@ -45,8 +45,11 @@ export class ViewResolver {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
throw new BaseException(
|
||||
`Could not compile '${stringify(component)}' because it is not a component.`);
|
||||
if (throwIfNotFound) {
|
||||
throw new BaseException(
|
||||
`Could not compile '${stringify(component)}' because it is not a component.`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user