@ -11,7 +11,7 @@
|
||||
* @description
|
||||
* Starting point to import all compiler APIs.
|
||||
*/
|
||||
export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompileMetadataWithType, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, NormalizedComponentWithViewDirectives, OfflineCompiler, PipeResolver, RenderTypes, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, ViewResolver, XHR, createOfflineCompileUrlResolver} from './src/compiler';
|
||||
export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompileMetadataWithType, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, OfflineCompiler, PipeResolver, RenderTypes, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, ViewResolver, XHR, createOfflineCompileUrlResolver} from './src/compiler';
|
||||
export {ElementSchemaRegistry} from './src/schema/element_schema_registry';
|
||||
|
||||
export * from './src/template_ast';
|
||||
|
@ -29,6 +29,7 @@ export var CodegenComponentFactoryResolver: typeof t.CodegenComponentFactoryReso
|
||||
export var AppView: typeof t.AppView = r.AppView;
|
||||
export type DebugAppView<T> = t.DebugAppView<T>;
|
||||
export var DebugAppView: typeof t.DebugAppView = r.DebugAppView;
|
||||
export var AppModuleInjector: typeof t.AppModuleInjector = r.AppModuleInjector;
|
||||
export type ViewType = t.ViewType;
|
||||
export var ViewType: typeof t.ViewType = r.ViewType;
|
||||
export var MAX_INTERPOLATION_VALUES: typeof t.MAX_INTERPOLATION_VALUES = r.MAX_INTERPOLATION_VALUES;
|
||||
|
@ -6,6 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import * as app_module_compiler from './src/app_module_compiler';
|
||||
import * as directive_normalizer from './src/directive_normalizer';
|
||||
import * as lexer from './src/expression_parser/lexer';
|
||||
import * as parser from './src/expression_parser/parser';
|
||||
@ -98,6 +99,9 @@ export var StyleCompiler = style_compiler.StyleCompiler;
|
||||
export type ViewCompiler = view_compiler.ViewCompiler;
|
||||
export var ViewCompiler = view_compiler.ViewCompiler;
|
||||
|
||||
export type AppModuleCompiler = app_module_compiler.AppModuleCompiler;
|
||||
export var AppModuleCompiler = app_module_compiler.AppModuleCompiler;
|
||||
|
||||
export type TypeScriptEmitter = ts_emitter.TypeScriptEmitter;
|
||||
export var TypeScriptEmitter = ts_emitter.TypeScriptEmitter;
|
||||
}
|
||||
|
215
modules/@angular/compiler/src/app_module_compiler.ts
Normal file
215
modules/@angular/compiler/src/app_module_compiler.ts
Normal file
@ -0,0 +1,215 @@
|
||||
/**
|
||||
* @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} from '@angular/core';
|
||||
|
||||
import {CompileAppModuleMetadata, CompileDiDependencyMetadata, CompileIdentifierMetadata, CompileProviderMetadata, CompileTokenMap, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
|
||||
import {isBlank, isPresent} from './facade/lang';
|
||||
import {Identifiers, identifierToken} from './identifiers';
|
||||
import * as o from './output/output_ast';
|
||||
import {ParseLocation, ParseSourceFile, ParseSourceSpan} from './parse_util';
|
||||
import {AppModuleProviderParser} from './provider_parser';
|
||||
import {ProviderAst, ProviderAstType} from './template_ast';
|
||||
import {createDiTokenExpression} from './util';
|
||||
|
||||
export class ComponentFactoryDependency {
|
||||
constructor(
|
||||
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
|
||||
}
|
||||
|
||||
export class AppModuleCompileResult {
|
||||
constructor(
|
||||
public statements: o.Statement[], public appModuleFactoryVar: 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}`;
|
||||
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 id = new CompileIdentifierMetadata({name: precompileComp.name});
|
||||
deps.push(new ComponentFactoryDependency(precompileComp, id));
|
||||
return id;
|
||||
});
|
||||
var builder = new _InjectorBuilder(appModuleMeta, precompileComponents, sourceSpan);
|
||||
|
||||
var providerParser = new AppModuleProviderParser(appModuleMeta, 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)
|
||||
.instantiate(
|
||||
[o.variable(injectorClass.name), o.importExpr(appModuleMeta.type)],
|
||||
o.importType(
|
||||
Identifiers.AppModuleFactory, [o.importType(appModuleMeta.type)],
|
||||
[o.TypeModifier.Const])))
|
||||
.toDeclStmt(null, [o.StmtModifier.Final]);
|
||||
|
||||
return new AppModuleCompileResult(
|
||||
[injectorClass, appModuleFactoryStmt], appModuleFactoryVar, deps);
|
||||
}
|
||||
}
|
||||
|
||||
class _InjectorBuilder {
|
||||
private _instances = new CompileTokenMap<o.Expression>();
|
||||
private _fields: o.ClassField[] = [];
|
||||
private _createStmts: o.Statement[] = [];
|
||||
private _getters: o.ClassGetter[] = [];
|
||||
|
||||
constructor(
|
||||
private _appModuleMeta: CompileAppModuleMetadata,
|
||||
private _precompileComponents: CompileIdentifierMetadata[],
|
||||
private _sourceSpan: ParseSourceSpan) {}
|
||||
|
||||
addProvider(resolvedProvider: ProviderAst) {
|
||||
var providerValueExpressions =
|
||||
resolvedProvider.providers.map((provider) => this._getProviderValue(provider));
|
||||
var propName = `_${resolvedProvider.token.name}_${this._instances.size}`;
|
||||
var instance = this._createProviderProperty(
|
||||
propName, resolvedProvider, providerValueExpressions, resolvedProvider.multiProvider,
|
||||
resolvedProvider.eager);
|
||||
this._instances.add(resolvedProvider.token, instance);
|
||||
}
|
||||
|
||||
build(): o.ClassStmt {
|
||||
let getMethodStmts: o.Statement[] = this._instances.keys().map((token) => {
|
||||
var providerExpr = this._instances.get(token);
|
||||
return new o.IfStmt(
|
||||
InjectMethodVars.token.identical(createDiTokenExpression(token)),
|
||||
[new o.ReturnStatement(providerExpr)]);
|
||||
});
|
||||
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.ClassMethod(
|
||||
'getInternal',
|
||||
[
|
||||
new o.FnParam(InjectMethodVars.token.name, o.DYNAMIC_TYPE),
|
||||
new o.FnParam(InjectMethodVars.notFoundResult.name, o.DYNAMIC_TYPE)
|
||||
],
|
||||
getMethodStmts.concat([new o.ReturnStatement(InjectMethodVars.notFoundResult)]),
|
||||
o.DYNAMIC_TYPE)
|
||||
];
|
||||
|
||||
var ctor = new o.ClassMethod(
|
||||
null, [new o.FnParam(InjectorProps.parent.name, o.importType(Identifiers.Injector))],
|
||||
[o.SUPER_EXPR
|
||||
.callFn([
|
||||
o.variable(InjectorProps.parent.name),
|
||||
o.literalArr(this._precompileComponents.map(
|
||||
(precompiledComponent) => o.importExpr(precompiledComponent)))
|
||||
])
|
||||
.toStmt()]);
|
||||
|
||||
var injClassName = `${this._appModuleMeta.type.name}Injector`;
|
||||
return new o.ClassStmt(
|
||||
injClassName,
|
||||
o.importExpr(Identifiers.AppModuleInjector, [o.importType(this._appModuleMeta.type)]),
|
||||
this._fields, this._getters, ctor, methods);
|
||||
}
|
||||
|
||||
private _getProviderValue(provider: CompileProviderMetadata): o.Expression {
|
||||
var result: o.Expression;
|
||||
if (isPresent(provider.useExisting)) {
|
||||
result = this._getDependency(new CompileDiDependencyMetadata({token: provider.useExisting}));
|
||||
} else if (isPresent(provider.useFactory)) {
|
||||
var deps = isPresent(provider.deps) ? provider.deps : provider.useFactory.diDeps;
|
||||
var depsExpr = deps.map((dep) => this._getDependency(dep));
|
||||
result = o.importExpr(provider.useFactory).callFn(depsExpr);
|
||||
} else if (isPresent(provider.useClass)) {
|
||||
var deps = isPresent(provider.deps) ? provider.deps : provider.useClass.diDeps;
|
||||
var depsExpr = deps.map((dep) => this._getDependency(dep));
|
||||
result =
|
||||
o.importExpr(provider.useClass).instantiate(depsExpr, o.importType(provider.useClass));
|
||||
} else {
|
||||
result = o.literal(provider.useValue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private _createProviderProperty(
|
||||
propName: string, provider: ProviderAst, providerValueExpressions: o.Expression[],
|
||||
isMulti: boolean, isEager: boolean): o.Expression {
|
||||
var resolvedProviderValueExpr: o.Expression;
|
||||
var type: o.Type;
|
||||
if (isMulti) {
|
||||
resolvedProviderValueExpr = o.literalArr(providerValueExpressions);
|
||||
type = new o.ArrayType(o.DYNAMIC_TYPE);
|
||||
} else {
|
||||
resolvedProviderValueExpr = providerValueExpressions[0];
|
||||
type = providerValueExpressions[0].type;
|
||||
}
|
||||
if (isBlank(type)) {
|
||||
type = o.DYNAMIC_TYPE;
|
||||
}
|
||||
if (isEager) {
|
||||
this._fields.push(new o.ClassField(propName, type));
|
||||
this._createStmts.push(o.THIS_EXPR.prop(propName).set(resolvedProviderValueExpr).toStmt());
|
||||
} else {
|
||||
var internalField = `_${propName}`;
|
||||
this._fields.push(new o.ClassField(internalField, type));
|
||||
// Note: Equals is important for JS so that it also checks the undefined case!
|
||||
var getterStmts = [
|
||||
new o.IfStmt(
|
||||
o.THIS_EXPR.prop(internalField).isBlank(),
|
||||
[o.THIS_EXPR.prop(internalField).set(resolvedProviderValueExpr).toStmt()]),
|
||||
new o.ReturnStatement(o.THIS_EXPR.prop(internalField))
|
||||
];
|
||||
this._getters.push(new o.ClassGetter(propName, getterStmts, type));
|
||||
}
|
||||
return o.THIS_EXPR.prop(propName);
|
||||
}
|
||||
|
||||
private _getDependency(dep: CompileDiDependencyMetadata): o.Expression {
|
||||
var result: o.Expression = null;
|
||||
if (dep.isValue) {
|
||||
result = o.literal(dep.value);
|
||||
}
|
||||
if (!dep.isSkipSelf) {
|
||||
if (dep.token &&
|
||||
(dep.token.equalsTo(identifierToken(Identifiers.Injector)) ||
|
||||
dep.token.equalsTo(identifierToken(Identifiers.ComponentFactoryResolver)))) {
|
||||
result = o.THIS_EXPR;
|
||||
}
|
||||
if (isBlank(result)) {
|
||||
result = this._instances.get(dep.token);
|
||||
}
|
||||
}
|
||||
if (isBlank(result)) {
|
||||
var args = [createDiTokenExpression(dep.token)];
|
||||
if (dep.isOptional) {
|
||||
args.push(o.NULL_EXPR);
|
||||
}
|
||||
result = InjectorProps.parent.callMethod('get', args);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class InjectorProps {
|
||||
static parent = o.THIS_EXPR.prop('parent');
|
||||
}
|
||||
|
||||
class InjectMethodVars {
|
||||
static token = o.variable('token');
|
||||
static notFoundResult = o.variable('notFoundResult');
|
||||
}
|
@ -11,13 +11,14 @@ import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
|
||||
import {CHANGE_DETECTION_STRATEGY_VALUES, LIFECYCLE_HOOKS_VALUES, LifecycleHooks, VIEW_ENCAPSULATION_VALUES, reflector} from '../core_private';
|
||||
import {ListWrapper, StringMapWrapper} from '../src/facade/collection';
|
||||
import {BaseException, unimplemented} from '../src/facade/exceptions';
|
||||
import {NumberWrapper, RegExpWrapper, Type, isArray, isBlank, isBoolean, isNumber, isPresent, isString, normalizeBlank, normalizeBool, serializeEnum} from '../src/facade/lang';
|
||||
import {NumberWrapper, RegExpWrapper, Type, isArray, isBlank, isBoolean, isNumber, isPresent, isString, isStringMap, normalizeBlank, normalizeBool, serializeEnum} from '../src/facade/lang';
|
||||
|
||||
import {CssSelector} from './selector';
|
||||
import {getUrlScheme} from './url_resolver';
|
||||
import {sanitizeIdentifier, splitAtColon} from './util';
|
||||
|
||||
|
||||
|
||||
// group 2: "event" from "(event)"
|
||||
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
|
||||
|
||||
@ -468,12 +469,14 @@ export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
|
||||
export class CompileTokenMap<VALUE> {
|
||||
private _valueMap = new Map<any, VALUE>();
|
||||
private _values: VALUE[] = [];
|
||||
private _tokens: CompileTokenMetadata[] = [];
|
||||
|
||||
add(token: CompileTokenMetadata, value: VALUE) {
|
||||
var existing = this.get(token);
|
||||
if (isPresent(existing)) {
|
||||
throw new BaseException(`Can only add to a TokenMap! Token: ${token.name}`);
|
||||
}
|
||||
this._tokens.push(token);
|
||||
this._values.push(value);
|
||||
var rk = token.runtimeCacheKey;
|
||||
if (isPresent(rk)) {
|
||||
@ -496,6 +499,7 @@ export class CompileTokenMap<VALUE> {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
keys(): CompileTokenMetadata[] { return this._tokens; }
|
||||
values(): VALUE[] { return this._values; }
|
||||
get size(): number { return this._values.length; }
|
||||
}
|
||||
@ -966,7 +970,61 @@ export class CompilePipeMetadata implements CompileMetadataWithType {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Metadata regarding compilation of a directive.
|
||||
*/
|
||||
export class CompileAppModuleMetadata implements CompileMetadataWithType {
|
||||
type: CompileTypeMetadata;
|
||||
providers: CompileProviderMetadata[];
|
||||
directives: CompileTypeMetadata[];
|
||||
pipes: CompileTypeMetadata[];
|
||||
precompile: CompileTypeMetadata[];
|
||||
modules: CompileTypeMetadata[];
|
||||
|
||||
constructor({type, providers, directives, pipes, precompile, modules}: {
|
||||
type?: CompileTypeMetadata,
|
||||
providers?: Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
|
||||
directives?: CompileTypeMetadata[],
|
||||
pipes?: CompileTypeMetadata[],
|
||||
precompile?: CompileTypeMetadata[],
|
||||
modules?: CompileTypeMetadata[]
|
||||
} = {}) {
|
||||
this.type = type;
|
||||
this.directives = _normalizeArray(directives);
|
||||
this.pipes = _normalizeArray(pipes);
|
||||
this.providers = _normalizeArray(providers);
|
||||
this.precompile = _normalizeArray(precompile);
|
||||
this.modules = _normalizeArray(modules);
|
||||
}
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return this.type; }
|
||||
|
||||
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)
|
||||
});
|
||||
}
|
||||
|
||||
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)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var _COMPILE_METADATA_FROM_JSON = {
|
||||
'AppModule': CompileAppModuleMetadata.fromJson,
|
||||
'Directive': CompileDirectiveMetadata.fromJson,
|
||||
'Pipe': CompilePipeMetadata.fromJson,
|
||||
'Type': CompileTypeMetadata.fromJson,
|
||||
@ -1006,3 +1064,12 @@ function _objToJson(obj: any): string|{[key: string]: any} {
|
||||
function _normalizeArray(obj: any[]): any[] {
|
||||
return isPresent(obj) ? obj : [];
|
||||
}
|
||||
|
||||
export function isStaticSymbol(value: any): value is StaticSymbol {
|
||||
return isStringMap(value) && isPresent(value['name']) && isPresent(value['filePath']);
|
||||
}
|
||||
|
||||
export interface StaticSymbol {
|
||||
name: string;
|
||||
filePath: string;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ 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 {CompilerConfig} from './config';
|
||||
import {RuntimeCompiler} from './runtime_compiler';
|
||||
import {ElementSchemaRegistry} from './schema/element_schema_registry';
|
||||
@ -44,13 +45,24 @@ import {PipeResolver} from './pipe_resolver';
|
||||
*/
|
||||
export const COMPILER_PROVIDERS: Array<any|Type|{[k: string]: any}|any[]> =
|
||||
/*@ts2dart_const*/[
|
||||
Lexer, Parser, HtmlParser, TemplateParser, DirectiveNormalizer, CompileMetadataResolver,
|
||||
DEFAULT_PACKAGE_URL_PROVIDER, StyleCompiler, ViewCompiler,
|
||||
Lexer,
|
||||
Parser,
|
||||
HtmlParser,
|
||||
TemplateParser,
|
||||
DirectiveNormalizer,
|
||||
CompileMetadataResolver,
|
||||
DEFAULT_PACKAGE_URL_PROVIDER,
|
||||
StyleCompiler,
|
||||
ViewCompiler,
|
||||
AppModuleCompiler,
|
||||
/*@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
|
||||
UrlResolver,
|
||||
ViewResolver,
|
||||
DirectiveResolver,
|
||||
PipeResolver
|
||||
];
|
||||
|
@ -20,14 +20,9 @@ import {HtmlParser} from './html_parser';
|
||||
import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver';
|
||||
import {PreparsedElementType, preparseElement} from './template_preparser';
|
||||
import {UrlResolver} from './url_resolver';
|
||||
import {SyncAsyncResult} from './util';
|
||||
import {XHR} from './xhr';
|
||||
|
||||
export class NormalizeDirectiveResult {
|
||||
constructor(
|
||||
public syncResult: CompileDirectiveMetadata,
|
||||
public asyncResult: Promise<CompileDirectiveMetadata>) {}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class DirectiveNormalizer {
|
||||
private _xhrCache = new Map<string, Promise<string>>();
|
||||
@ -56,10 +51,11 @@ export class DirectiveNormalizer {
|
||||
return result;
|
||||
}
|
||||
|
||||
normalizeDirective(directive: CompileDirectiveMetadata): NormalizeDirectiveResult {
|
||||
normalizeDirective(directive: CompileDirectiveMetadata):
|
||||
SyncAsyncResult<CompileDirectiveMetadata> {
|
||||
if (!directive.isComponent) {
|
||||
// For non components there is nothing to be normalized yet.
|
||||
return new NormalizeDirectiveResult(directive, Promise.resolve(directive));
|
||||
return new SyncAsyncResult(directive, Promise.resolve(directive));
|
||||
}
|
||||
let normalizedTemplateSync: CompileTemplateMetadata = null;
|
||||
let normalizedTemplateAsync: Promise<CompileTemplateMetadata>;
|
||||
@ -74,11 +70,10 @@ export class DirectiveNormalizer {
|
||||
if (normalizedTemplateSync && normalizedTemplateSync.styleUrls.length === 0) {
|
||||
// sync case
|
||||
let normalizedDirective = _cloneDirectiveWithTemplate(directive, normalizedTemplateSync);
|
||||
return new NormalizeDirectiveResult(
|
||||
normalizedDirective, Promise.resolve(normalizedDirective));
|
||||
return new SyncAsyncResult(normalizedDirective, Promise.resolve(normalizedDirective));
|
||||
} else {
|
||||
// async case
|
||||
return new NormalizeDirectiveResult(
|
||||
return new SyncAsyncResult(
|
||||
null,
|
||||
normalizedTemplateAsync
|
||||
.then((normalizedTemplate) => this.normalizeExternalStylesheets(normalizedTemplate))
|
||||
|
@ -6,9 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactoryResolver, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
||||
import {AppModuleFactory, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
||||
|
||||
import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, SecurityContext, StaticNodeDebugInfo, TemplateRef_, 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, uninitialized} from '../core_private';
|
||||
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_, SecurityContext, StaticNodeDebugInfo, TemplateRef_, 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, uninitialized} from '../core_private';
|
||||
|
||||
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
|
||||
import {assetUrl} from './util';
|
||||
@ -108,6 +108,21 @@ export class Identifiers {
|
||||
moduleUrl: assetUrl('core', 'linker/component_factory_resolver'),
|
||||
runtime: ComponentFactoryResolver
|
||||
});
|
||||
static ComponentFactory = new CompileIdentifierMetadata({
|
||||
name: 'ComponentFactory',
|
||||
runtime: ComponentFactory,
|
||||
moduleUrl: assetUrl('core', 'linker/component_factory')
|
||||
});
|
||||
static AppModuleFactory = new CompileIdentifierMetadata({
|
||||
name: 'AppModuleFactory',
|
||||
runtime: AppModuleFactory,
|
||||
moduleUrl: assetUrl('core', 'linker/app_module_factory')
|
||||
});
|
||||
static AppModuleInjector = new CompileIdentifierMetadata({
|
||||
name: 'AppModuleInjector',
|
||||
runtime: AppModuleInjector,
|
||||
moduleUrl: assetUrl('core', 'linker/app_module_factory')
|
||||
});
|
||||
static ValueUnwrapper = new CompileIdentifierMetadata(
|
||||
{name: 'ValueUnwrapper', moduleUrl: CD_MODULE_URL, runtime: impValueUnwrapper});
|
||||
static Injector = new CompileIdentifierMetadata(
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, AttributeMetadata, 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, AppModuleMetadata, AttributeMetadata, ComponentMetadata, HostMetadata, Inject, InjectMetadata, Injectable, 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';
|
||||
@ -27,6 +27,7 @@ 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 _anonymousTypes = new Map<Object, number>();
|
||||
private _anonymousTypeIndex = 0;
|
||||
|
||||
@ -49,14 +50,16 @@ export class CompileMetadataResolver {
|
||||
return sanitizeIdentifier(identifier);
|
||||
}
|
||||
|
||||
clearCacheFor(compType: Type) {
|
||||
this._directiveCache.delete(compType);
|
||||
this._pipeCache.delete(compType);
|
||||
clearCacheFor(type: Type) {
|
||||
this._directiveCache.delete(type);
|
||||
this._pipeCache.delete(type);
|
||||
this._appModuleCache.delete(type);
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
this._directiveCache.clear();
|
||||
this._pipeCache.clear();
|
||||
this._appModuleCache.clear();
|
||||
}
|
||||
|
||||
getAnimationEntryMetadata(entry: AnimationEntryMetadata): cpl.CompileAnimationEntryMetadata {
|
||||
@ -102,6 +105,7 @@ export class CompileMetadataResolver {
|
||||
}
|
||||
|
||||
getDirectiveMetadata(directiveType: Type): cpl.CompileDirectiveMetadata {
|
||||
directiveType = resolveForwardRef(directiveType);
|
||||
var meta = this._directiveCache.get(directiveType);
|
||||
if (isBlank(meta)) {
|
||||
var dirMeta = this._directiveResolver.resolve(directiveType);
|
||||
@ -176,6 +180,72 @@ 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;
|
||||
moduleType = resolveForwardRef(moduleType);
|
||||
var compileMeta = this._appModuleCache.get(moduleType);
|
||||
if (isBlank(compileMeta) || !useCache) {
|
||||
if (!meta) {
|
||||
meta = this._reflector.annotations(moduleType)
|
||||
.find((meta) => meta instanceof AppModuleMetadata);
|
||||
}
|
||||
if (!meta) {
|
||||
throw new BaseException(
|
||||
`Could not compile '${stringify(moduleType)}' because it is not an AppModule.`);
|
||||
}
|
||||
let providers: any[] = [];
|
||||
if (meta.providers) {
|
||||
providers.push(...this.getProvidersMetadata(meta.providers));
|
||||
}
|
||||
|
||||
let directives: cpl.CompileTypeMetadata[] = [];
|
||||
if (meta.directives) {
|
||||
directives.push(...flattenArray(meta.directives)
|
||||
.map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
|
||||
}
|
||||
|
||||
let pipes: cpl.CompileTypeMetadata[] = [];
|
||||
if (meta.pipes) {
|
||||
pipes.push(...flattenArray(meta.pipes)
|
||||
.map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
|
||||
}
|
||||
|
||||
let precompile: cpl.CompileTypeMetadata[] = [];
|
||||
if (meta.precompile) {
|
||||
precompile.push(...flattenArray(meta.precompile)
|
||||
.map(type => this.getTypeMetadata(type, staticTypeModuleUrl(type))));
|
||||
}
|
||||
let modules: 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);
|
||||
});
|
||||
}
|
||||
|
||||
compileMeta = new cpl.CompileAppModuleMetadata({
|
||||
type: this.getTypeMetadata(moduleType, staticTypeModuleUrl(moduleType)),
|
||||
providers: providers,
|
||||
directives: directives,
|
||||
pipes: pipes,
|
||||
precompile: precompile,
|
||||
modules: modules
|
||||
});
|
||||
if (useCache) {
|
||||
this._appModuleCache.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.
|
||||
@ -193,6 +263,7 @@ export class CompileMetadataResolver {
|
||||
|
||||
getTypeMetadata(type: Type, moduleUrl: string, dependencies: any[] = null):
|
||||
cpl.CompileTypeMetadata {
|
||||
type = resolveForwardRef(type);
|
||||
return new cpl.CompileTypeMetadata({
|
||||
name: this.sanitizeTokenName(type),
|
||||
moduleUrl: moduleUrl,
|
||||
@ -203,6 +274,7 @@ export class CompileMetadataResolver {
|
||||
|
||||
getFactoryMetadata(factory: Function, moduleUrl: string, dependencies: any[] = null):
|
||||
cpl.CompileFactoryMetadata {
|
||||
factory = resolveForwardRef(factory);
|
||||
return new cpl.CompileFactoryMetadata({
|
||||
name: this.sanitizeTokenName(factory),
|
||||
moduleUrl: moduleUrl,
|
||||
@ -212,6 +284,7 @@ export class CompileMetadataResolver {
|
||||
}
|
||||
|
||||
getPipeMetadata(pipeType: Type): cpl.CompilePipeMetadata {
|
||||
pipeType = resolveForwardRef(pipeType);
|
||||
var meta = this._pipeCache.get(pipeType);
|
||||
if (isBlank(meta)) {
|
||||
var pipeMeta = this._pipeResolver.resolve(pipeType);
|
||||
@ -349,8 +422,11 @@ export class CompileMetadataResolver {
|
||||
return this.getProviderMetadata(provider);
|
||||
} else if (isProviderLiteral(provider)) {
|
||||
return this.getProviderMetadata(createProvider(provider));
|
||||
} else {
|
||||
} else if (isValidType(provider)) {
|
||||
return this.getTypeMetadata(provider, staticTypeModuleUrl(provider));
|
||||
} else {
|
||||
throw new BaseException(
|
||||
`Invalid provider - only instances of Provider and Type are allowed, got: ${stringify(provider)}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -468,21 +544,17 @@ function verifyNonBlankProviders(
|
||||
return providersTree;
|
||||
}
|
||||
|
||||
function isStaticType(value: any): boolean {
|
||||
return isStringMap(value) && isPresent(value['name']) && isPresent(value['filePath']);
|
||||
}
|
||||
|
||||
function isValidType(value: any): boolean {
|
||||
return isStaticType(value) || (value instanceof Type);
|
||||
return cpl.isStaticSymbol(value) || (value instanceof Type);
|
||||
}
|
||||
|
||||
function staticTypeModuleUrl(value: any): string {
|
||||
return isStaticType(value) ? value['filePath'] : null;
|
||||
return cpl.isStaticSymbol(value) ? value.filePath : null;
|
||||
}
|
||||
|
||||
function componentModuleUrl(
|
||||
reflector: ReflectorReader, type: any, cmpMetadata: ComponentMetadata): string {
|
||||
if (isStaticType(type)) {
|
||||
if (cpl.isStaticSymbol(type)) {
|
||||
return staticTypeModuleUrl(type);
|
||||
}
|
||||
|
||||
@ -503,9 +575,8 @@ function convertToCompileValue(value: any): any {
|
||||
|
||||
class _CompileValueConverter extends ValueTransformer {
|
||||
visitOther(value: any, context: any): any {
|
||||
if (isStaticType(value)) {
|
||||
return new cpl.CompileIdentifierMetadata(
|
||||
{name: value['name'], moduleUrl: staticTypeModuleUrl(value)});
|
||||
if (cpl.isStaticSymbol(value)) {
|
||||
return new cpl.CompileIdentifierMetadata({name: value.name, moduleUrl: value.filePath});
|
||||
} else {
|
||||
return new cpl.CompileIdentifierMetadata({runtime: value});
|
||||
}
|
||||
|
@ -6,12 +6,15 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ComponentFactory} from '@angular/core';
|
||||
import {AppModuleMetadata, ComponentMetadata} from '@angular/core';
|
||||
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeMetadata, createHostComponentMeta} from './compile_metadata';
|
||||
import {AppModuleCompiler} from './app_module_compiler';
|
||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, 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 {OutputEmitter} from './output/abstract_emitter';
|
||||
import * as o from './output/output_ast';
|
||||
import {CompiledStylesheet, StyleCompiler} from './style_compiler';
|
||||
@ -20,79 +23,164 @@ import {assetUrl} from './util';
|
||||
import {ComponentFactoryDependency, ViewCompileResult, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
|
||||
import {XHR} from './xhr';
|
||||
|
||||
var _COMPONENT_FACTORY_IDENTIFIER = new CompileIdentifierMetadata({
|
||||
name: 'ComponentFactory',
|
||||
runtime: ComponentFactory,
|
||||
moduleUrl: assetUrl('core', 'linker/component_factory')
|
||||
});
|
||||
|
||||
export class SourceModule {
|
||||
constructor(public moduleUrl: string, public source: string) {}
|
||||
}
|
||||
|
||||
export class StyleSheetSourceWithImports {
|
||||
constructor(public source: SourceModule, public importedUrls: string[]) {}
|
||||
}
|
||||
export class AppModulesSummary {
|
||||
private _compAppModule = new Map<string, StaticSymbol>();
|
||||
private _hashKey(type: StaticSymbol) { return `${type.filePath}#${type.name}`; }
|
||||
|
||||
export class NormalizedComponentWithViewDirectives {
|
||||
constructor(
|
||||
public component: CompileDirectiveMetadata, public directives: CompileDirectiveMetadata[],
|
||||
public pipes: CompilePipeMetadata[]) {}
|
||||
}
|
||||
|
||||
export class OfflineCompiler {
|
||||
constructor(
|
||||
private _directiveNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
|
||||
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
|
||||
private _outputEmitter: OutputEmitter) {}
|
||||
|
||||
normalizeDirectiveMetadata(directive: CompileDirectiveMetadata):
|
||||
Promise<CompileDirectiveMetadata> {
|
||||
return this._directiveNormalizer.normalizeDirective(directive).asyncResult;
|
||||
hasComponent(component: StaticSymbol): boolean {
|
||||
return this._compAppModule.has(this._hashKey(component));
|
||||
}
|
||||
|
||||
compileTemplates(components: NormalizedComponentWithViewDirectives[]): SourceModule[] {
|
||||
if (components.length === 0) {
|
||||
throw new BaseException('No components given');
|
||||
}
|
||||
var statements: o.DeclareVarStmt[] = [];
|
||||
var exportedVars: string[] = [];
|
||||
var moduleUrl = _ngfactoryModuleUrl(components[0].component.type);
|
||||
var outputSourceModules: SourceModule[] = [];
|
||||
components.forEach(componentWithDirs => {
|
||||
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
|
||||
_assertComponent(compMeta);
|
||||
var fileSuffix = _splitLastSuffix(compMeta.type.moduleUrl)[1];
|
||||
var stylesCompileResults = this._styleCompiler.compileComponent(compMeta);
|
||||
stylesCompileResults.externalStylesheets.forEach((compiledStyleSheet) => {
|
||||
outputSourceModules.push(this._codgenStyles(compiledStyleSheet, fileSuffix));
|
||||
});
|
||||
addComponent(module: StaticSymbol, component: StaticSymbol) {
|
||||
this._compAppModule.set(this._hashKey(component), module);
|
||||
}
|
||||
|
||||
var compViewFactoryVar = this._compileComponent(
|
||||
compMeta, componentWithDirs.directives, componentWithDirs.pipes,
|
||||
stylesCompileResults.componentStylesheet, fileSuffix, statements);
|
||||
exportedVars.push(compViewFactoryVar);
|
||||
getModule(comp: StaticSymbol): StaticSymbol {
|
||||
return this._compAppModule.get(this._hashKey(comp));
|
||||
}
|
||||
}
|
||||
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) {}
|
||||
|
||||
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||
var hostViewFactoryVar =
|
||||
this._compileComponent(hostMeta, [compMeta], [], null, fileSuffix, statements);
|
||||
var compFactoryVar = _componentFactoryName(compMeta.type);
|
||||
statements.push(
|
||||
o.variable(compFactoryVar)
|
||||
.set(o.importExpr(_COMPONENT_FACTORY_IDENTIFIER, [o.importType(compMeta.type)])
|
||||
.instantiate(
|
||||
[
|
||||
o.literal(compMeta.selector), o.variable(hostViewFactoryVar),
|
||||
o.importExpr(compMeta.type)
|
||||
],
|
||||
o.importType(
|
||||
_COMPONENT_FACTORY_IDENTIFIER, [o.importType(compMeta.type)],
|
||||
[o.TypeModifier.Const])))
|
||||
.toDeclStmt(null, [o.StmtModifier.Final]));
|
||||
exportedVars.push(compFactoryVar);
|
||||
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));
|
||||
});
|
||||
outputSourceModules.unshift(this._codegenSourceModule(moduleUrl, statements, exportedVars));
|
||||
return outputSourceModules;
|
||||
return result;
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
compMeta.precompile.forEach((precompileComp) => {
|
||||
this._getTransitiveComponents(appModule, <any>precompileComp.type.runtime);
|
||||
});
|
||||
return target;
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
this._directiveNormalizer.clearCache();
|
||||
this._metadataResolver.clearCache();
|
||||
}
|
||||
|
||||
compile(
|
||||
moduleUrl: string, appModulesSummary: AppModulesSummary, components: StaticSymbol[],
|
||||
appModules: StaticSymbol[]): Promise<SourceModule[]> {
|
||||
let fileSuffix = _splitLastSuffix(moduleUrl)[1];
|
||||
let statements: o.Statement[] = [];
|
||||
let exportedVars: string[] = [];
|
||||
let outputSourceModules: SourceModule[] = [];
|
||||
|
||||
// compile app modules
|
||||
exportedVars.push(
|
||||
...appModules.map((appModule) => this._compileAppModule(appModule, 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)));
|
||||
}
|
||||
return Promise
|
||||
.all([
|
||||
this._metadataResolver.getDirectiveMetadata(<any>compType), ...appModuleDirectives,
|
||||
...this._metadataResolver.getViewDirectivesMetadata(<any>compType)
|
||||
].map(dirMeta => this._directiveNormalizer.normalizeDirective(dirMeta).asyncResult))
|
||||
.then((normalizedCompWithDirectives) => {
|
||||
let compMeta = normalizedCompWithDirectives[0];
|
||||
let dirMetas = normalizedCompWithDirectives.slice(1);
|
||||
_assertComponent(compMeta);
|
||||
|
||||
// compile styles
|
||||
let 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));
|
||||
});
|
||||
}))
|
||||
.then(() => {
|
||||
if (statements.length > 0) {
|
||||
outputSourceModules.unshift(this._codegenSourceModule(
|
||||
_ngfactoryModuleUrl(moduleUrl), statements, exportedVars));
|
||||
}
|
||||
return outputSourceModules;
|
||||
});
|
||||
}
|
||||
|
||||
private _compileAppModule(appModuleType: StaticSymbol, targetStatements: o.Statement[]): string {
|
||||
let appModuleMeta = this._metadataResolver.getAppModuleMetadata(appModuleType);
|
||||
let appCompileResult = this._appModuleCompiler.compile(appModuleMeta);
|
||||
appCompileResult.dependencies.forEach((dep) => {
|
||||
dep.placeholder.name = _componentFactoryName(dep.comp);
|
||||
dep.placeholder.moduleUrl = _ngfactoryModuleUrl(dep.comp.moduleUrl);
|
||||
});
|
||||
targetStatements.push(...appCompileResult.statements);
|
||||
return appCompileResult.appModuleFactoryVar;
|
||||
}
|
||||
|
||||
private _compileComponentFactory(
|
||||
compMeta: CompileDirectiveMetadata, fileSuffix: string,
|
||||
targetStatements: o.Statement[]): string {
|
||||
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
|
||||
var hostViewFactoryVar =
|
||||
this._compileComponent(hostMeta, [compMeta], [], null, fileSuffix, targetStatements);
|
||||
var compFactoryVar = _componentFactoryName(compMeta.type);
|
||||
targetStatements.push(
|
||||
o.variable(compFactoryVar)
|
||||
.set(o.importExpr(Identifiers.ComponentFactory, [o.importType(compMeta.type)])
|
||||
.instantiate(
|
||||
[
|
||||
o.literal(compMeta.selector), o.variable(hostViewFactoryVar),
|
||||
o.importExpr(compMeta.type)
|
||||
],
|
||||
o.importType(
|
||||
Identifiers.ComponentFactory, [o.importType(compMeta.type)],
|
||||
[o.TypeModifier.Const])))
|
||||
.toDeclStmt(null, [o.StmtModifier.Final]));
|
||||
return compFactoryVar;
|
||||
}
|
||||
|
||||
private _compileComponent(
|
||||
@ -130,11 +218,11 @@ function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[]
|
||||
compileResult.dependencies.forEach((dep) => {
|
||||
if (dep instanceof ViewFactoryDependency) {
|
||||
let vfd = <ViewFactoryDependency>dep;
|
||||
vfd.placeholder.moduleUrl = _ngfactoryModuleUrl(vfd.comp);
|
||||
vfd.placeholder.moduleUrl = _ngfactoryModuleUrl(vfd.comp.moduleUrl);
|
||||
} else if (dep instanceof ComponentFactoryDependency) {
|
||||
let cfd = <ComponentFactoryDependency>dep;
|
||||
cfd.placeholder.name = _componentFactoryName(cfd.comp);
|
||||
cfd.placeholder.moduleUrl = _ngfactoryModuleUrl(cfd.comp);
|
||||
cfd.placeholder.moduleUrl = _ngfactoryModuleUrl(cfd.comp.moduleUrl);
|
||||
}
|
||||
});
|
||||
return compileResult.statements;
|
||||
@ -149,8 +237,8 @@ function _resolveStyleStatements(
|
||||
return compileResult.statements;
|
||||
}
|
||||
|
||||
function _ngfactoryModuleUrl(comp: CompileIdentifierMetadata): string {
|
||||
var urlWithSuffix = _splitLastSuffix(comp.moduleUrl);
|
||||
function _ngfactoryModuleUrl(compUrl: string): string {
|
||||
var urlWithSuffix = _splitLastSuffix(compUrl);
|
||||
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
|
||||
}
|
||||
|
||||
|
@ -1,86 +0,0 @@
|
||||
/**
|
||||
* @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 {AppElement, AppView, DebugAppView} from '../../core_private';
|
||||
import {BaseException} from '../facade/exceptions';
|
||||
import {isPresent} from '../facade/lang';
|
||||
|
||||
import {DynamicInstance, InstanceFactory} from './output_interpreter';
|
||||
|
||||
export class InterpretiveAppViewInstanceFactory implements InstanceFactory {
|
||||
createInstance(
|
||||
superClass: any, clazz: any, args: any[], props: Map<string, any>,
|
||||
getters: Map<string, Function>, methods: Map<string, Function>): any {
|
||||
if (superClass === AppView) {
|
||||
// We are always using DebugAppView as parent.
|
||||
// However, in prod mode we generate a constructor call that does
|
||||
// not have the argument for the debugNodeInfos.
|
||||
args = args.concat([null]);
|
||||
return new _InterpretiveAppView(args, props, getters, methods);
|
||||
} else if (superClass === DebugAppView) {
|
||||
return new _InterpretiveAppView(args, props, getters, methods);
|
||||
}
|
||||
throw new BaseException(`Can't instantiate class ${superClass} in interpretative mode`);
|
||||
}
|
||||
}
|
||||
|
||||
class _InterpretiveAppView extends DebugAppView<any> implements DynamicInstance {
|
||||
constructor(
|
||||
args: any[], public props: Map<string, any>, public getters: Map<string, Function>,
|
||||
public methods: Map<string, Function>) {
|
||||
super(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
|
||||
}
|
||||
createInternal(rootSelector: string|any): AppElement {
|
||||
var m = this.methods.get('createInternal');
|
||||
if (isPresent(m)) {
|
||||
return m(rootSelector);
|
||||
} else {
|
||||
return super.createInternal(rootSelector);
|
||||
}
|
||||
}
|
||||
injectorGetInternal(token: any, nodeIndex: number, notFoundResult: any): any {
|
||||
var m = this.methods.get('injectorGetInternal');
|
||||
if (isPresent(m)) {
|
||||
return m(token, nodeIndex, notFoundResult);
|
||||
} else {
|
||||
return super.injectorGet(token, nodeIndex, notFoundResult);
|
||||
}
|
||||
}
|
||||
detachInternal(): void {
|
||||
var m = this.methods.get('detachInternal');
|
||||
if (isPresent(m)) {
|
||||
return m();
|
||||
} else {
|
||||
return super.detachInternal();
|
||||
}
|
||||
}
|
||||
destroyInternal(): void {
|
||||
var m = this.methods.get('destroyInternal');
|
||||
if (isPresent(m)) {
|
||||
return m();
|
||||
} else {
|
||||
return super.destroyInternal();
|
||||
}
|
||||
}
|
||||
dirtyParentQueriesInternal(): void {
|
||||
var m = this.methods.get('dirtyParentQueriesInternal');
|
||||
if (isPresent(m)) {
|
||||
return m();
|
||||
} else {
|
||||
return super.dirtyParentQueriesInternal();
|
||||
}
|
||||
}
|
||||
detectChangesInternal(throwOnChange: boolean): void {
|
||||
var m = this.methods.get('detectChangesInternal');
|
||||
if (isPresent(m)) {
|
||||
return m(throwOnChange);
|
||||
} else {
|
||||
return super.detectChangesInternal(throwOnChange);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,11 @@
|
||||
*/
|
||||
|
||||
import {CompileIdentifierMetadata} from '../compile_metadata';
|
||||
import {StringMapWrapper} from '../facade/collection';
|
||||
import {BaseException} from '../facade/exceptions';
|
||||
import {isBlank, isPresent, isString} from '../facade/lang';
|
||||
import {ValueTransformer, visitValue} from '../util';
|
||||
|
||||
|
||||
|
||||
//// Types
|
||||
@ -875,10 +879,6 @@ export function importType(
|
||||
return isPresent(id) ? new ExternalType(id, typeParams, typeModifiers) : null;
|
||||
}
|
||||
|
||||
export function literal(value: any, type: Type = null): LiteralExpr {
|
||||
return new LiteralExpr(value, type);
|
||||
}
|
||||
|
||||
export function literalArr(values: Expression[], type: Type = null): LiteralArrayExpr {
|
||||
return new LiteralArrayExpr(values, type);
|
||||
}
|
||||
@ -895,3 +895,30 @@ export function not(expr: Expression): NotExpr {
|
||||
export function fn(params: FnParam[], body: Statement[], type: Type = null): FunctionExpr {
|
||||
return new FunctionExpr(params, body, type);
|
||||
}
|
||||
|
||||
export function literal(value: any, type: Type = null): Expression {
|
||||
return visitValue(value, new _ValueOutputAstTransformer(), type);
|
||||
}
|
||||
|
||||
class _ValueOutputAstTransformer implements ValueTransformer {
|
||||
visitArray(arr: any[], type: Type): Expression {
|
||||
return literalArr(arr.map(value => visitValue(value, this, null)), type);
|
||||
}
|
||||
visitStringMap(map: {[key: string]: any}, type: MapType): Expression {
|
||||
var entries: Array<string|Expression>[] = [];
|
||||
StringMapWrapper.forEach(map, (value: any, key: string) => {
|
||||
entries.push([key, visitValue(value, this, null)]);
|
||||
});
|
||||
return literalMap(entries, type);
|
||||
}
|
||||
visitPrimitive(value: any, type: Type): Expression { return new LiteralExpr(value, type); }
|
||||
visitOther(value: any, type: Type): Expression {
|
||||
if (value instanceof CompileIdentifierMetadata) {
|
||||
return importExpr(value);
|
||||
} else if (value instanceof Expression) {
|
||||
return value;
|
||||
} else {
|
||||
throw new BaseException(`Illegal state: Don't now how to compile value ${value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,49 +6,23 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {reflector} from '../../core_private';
|
||||
import {ObservableWrapper} from '../facade/async';
|
||||
import {ListWrapper} from '../facade/collection';
|
||||
import {BaseException, unimplemented} from '../facade/exceptions';
|
||||
import {FunctionWrapper, IS_DART, isPresent} from '../facade/lang';
|
||||
import {IS_DART, isPresent} from '../facade/lang';
|
||||
|
||||
import {debugOutputAstAsDart} from './dart_emitter';
|
||||
import * as o from './output_ast';
|
||||
import {debugOutputAstAsTypeScript} from './ts_emitter';
|
||||
|
||||
export function interpretStatements(
|
||||
statements: o.Statement[], resultVar: string, instanceFactory: InstanceFactory): any {
|
||||
export function interpretStatements(statements: o.Statement[], resultVar: string): any {
|
||||
var stmtsWithReturn = statements.concat([new o.ReturnStatement(o.variable(resultVar))]);
|
||||
var ctx = new _ExecutionContext(
|
||||
null, null, null, null, new Map<string, any>(), new Map<string, any>(),
|
||||
new Map<string, Function>(), new Map<string, Function>(), instanceFactory);
|
||||
var ctx = new _ExecutionContext(null, null, null, new Map<string, any>());
|
||||
var visitor = new StatementInterpreter();
|
||||
var result = visitor.visitAllStatements(stmtsWithReturn, ctx);
|
||||
return isPresent(result) ? result.value : null;
|
||||
}
|
||||
|
||||
export interface InstanceFactory {
|
||||
createInstance(
|
||||
superClass: any, clazz: any, constructorArgs: any[], props: Map<string, any>,
|
||||
getters: Map<string, Function>, methods: Map<string, Function>): DynamicInstance;
|
||||
}
|
||||
|
||||
export abstract class DynamicInstance {
|
||||
get props(): Map<string, any> { return unimplemented(); }
|
||||
get getters(): Map<string, Function> { return unimplemented(); }
|
||||
get methods(): Map<string, any> { return unimplemented(); }
|
||||
get clazz(): any { return unimplemented(); }
|
||||
}
|
||||
|
||||
function isDynamicInstance(instance: any): any {
|
||||
if (IS_DART) {
|
||||
return instance instanceof DynamicInstance;
|
||||
} else {
|
||||
return isPresent(instance) && isPresent(instance.props) && isPresent(instance.getters) &&
|
||||
isPresent(instance.methods);
|
||||
}
|
||||
}
|
||||
|
||||
function _executeFunctionStatements(
|
||||
varNames: string[], varValues: any[], statements: o.Statement[], ctx: _ExecutionContext,
|
||||
visitor: StatementInterpreter): any {
|
||||
@ -62,15 +36,11 @@ function _executeFunctionStatements(
|
||||
|
||||
class _ExecutionContext {
|
||||
constructor(
|
||||
public parent: _ExecutionContext, public superClass: any, public superInstance: any,
|
||||
public className: string, public vars: Map<string, any>, public props: Map<string, any>,
|
||||
public getters: Map<string, Function>, public methods: Map<string, Function>,
|
||||
public instanceFactory: InstanceFactory) {}
|
||||
public parent: _ExecutionContext, public instance: any, public className: string,
|
||||
public vars: Map<string, any>) {}
|
||||
|
||||
createChildWihtLocalVars(): _ExecutionContext {
|
||||
return new _ExecutionContext(
|
||||
this, this.superClass, this.superInstance, this.className, new Map<string, any>(),
|
||||
this.props, this.getters, this.methods, this.instanceFactory);
|
||||
return new _ExecutionContext(this, this.instance, this.className, new Map<string, any>());
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,38 +48,44 @@ class ReturnValue {
|
||||
constructor(public value: any) {}
|
||||
}
|
||||
|
||||
class _DynamicClass {
|
||||
constructor(
|
||||
private _classStmt: o.ClassStmt, private _ctx: _ExecutionContext,
|
||||
private _visitor: StatementInterpreter) {}
|
||||
function createDynamicClass(
|
||||
_classStmt: o.ClassStmt, _ctx: _ExecutionContext, _visitor: StatementInterpreter): Function {
|
||||
let propertyDescriptors: {[key: string]: any} = {};
|
||||
|
||||
instantiate(args: any[]): DynamicInstance {
|
||||
var props = new Map<string, any>();
|
||||
var getters = new Map<string, Function>();
|
||||
var methods = new Map<string, Function>();
|
||||
var superClass = this._classStmt.parent.visitExpression(this._visitor, this._ctx);
|
||||
var instanceCtx = new _ExecutionContext(
|
||||
this._ctx, superClass, null, this._classStmt.name, this._ctx.vars, props, getters, methods,
|
||||
this._ctx.instanceFactory);
|
||||
_classStmt.getters.forEach((getter: o.ClassGetter) => {
|
||||
// Note: use `function` instead of arrow function to capture `this`
|
||||
propertyDescriptors[getter.name] = {
|
||||
configurable: false,
|
||||
get: function() {
|
||||
let instanceCtx = new _ExecutionContext(_ctx, this, _classStmt.name, _ctx.vars);
|
||||
return _executeFunctionStatements([], [], getter.body, instanceCtx, _visitor);
|
||||
}
|
||||
};
|
||||
});
|
||||
_classStmt.methods.forEach(function(method: o.ClassMethod) {
|
||||
var paramNames = method.params.map(param => param.name);
|
||||
// Note: use `function` instead of arrow function to capture `this`
|
||||
propertyDescriptors[method.name] = {
|
||||
writable: false,
|
||||
configurable: false,
|
||||
value: function(...args: any[]) {
|
||||
let instanceCtx = new _ExecutionContext(_ctx, this, _classStmt.name, _ctx.vars);
|
||||
return _executeFunctionStatements(paramNames, args, method.body, instanceCtx, _visitor);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
this._classStmt.fields.forEach((field: o.ClassField) => { props.set(field.name, null); });
|
||||
this._classStmt.getters.forEach((getter: o.ClassGetter) => {
|
||||
getters.set(
|
||||
getter.name,
|
||||
() => _executeFunctionStatements([], [], getter.body, instanceCtx, this._visitor));
|
||||
});
|
||||
this._classStmt.methods.forEach((method: o.ClassMethod) => {
|
||||
var paramNames = method.params.map(param => param.name);
|
||||
methods.set(method.name, _declareFn(paramNames, method.body, instanceCtx, this._visitor));
|
||||
});
|
||||
|
||||
var ctorParamNames = this._classStmt.constructorMethod.params.map(param => param.name);
|
||||
var ctorParamNames = _classStmt.constructorMethod.params.map(param => param.name);
|
||||
// Note: use `function` instead of arrow function to capture `this`
|
||||
var ctor = function(...args: any[]) {
|
||||
let instanceCtx = new _ExecutionContext(_ctx, this, _classStmt.name, _ctx.vars);
|
||||
_classStmt.fields.forEach((field) => { this[field.name] = undefined; });
|
||||
_executeFunctionStatements(
|
||||
ctorParamNames, args, this._classStmt.constructorMethod.body, instanceCtx, this._visitor);
|
||||
return instanceCtx.superInstance;
|
||||
}
|
||||
|
||||
debugAst(): string { return this._visitor.debugAst(this._classStmt); }
|
||||
ctorParamNames, args, _classStmt.constructorMethod.body, instanceCtx, _visitor);
|
||||
};
|
||||
var superClass = _classStmt.parent.visitExpression(_visitor, _ctx);
|
||||
ctor.prototype = Object.create(superClass.prototype, propertyDescriptors);
|
||||
return ctor;
|
||||
}
|
||||
|
||||
class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
@ -138,8 +114,9 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
if (isPresent(ast.builtin)) {
|
||||
switch (ast.builtin) {
|
||||
case o.BuiltinVar.Super:
|
||||
return ctx.instance.__proto__;
|
||||
case o.BuiltinVar.This:
|
||||
return ctx.superInstance;
|
||||
return ctx.instance;
|
||||
case o.BuiltinVar.CatchError:
|
||||
varName = CATCH_ERROR_VAR;
|
||||
break;
|
||||
@ -169,23 +146,14 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
visitWritePropExpr(expr: o.WritePropExpr, ctx: _ExecutionContext): any {
|
||||
var receiver = expr.receiver.visitExpression(this, ctx);
|
||||
var value = expr.value.visitExpression(this, ctx);
|
||||
if (isDynamicInstance(receiver)) {
|
||||
var di = <DynamicInstance>receiver;
|
||||
if (di.props.has(expr.name)) {
|
||||
di.props.set(expr.name, value);
|
||||
} else {
|
||||
reflector.setter(expr.name)(receiver, value);
|
||||
}
|
||||
} else {
|
||||
reflector.setter(expr.name)(receiver, value);
|
||||
}
|
||||
receiver[expr.name] = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
visitInvokeMethodExpr(expr: o.InvokeMethodExpr, ctx: _ExecutionContext): any {
|
||||
var receiver = expr.receiver.visitExpression(this, ctx);
|
||||
var args = this.visitAllExpressions(expr.args, ctx);
|
||||
var result: any /** TODO #9100 */;
|
||||
var result: any;
|
||||
if (isPresent(expr.builtin)) {
|
||||
switch (expr.builtin) {
|
||||
case o.BuiltinMethod.ConcatArray:
|
||||
@ -204,15 +172,8 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
default:
|
||||
throw new BaseException(`Unknown builtin method ${expr.builtin}`);
|
||||
}
|
||||
} else if (isDynamicInstance(receiver)) {
|
||||
var di = <DynamicInstance>receiver;
|
||||
if (di.methods.has(expr.name)) {
|
||||
result = FunctionWrapper.apply(di.methods.get(expr.name), args);
|
||||
} else {
|
||||
result = reflector.method(expr.name)(receiver, args);
|
||||
}
|
||||
} else {
|
||||
result = reflector.method(expr.name)(receiver, args);
|
||||
result = receiver[expr.name].apply(receiver, args);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -220,20 +181,18 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
var args = this.visitAllExpressions(stmt.args, ctx);
|
||||
var fnExpr = stmt.fn;
|
||||
if (fnExpr instanceof o.ReadVarExpr && fnExpr.builtin === o.BuiltinVar.Super) {
|
||||
ctx.superInstance = ctx.instanceFactory.createInstance(
|
||||
ctx.superClass, ctx.className, args, ctx.props, ctx.getters, ctx.methods);
|
||||
ctx.parent.superInstance = ctx.superInstance;
|
||||
ctx.instance.constructor.prototype.constructor.apply(ctx.instance, args);
|
||||
return null;
|
||||
} else {
|
||||
var fn = stmt.fn.visitExpression(this, ctx);
|
||||
return FunctionWrapper.apply(fn, args);
|
||||
return fn.apply(null, args);
|
||||
}
|
||||
}
|
||||
visitReturnStmt(stmt: o.ReturnStatement, ctx: _ExecutionContext): any {
|
||||
return new ReturnValue(stmt.value.visitExpression(this, ctx));
|
||||
}
|
||||
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: _ExecutionContext): any {
|
||||
var clazz = new _DynamicClass(stmt, ctx, this);
|
||||
var clazz = createDynamicClass(stmt, ctx, this);
|
||||
ctx.vars.set(stmt.name, clazz);
|
||||
return null;
|
||||
}
|
||||
@ -266,11 +225,7 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
visitInstantiateExpr(ast: o.InstantiateExpr, ctx: _ExecutionContext): any {
|
||||
var args = this.visitAllExpressions(ast.args, ctx);
|
||||
var clazz = ast.classExpr.visitExpression(this, ctx);
|
||||
if (clazz instanceof _DynamicClass) {
|
||||
return clazz.instantiate(args);
|
||||
} else {
|
||||
return FunctionWrapper.apply(reflector.factory(clazz), args);
|
||||
}
|
||||
return new clazz(...args);
|
||||
}
|
||||
visitLiteralExpr(ast: o.LiteralExpr, ctx: _ExecutionContext): any { return ast.value; }
|
||||
visitExternalExpr(ast: o.ExternalExpr, ctx: _ExecutionContext): any { return ast.value.runtime; }
|
||||
@ -337,22 +292,9 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
}
|
||||
}
|
||||
visitReadPropExpr(ast: o.ReadPropExpr, ctx: _ExecutionContext): any {
|
||||
var result: any /** TODO #9100 */;
|
||||
var result: any;
|
||||
var receiver = ast.receiver.visitExpression(this, ctx);
|
||||
if (isDynamicInstance(receiver)) {
|
||||
var di = <DynamicInstance>receiver;
|
||||
if (di.props.has(ast.name)) {
|
||||
result = di.props.get(ast.name);
|
||||
} else if (di.getters.has(ast.name)) {
|
||||
result = di.getters.get(ast.name)();
|
||||
} else if (di.methods.has(ast.name)) {
|
||||
result = di.methods.get(ast.name);
|
||||
} else {
|
||||
result = reflector.getter(ast.name)(receiver);
|
||||
}
|
||||
} else {
|
||||
result = reflector.getter(ast.name)(receiver);
|
||||
}
|
||||
result = receiver[ast.name];
|
||||
return result;
|
||||
}
|
||||
visitReadKeyExpr(ast: o.ReadKeyExpr, ctx: _ExecutionContext): any {
|
||||
@ -366,7 +308,7 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
visitLiteralMapExpr(ast: o.LiteralMapExpr, ctx: _ExecutionContext): any {
|
||||
var result = {};
|
||||
ast.entries.forEach(
|
||||
(entry) => (result as any /** TODO #9100 */)[<string>entry[0]] =
|
||||
(entry) => (result as any)[<string>entry[0]] =
|
||||
(<o.Expression>entry[1]).visitExpression(this, ctx));
|
||||
return result;
|
||||
}
|
||||
@ -390,61 +332,7 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
|
||||
function _declareFn(
|
||||
varNames: string[], statements: o.Statement[], ctx: _ExecutionContext,
|
||||
visitor: StatementInterpreter): Function {
|
||||
switch (varNames.length) {
|
||||
case 0:
|
||||
return () => _executeFunctionStatements(varNames, [], statements, ctx, visitor);
|
||||
case 1:
|
||||
return (d0: any /** TODO #9100 */) =>
|
||||
_executeFunctionStatements(varNames, [d0], statements, ctx, visitor);
|
||||
case 2:
|
||||
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */) =>
|
||||
_executeFunctionStatements(varNames, [d0, d1], statements, ctx, visitor);
|
||||
case 3:
|
||||
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */) =>
|
||||
_executeFunctionStatements(varNames, [d0, d1, d2], statements, ctx, visitor);
|
||||
case 4:
|
||||
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
|
||||
d3: any /** TODO #9100 */) =>
|
||||
_executeFunctionStatements(varNames, [d0, d1, d2, d3], statements, ctx, visitor);
|
||||
case 5:
|
||||
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
|
||||
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */) =>
|
||||
_executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4], statements, ctx, visitor);
|
||||
case 6:
|
||||
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
|
||||
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */) =>
|
||||
_executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4, d5], statements, ctx, visitor);
|
||||
case 7:
|
||||
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
|
||||
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */,
|
||||
d6: any /** TODO #9100 */) =>
|
||||
_executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4, d5, d6], statements, ctx, visitor);
|
||||
case 8:
|
||||
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
|
||||
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */,
|
||||
d6: any /** TODO #9100 */, d7: any /** TODO #9100 */) =>
|
||||
_executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4, d5, d6, d7], statements, ctx, visitor);
|
||||
case 9:
|
||||
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
|
||||
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */,
|
||||
d6: any /** TODO #9100 */, d7: any /** TODO #9100 */, d8: any /** TODO #9100 */) =>
|
||||
_executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4, d5, d6, d7, d8], statements, ctx, visitor);
|
||||
case 10:
|
||||
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
|
||||
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */,
|
||||
d6: any /** TODO #9100 */, d7: any /** TODO #9100 */, d8: any /** TODO #9100 */,
|
||||
d9: any /** TODO #9100 */) =>
|
||||
_executeFunctionStatements(
|
||||
varNames, [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], statements, ctx, visitor);
|
||||
default:
|
||||
throw new BaseException(
|
||||
'Declaring functions with more than 10 arguments is not supported right now');
|
||||
}
|
||||
return (...args: any[]) => _executeFunctionStatements(varNames, args, statements, ctx, visitor);
|
||||
}
|
||||
|
||||
var CATCH_ERROR_VAR = 'error';
|
||||
|
@ -5,13 +5,16 @@
|
||||
* 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 {isPresent} from './facade/lang';
|
||||
|
||||
export class ParseLocation {
|
||||
constructor(
|
||||
public file: ParseSourceFile, public offset: number, public line: number,
|
||||
public col: number) {}
|
||||
|
||||
toString(): string { return `${this.file.url}@${this.line}:${this.col}`; }
|
||||
toString(): string {
|
||||
return isPresent(this.offset) ? `${this.file.url}@${this.line}:${this.col}` : this.file.url;
|
||||
}
|
||||
}
|
||||
|
||||
export class ParseSourceFile {
|
||||
@ -39,38 +42,41 @@ export abstract class ParseError {
|
||||
toString(): string {
|
||||
var source = this.span.start.file.content;
|
||||
var ctxStart = this.span.start.offset;
|
||||
if (ctxStart > source.length - 1) {
|
||||
ctxStart = source.length - 1;
|
||||
}
|
||||
var ctxEnd = ctxStart;
|
||||
var ctxLen = 0;
|
||||
var ctxLines = 0;
|
||||
var contextStr = '';
|
||||
if (isPresent(ctxStart)) {
|
||||
if (ctxStart > source.length - 1) {
|
||||
ctxStart = source.length - 1;
|
||||
}
|
||||
var ctxEnd = ctxStart;
|
||||
var ctxLen = 0;
|
||||
var ctxLines = 0;
|
||||
|
||||
while (ctxLen < 100 && ctxStart > 0) {
|
||||
ctxStart--;
|
||||
ctxLen++;
|
||||
if (source[ctxStart] == '\n') {
|
||||
if (++ctxLines == 3) {
|
||||
break;
|
||||
while (ctxLen < 100 && ctxStart > 0) {
|
||||
ctxStart--;
|
||||
ctxLen++;
|
||||
if (source[ctxStart] == '\n') {
|
||||
if (++ctxLines == 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctxLen = 0;
|
||||
ctxLines = 0;
|
||||
while (ctxLen < 100 && ctxEnd < source.length - 1) {
|
||||
ctxEnd++;
|
||||
ctxLen++;
|
||||
if (source[ctxEnd] == '\n') {
|
||||
if (++ctxLines == 3) {
|
||||
break;
|
||||
ctxLen = 0;
|
||||
ctxLines = 0;
|
||||
while (ctxLen < 100 && ctxEnd < source.length - 1) {
|
||||
ctxEnd++;
|
||||
ctxLen++;
|
||||
if (source[ctxEnd] == '\n') {
|
||||
if (++ctxLines == 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let context = source.substring(ctxStart, this.span.start.offset) + '[ERROR ->]' +
|
||||
source.substring(this.span.start.offset, ctxEnd + 1);
|
||||
contextStr = ` ("${context}")`;
|
||||
}
|
||||
|
||||
let context = source.substring(ctxStart, this.span.start.offset) + '[ERROR ->]' +
|
||||
source.substring(this.span.start.offset, ctxEnd + 1);
|
||||
|
||||
return `${this.msg} ("${context}"): ${this.span.start}`;
|
||||
return `${this.msg}${contextStr}: ${this.span.start}`;
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,10 @@
|
||||
*/
|
||||
|
||||
import {ListWrapper} from '../src/facade/collection';
|
||||
import {BaseException} from '../src/facade/exceptions';
|
||||
import {isArray, isBlank, isPresent, normalizeBlank} from '../src/facade/lang';
|
||||
|
||||
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMap, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
|
||||
import {CompileAppModuleMetadata, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMap, 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';
|
||||
@ -270,6 +271,115 @@ export class ProviderElementContext {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class AppModuleProviderParser {
|
||||
private _transformedProviders = new CompileTokenMap<ProviderAst>();
|
||||
private _seenProviders = new CompileTokenMap<boolean>();
|
||||
private _unparsedProviders: any[] = [];
|
||||
private _allProviders: CompileTokenMap<ProviderAst>;
|
||||
private _errors: ProviderError[] = [];
|
||||
|
||||
constructor(appModule: CompileAppModuleMetadata, sourceSpan: ParseSourceSpan) {
|
||||
this._allProviders = new CompileTokenMap<ProviderAst>();
|
||||
[appModule.type].concat(appModule.modules).forEach((appModuleType: CompileTypeMetadata) => {
|
||||
var appModuleProvider = new CompileProviderMetadata(
|
||||
{token: new CompileTokenMetadata({identifier: appModuleType}), useClass: appModuleType});
|
||||
_resolveProviders(
|
||||
[appModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors,
|
||||
this._allProviders);
|
||||
});
|
||||
_resolveProviders(
|
||||
_normalizeProviders(appModule.providers, sourceSpan, this._errors),
|
||||
ProviderAstType.PublicService, false, sourceSpan, this._errors, this._allProviders);
|
||||
}
|
||||
|
||||
parse(): ProviderAst[] {
|
||||
this._allProviders.values().forEach(
|
||||
(provider) => { this._getOrCreateLocalProvider(provider.token, provider.eager); });
|
||||
if (this._errors.length > 0) {
|
||||
var errorString = this._errors.join('\n');
|
||||
throw new BaseException(`Provider parse errors:\n${errorString}`);
|
||||
}
|
||||
return this._transformedProviders.values();
|
||||
}
|
||||
|
||||
private _getOrCreateLocalProvider(token: CompileTokenMetadata, eager: boolean): ProviderAst {
|
||||
var resolvedProvider = this._allProviders.get(token);
|
||||
if (isBlank(resolvedProvider)) {
|
||||
return null;
|
||||
}
|
||||
var transformedProviderAst = this._transformedProviders.get(token);
|
||||
if (isPresent(transformedProviderAst)) {
|
||||
return transformedProviderAst;
|
||||
}
|
||||
if (isPresent(this._seenProviders.get(token))) {
|
||||
this._errors.push(new ProviderError(
|
||||
`Cannot instantiate cyclic dependency! ${token.name}`, resolvedProvider.sourceSpan));
|
||||
return null;
|
||||
}
|
||||
this._seenProviders.add(token, true);
|
||||
var transformedProviders = resolvedProvider.providers.map((provider) => {
|
||||
var transformedUseValue = provider.useValue;
|
||||
var transformedUseExisting = provider.useExisting;
|
||||
var transformedDeps: CompileDiDependencyMetadata[];
|
||||
if (isPresent(provider.useExisting)) {
|
||||
var existingDiDep = this._getDependency(
|
||||
new CompileDiDependencyMetadata({token: provider.useExisting}), eager,
|
||||
resolvedProvider.sourceSpan);
|
||||
if (isPresent(existingDiDep.token)) {
|
||||
transformedUseExisting = existingDiDep.token;
|
||||
} else {
|
||||
transformedUseExisting = null;
|
||||
transformedUseValue = existingDiDep.value;
|
||||
}
|
||||
} else if (isPresent(provider.useFactory)) {
|
||||
var deps = isPresent(provider.deps) ? provider.deps : provider.useFactory.diDeps;
|
||||
transformedDeps =
|
||||
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
|
||||
} else if (isPresent(provider.useClass)) {
|
||||
var deps = isPresent(provider.deps) ? provider.deps : provider.useClass.diDeps;
|
||||
transformedDeps =
|
||||
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
|
||||
}
|
||||
return _transformProvider(provider, {
|
||||
useExisting: transformedUseExisting,
|
||||
useValue: transformedUseValue,
|
||||
deps: transformedDeps
|
||||
});
|
||||
});
|
||||
transformedProviderAst =
|
||||
_transformProviderAst(resolvedProvider, {eager: eager, providers: transformedProviders});
|
||||
this._transformedProviders.add(token, transformedProviderAst);
|
||||
return transformedProviderAst;
|
||||
}
|
||||
|
||||
private _getDependency(
|
||||
dep: CompileDiDependencyMetadata, eager: boolean = null,
|
||||
requestorSourceSpan: ParseSourceSpan): CompileDiDependencyMetadata {
|
||||
var foundLocal = false;
|
||||
if (!dep.isSkipSelf && isPresent(dep.token)) {
|
||||
// access the injector
|
||||
if (dep.token.equalsTo(identifierToken(Identifiers.Injector)) ||
|
||||
dep.token.equalsTo(identifierToken(Identifiers.ComponentFactoryResolver))) {
|
||||
foundLocal = true;
|
||||
// access providers
|
||||
} else if (isPresent(this._getOrCreateLocalProvider(dep.token, eager))) {
|
||||
foundLocal = true;
|
||||
}
|
||||
}
|
||||
var result: CompileDiDependencyMetadata = dep;
|
||||
if (dep.isSelf && !foundLocal) {
|
||||
if (dep.isOptional) {
|
||||
result = new CompileDiDependencyMetadata({isValue: true, value: null});
|
||||
} else {
|
||||
this._errors.push(
|
||||
new ProviderError(`No provider for ${dep.token.name}`, requestorSourceSpan));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function _transformProvider(
|
||||
provider: CompileProviderMetadata,
|
||||
{useExisting, useValue, deps}:
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Compiler, ComponentFactory, ComponentResolver, Injectable} from '@angular/core';
|
||||
import {AppModuleFactory, AppModuleMetadata, Compiler, ComponentFactory, ComponentResolver, Injectable} from '@angular/core';
|
||||
|
||||
import {BaseException} from '../src/facade/exceptions';
|
||||
import {ConcreteType, IS_DART, Type, isBlank, isString, stringify} from '../src/facade/lang';
|
||||
@ -17,14 +17,15 @@ import {createHostComponentMeta, CompileDirectiveMetadata, CompilePipeMetadata,
|
||||
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 {TemplateParser} from './template_parser';
|
||||
import {DirectiveNormalizer, NormalizeDirectiveResult} from './directive_normalizer';
|
||||
import {DirectiveNormalizer} from './directive_normalizer';
|
||||
import {CompileMetadataResolver} from './metadata_resolver';
|
||||
import {CompilerConfig} from './config';
|
||||
import * as ir from './output/output_ast';
|
||||
import {jitStatements} from './output/output_jit';
|
||||
import {interpretStatements} from './output/output_interpreter';
|
||||
import {InterpretiveAppViewInstanceFactory} from './output/interpretive_view';
|
||||
import {SyncAsyncResult} from './util';
|
||||
|
||||
/**
|
||||
* An internal module of the Angular compiler that begins with component types,
|
||||
@ -37,14 +38,15 @@ import {InterpretiveAppViewInstanceFactory} from './output/interpretive_view';
|
||||
*/
|
||||
@Injectable()
|
||||
export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
private _compiledTemplateCache = new Map<any, CompiledTemplate>();
|
||||
private _compiledHostTemplateCache = new Map<any, CompiledTemplate>();
|
||||
private _compiledTemplateCache = new Map<Type, CompiledTemplate>();
|
||||
private _compiledHostTemplateCache = new Map<Type, CompiledTemplate>();
|
||||
private _compiledAppModuleCache = new Map<Type, AppModuleFactory<any>>();
|
||||
|
||||
constructor(
|
||||
private _metadataResolver: CompileMetadataResolver,
|
||||
private _templateNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
|
||||
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
|
||||
private _genConfig: CompilerConfig) {}
|
||||
private _appModuleCompiler: AppModuleCompiler, private _genConfig: CompilerConfig) {}
|
||||
|
||||
resolveComponent(component: Type|string): Promise<ComponentFactory<any>> {
|
||||
if (isString(component)) {
|
||||
@ -54,39 +56,101 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
return this.compileComponentAsync(<ConcreteType<any>>component);
|
||||
}
|
||||
|
||||
compileComponentAsync<T>(compType: ConcreteType<T>): Promise<ComponentFactory<T>> {
|
||||
var templates = this._getTransitiveCompiledTemplates(compType, true);
|
||||
compileAppModuleSync<T>(moduleType: ConcreteType<T>, metadata: AppModuleMetadata = null):
|
||||
AppModuleFactory<T> {
|
||||
return this._compileAppModule(moduleType, true, metadata).syncResult;
|
||||
}
|
||||
|
||||
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);
|
||||
var compileResult = this._appModuleCompiler.compile(compileModuleMeta);
|
||||
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.name = `compFactory_${dep.comp.name}`;
|
||||
});
|
||||
if (IS_DART || !this._genConfig.useJit) {
|
||||
appModuleFactory =
|
||||
interpretStatements(compileResult.statements, compileResult.appModuleFactoryVar);
|
||||
} else {
|
||||
appModuleFactory = jitStatements(
|
||||
`${compileModuleMeta.type.name}.ngfactory.js`, compileResult.statements,
|
||||
compileResult.appModuleFactoryVar);
|
||||
}
|
||||
if (useCache) {
|
||||
this._compiledAppModuleCache.set(moduleType, appModuleFactory);
|
||||
}
|
||||
}
|
||||
return new SyncAsyncResult(
|
||||
appModuleFactory, Promise.all(componentCompilePromises).then(() => appModuleFactory));
|
||||
}
|
||||
|
||||
compileComponentAsync<T>(compType: ConcreteType<T>, {moduleDirectives = [], modulePipes = []}: {
|
||||
moduleDirectives?: ConcreteType<any>[],
|
||||
modulePipes?: ConcreteType<any>[]
|
||||
} = {}): Promise<ComponentFactory<T>> {
|
||||
return this._compileComponent(compType, false, moduleDirectives, modulePipes).asyncResult;
|
||||
}
|
||||
|
||||
compileComponentSync<T>(compType: ConcreteType<T>, {moduleDirectives = [], modulePipes = []}: {
|
||||
moduleDirectives?: ConcreteType<any>[],
|
||||
modulePipes?: ConcreteType<any>[]
|
||||
} = {}): ComponentFactory<T> {
|
||||
return this._compileComponent(compType, true, moduleDirectives, modulePipes).syncResult;
|
||||
}
|
||||
|
||||
private _compileComponent<T>(
|
||||
compType: ConcreteType<T>, isSync: boolean, moduleDirectives: ConcreteType<any>[],
|
||||
modulePipes: ConcreteType<any>[]): SyncAsyncResult<ComponentFactory<T>> {
|
||||
var templates =
|
||||
this._getTransitiveCompiledTemplates(compType, true, moduleDirectives, modulePipes);
|
||||
var loadingPromises: Promise<any>[] = [];
|
||||
templates.forEach((template) => {
|
||||
if (template.loading) {
|
||||
loadingPromises.push(template.loading);
|
||||
if (isSync) {
|
||||
throw new BaseException(
|
||||
`Can't compile synchronously as ${template.compType.name} is still being loaded!`);
|
||||
} else {
|
||||
loadingPromises.push(template.loading);
|
||||
}
|
||||
}
|
||||
});
|
||||
return Promise.all(loadingPromises).then(() => {
|
||||
templates.forEach((template) => { this._compileTemplate(template); });
|
||||
return this._getCompiledHostTemplate(compType).proxyComponentFactory;
|
||||
});
|
||||
let compile = () => { templates.forEach((template) => { this._compileTemplate(template); }); };
|
||||
if (isSync) {
|
||||
compile();
|
||||
}
|
||||
let result = this._compiledHostTemplateCache.get(compType).proxyComponentFactory;
|
||||
return new SyncAsyncResult(result, Promise.all(loadingPromises).then(() => {
|
||||
compile();
|
||||
return result;
|
||||
}));
|
||||
}
|
||||
|
||||
compileComponentSync<T>(compType: ConcreteType<T>): ComponentFactory<T> {
|
||||
var templates = this._getTransitiveCompiledTemplates(compType, true);
|
||||
templates.forEach((template) => {
|
||||
if (template.loading) {
|
||||
throw new BaseException(
|
||||
`Can't compile synchronously as ${template.compType.name} is still being loaded!`);
|
||||
}
|
||||
});
|
||||
templates.forEach((template) => { this._compileTemplate(template); });
|
||||
return this._getCompiledHostTemplate(compType).proxyComponentFactory;
|
||||
}
|
||||
|
||||
clearCacheFor(compType: Type) {
|
||||
this._metadataResolver.clearCacheFor(compType);
|
||||
this._compiledHostTemplateCache.delete(compType);
|
||||
var compiledTemplate = this._compiledTemplateCache.get(compType);
|
||||
clearCacheFor(type: Type) {
|
||||
this._compiledAppModuleCache.delete(type);
|
||||
this._metadataResolver.clearCacheFor(type);
|
||||
this._compiledHostTemplateCache.delete(type);
|
||||
var compiledTemplate = this._compiledTemplateCache.get(type);
|
||||
if (compiledTemplate) {
|
||||
this._templateNormalizer.clearCacheFor(compiledTemplate.normalizedCompMeta);
|
||||
this._compiledTemplateCache.delete(compType);
|
||||
this._compiledTemplateCache.delete(type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,9 +159,10 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
this._compiledTemplateCache.clear();
|
||||
this._compiledHostTemplateCache.clear();
|
||||
this._templateNormalizer.clearCache();
|
||||
this._compiledAppModuleCache.clear();
|
||||
}
|
||||
|
||||
private _getCompiledHostTemplate(type: Type): CompiledTemplate {
|
||||
private _createCompiledHostTemplate(type: Type): CompiledTemplate {
|
||||
var compiledTemplate = this._compiledHostTemplateCache.get(type);
|
||||
if (isBlank(compiledTemplate)) {
|
||||
var compMeta = this._metadataResolver.getDirectiveMetadata(type);
|
||||
@ -111,12 +176,16 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
return compiledTemplate;
|
||||
}
|
||||
|
||||
private _getCompiledTemplate(type: Type): CompiledTemplate {
|
||||
private _createCompiledTemplate(
|
||||
type: Type, moduleDirectives: ConcreteType<any>[],
|
||||
modulePipes: ConcreteType<any>[]): CompiledTemplate {
|
||||
var compiledTemplate = this._compiledTemplateCache.get(type);
|
||||
if (isBlank(compiledTemplate)) {
|
||||
var compMeta = this._metadataResolver.getDirectiveMetadata(type);
|
||||
assertComponent(compMeta);
|
||||
var viewDirectives: CompileDirectiveMetadata[] = [];
|
||||
moduleDirectives.forEach(
|
||||
(type) => viewDirectives.push(this._metadataResolver.getDirectiveMetadata(type)));
|
||||
var viewComponentTypes: Type[] = [];
|
||||
this._metadataResolver.getViewDirectivesMetadata(type).forEach(dirOrComp => {
|
||||
if (dirOrComp.isComponent) {
|
||||
@ -126,7 +195,10 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
}
|
||||
});
|
||||
var precompileComponentTypes = compMeta.precompile.map((typeMeta) => typeMeta.runtime);
|
||||
var pipes = this._metadataResolver.getViewPipesMetadata(type);
|
||||
var 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));
|
||||
@ -136,16 +208,20 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
}
|
||||
|
||||
private _getTransitiveCompiledTemplates(
|
||||
compType: Type, isHost: boolean,
|
||||
compType: Type, isHost: boolean, moduleDirectives: ConcreteType<any>[],
|
||||
modulePipes: ConcreteType<any>[],
|
||||
target: Set<CompiledTemplate> = new Set<CompiledTemplate>()): Set<CompiledTemplate> {
|
||||
var template =
|
||||
isHost ? this._getCompiledHostTemplate(compType) : this._getCompiledTemplate(compType);
|
||||
var 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, target); });
|
||||
template.precompileHostComponentTypes.forEach(
|
||||
(compType) => { this._getTransitiveCompiledTemplates(compType, true, target); });
|
||||
template.viewComponentTypes.forEach((compType) => {
|
||||
this._getTransitiveCompiledTemplates(
|
||||
compType, false, moduleDirectives, modulePipes, target);
|
||||
});
|
||||
template.precompileHostComponentTypes.forEach((compType) => {
|
||||
this._getTransitiveCompiledTemplates(compType, true, moduleDirectives, modulePipes, target);
|
||||
});
|
||||
}
|
||||
return target;
|
||||
}
|
||||
@ -162,7 +238,7 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
this._resolveStylesCompileResult(
|
||||
stylesCompileResult.componentStylesheet, externalStylesheetsByModuleUrl);
|
||||
var viewCompMetas = template.viewComponentTypes.map(
|
||||
(compType) => this._getCompiledTemplate(compType).normalizedCompMeta);
|
||||
(compType) => this._compiledTemplateCache.get(compType).normalizedCompMeta);
|
||||
var parsedTemplate = this._templateParser.parse(
|
||||
compMeta, compMeta.template.template, template.viewDirectives.concat(viewCompMetas),
|
||||
template.viewPipes, compMeta.type.name);
|
||||
@ -173,12 +249,12 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
let depTemplate: CompiledTemplate;
|
||||
if (dep instanceof ViewFactoryDependency) {
|
||||
let vfd = <ViewFactoryDependency>dep;
|
||||
depTemplate = this._getCompiledTemplate(vfd.comp.runtime);
|
||||
depTemplate = this._compiledTemplateCache.get(vfd.comp.runtime);
|
||||
vfd.placeholder.runtime = depTemplate.proxyViewFactory;
|
||||
vfd.placeholder.name = `viewFactory_${vfd.comp.name}`;
|
||||
} else if (dep instanceof ComponentFactoryDependency) {
|
||||
let cfd = <ComponentFactoryDependency>dep;
|
||||
depTemplate = this._getCompiledHostTemplate(cfd.comp.runtime);
|
||||
depTemplate = this._compiledHostTemplateCache.get(cfd.comp.runtime);
|
||||
cfd.placeholder.runtime = depTemplate.proxyComponentFactory;
|
||||
cfd.placeholder.name = `compFactory_${cfd.comp.name}`;
|
||||
}
|
||||
@ -188,11 +264,10 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
stylesCompileResult.componentStylesheet.statements.concat(compileResult.statements);
|
||||
var factory: any;
|
||||
if (IS_DART || !this._genConfig.useJit) {
|
||||
factory = interpretStatements(
|
||||
statements, compileResult.viewFactoryVar, new InterpretiveAppViewInstanceFactory());
|
||||
factory = interpretStatements(statements, compileResult.viewFactoryVar);
|
||||
} else {
|
||||
factory = jitStatements(
|
||||
`${template.compType.name}.template.js`, statements, compileResult.viewFactoryVar);
|
||||
`${template.compType.name}.ngfactory.js`, statements, compileResult.viewFactoryVar);
|
||||
}
|
||||
template.compiled(factory);
|
||||
}
|
||||
@ -213,8 +288,7 @@ export class RuntimeCompiler implements ComponentResolver, Compiler {
|
||||
externalStylesheetsByModuleUrl: Map<string, CompiledStylesheet>): string[] {
|
||||
this._resolveStylesCompileResult(result, externalStylesheetsByModuleUrl);
|
||||
if (IS_DART || !this._genConfig.useJit) {
|
||||
return interpretStatements(
|
||||
result.statements, result.stylesVar, new InterpretiveAppViewInstanceFactory());
|
||||
return interpretStatements(result.statements, result.stylesVar);
|
||||
} else {
|
||||
return jitStatements(`${result.meta.moduleUrl}.css.js`, result.statements, result.stylesVar);
|
||||
}
|
||||
@ -234,7 +308,7 @@ class CompiledTemplate {
|
||||
public isHost: boolean, selector: string, public compType: CompileIdentifierMetadata,
|
||||
public viewDirectives: CompileDirectiveMetadata[], public viewComponentTypes: Type[],
|
||||
public precompileHostComponentTypes: Type[], public viewPipes: CompilePipeMetadata[],
|
||||
private _normalizeResult: NormalizeDirectiveResult) {
|
||||
_normalizeResult: SyncAsyncResult<CompileDirectiveMetadata>) {
|
||||
this.proxyViewFactory = (...args: any[]) => this._viewFactory.apply(null, args);
|
||||
this.proxyComponentFactory = isHost ?
|
||||
new ComponentFactory<any>(selector, this.proxyViewFactory, compType.runtime) :
|
||||
|
@ -6,8 +6,10 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {CompileTokenMetadata} from './compile_metadata';
|
||||
import {StringMapWrapper} from './facade/collection';
|
||||
import {IS_DART, StringWrapper, isArray, isBlank, isPrimitive, isStrictStringMap} from './facade/lang';
|
||||
import {IS_DART, StringWrapper, isArray, isBlank, isPresent, isPrimitive, isStrictStringMap} from './facade/lang';
|
||||
import * as o from './output/output_ast';
|
||||
|
||||
export var MODULE_SUFFIX = IS_DART ? '.dart' : '';
|
||||
|
||||
@ -80,3 +82,22 @@ export function assetUrl(pkg: string, path: string = null, type: string = 'src')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function createDiTokenExpression(token: CompileTokenMetadata): o.Expression {
|
||||
if (isPresent(token.value)) {
|
||||
return o.literal(token.value);
|
||||
} else if (token.identifierIsInstance) {
|
||||
return o.importExpr(token.identifier)
|
||||
.instantiate([], o.importType(token.identifier, [], [o.TypeModifier.Const]));
|
||||
} else {
|
||||
return o.importExpr(token.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
export class SyncAsyncResult<T> {
|
||||
constructor(public syncResult: T, public asyncResult: Promise<T> = null) {
|
||||
if (!asyncResult) {
|
||||
asyncResult = Promise.resolve(syncResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,10 @@ import {CompileView} from './compile_view';
|
||||
import {InjectMethodVars} from './constants';
|
||||
|
||||
import {CompileTokenMap, CompileDirectiveMetadata, CompileTokenMetadata, CompileQueryMetadata, CompileProviderMetadata, CompileDiDependencyMetadata, CompileIdentifierMetadata,} from '../compile_metadata';
|
||||
import {getPropertyInView, createDiTokenExpression, injectFromViewParentInjector} from './util';
|
||||
import {getPropertyInView, injectFromViewParentInjector} from './util';
|
||||
import {CompileQuery, createQueryList, addQueryToTokenMap} from './compile_query';
|
||||
import {CompileMethod} from './compile_method';
|
||||
import {ValueTransformer, visitValue} from '../util';
|
||||
import {createDiTokenExpression} from '../util';
|
||||
|
||||
export class CompileNode {
|
||||
constructor(
|
||||
@ -165,7 +165,7 @@ export class CompileElement extends CompileNode {
|
||||
return o.importExpr(provider.useClass)
|
||||
.instantiate(depsExpr, o.importType(provider.useClass));
|
||||
} else {
|
||||
return _convertValueToOutputAst(provider.useValue);
|
||||
return o.literal(provider.useValue);
|
||||
}
|
||||
});
|
||||
var propName = `_${resolvedProvider.token.name}_${this.nodeIndex}_${this._instances.size}`;
|
||||
@ -432,30 +432,3 @@ class _QueryWithRead {
|
||||
this.read = isPresent(query.meta.read) ? query.meta.read : match;
|
||||
}
|
||||
}
|
||||
|
||||
function _convertValueToOutputAst(value: any): o.Expression {
|
||||
return visitValue(value, new _ValueOutputAstTransformer(), null);
|
||||
}
|
||||
|
||||
class _ValueOutputAstTransformer extends ValueTransformer {
|
||||
visitArray(arr: any[], context: any): o.Expression {
|
||||
return o.literalArr(arr.map(value => visitValue(value, this, context)));
|
||||
}
|
||||
visitStringMap(map: {[key: string]: any}, context: any): o.Expression {
|
||||
var entries: Array<string|o.Expression>[] = [];
|
||||
StringMapWrapper.forEach(map, (value: any, key: string) => {
|
||||
entries.push([key, visitValue(value, this, context)]);
|
||||
});
|
||||
return o.literalMap(entries);
|
||||
}
|
||||
visitPrimitive(value: any, context: any): o.Expression { return o.literal(value); }
|
||||
visitOther(value: any, context: any): o.Expression {
|
||||
if (value instanceof CompileIdentifierMetadata) {
|
||||
return o.importExpr(value);
|
||||
} else if (value instanceof o.Expression) {
|
||||
return value;
|
||||
} else {
|
||||
throw new BaseException(`Illegal state: Don't now how to compile value ${value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import {ListWrapper} from '../facade/collection';
|
||||
import {isBlank, isPresent} from '../facade/lang';
|
||||
import {Identifiers} from '../identifiers';
|
||||
import * as o from '../output/output_ast';
|
||||
import {createDiTokenExpression} from '../util';
|
||||
|
||||
import {CompileBinding} from './compile_binding';
|
||||
import {CompileElement, CompileNode} from './compile_element';
|
||||
@ -22,7 +23,7 @@ import {CompilePipe} from './compile_pipe';
|
||||
import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query';
|
||||
import {EventHandlerVars} from './constants';
|
||||
import {NameResolver} from './expression_converter';
|
||||
import {createDiTokenExpression, createPureProxy, getPropertyInView, getViewFactoryName, injectFromViewParentInjector} from './util';
|
||||
import {createPureProxy, getPropertyInView, getViewFactoryName, injectFromViewParentInjector} from './util';
|
||||
|
||||
export class CompileView implements NameResolver {
|
||||
public viewType: ViewType;
|
||||
|
@ -13,6 +13,7 @@ import * as o from '../output/output_ast';
|
||||
import {CompileTokenMetadata, CompileDirectiveMetadata,} from '../compile_metadata';
|
||||
import {CompileView} from './compile_view';
|
||||
import {Identifiers} from '../identifiers';
|
||||
import {createDiTokenExpression} from '../util';
|
||||
|
||||
export function getPropertyInView(
|
||||
property: o.Expression, callingView: CompileView, definedView: CompileView): o.Expression {
|
||||
@ -55,18 +56,6 @@ export function getViewFactoryName(
|
||||
return `viewFactory_${component.type.name}${embeddedTemplateIndex}`;
|
||||
}
|
||||
|
||||
|
||||
export function createDiTokenExpression(token: CompileTokenMetadata): o.Expression {
|
||||
if (isPresent(token.value)) {
|
||||
return o.literal(token.value);
|
||||
} else if (token.identifierIsInstance) {
|
||||
return o.importExpr(token.identifier)
|
||||
.instantiate([], o.importType(token.identifier, [], [o.TypeModifier.Const]));
|
||||
} else {
|
||||
return o.importExpr(token.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
export function createFlatArray(expressions: o.Expression[]): o.Expression {
|
||||
var lastNonArrayExpressions: any[] /** TODO #9100 */ = [];
|
||||
var result: o.Expression = o.literalArr([]);
|
||||
|
@ -16,11 +16,12 @@ import {StringWrapper, isPresent} from '../facade/lang';
|
||||
import {Identifiers, identifierToken} from '../identifiers';
|
||||
import * as o from '../output/output_ast';
|
||||
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ProviderAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_ast';
|
||||
import {createDiTokenExpression} from '../util';
|
||||
|
||||
import {CompileElement, CompileNode} from './compile_element';
|
||||
import {CompileView} from './compile_view';
|
||||
import {ChangeDetectorStatusEnum, DetectChangesVars, InjectMethodVars, ViewConstructorVars, ViewEncapsulationEnum, ViewProperties, ViewTypeEnum} from './constants';
|
||||
import {createDiTokenExpression, createFlatArray, getViewFactoryName} from './util';
|
||||
import {createFlatArray, getViewFactoryName} from './util';
|
||||
|
||||
const IMPLICIT_TEMPLATE_VAR = '\$implicit';
|
||||
const CLASS_ATTR = 'class';
|
||||
|
@ -1,35 +0,0 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
// ATTENTION: This file will be overwritten with generated code by main()
|
||||
import {DartEmitter} from '@angular/compiler/src/output/dart_emitter';
|
||||
import {DartImportGenerator} from '@angular/compiler/src/output/dart_imports';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
|
||||
import {ComponentFactory} from '@angular/core/src/linker/component_factory';
|
||||
|
||||
import {IS_DART, print} from '../src/facade/lang';
|
||||
|
||||
import {compAMetadata, compileComp} from './offline_compiler_util';
|
||||
import {CompA, SimpleJsImportGenerator} from './offline_compiler_util';
|
||||
|
||||
export const CompANgFactory: ComponentFactory<CompA> = null;
|
||||
|
||||
export function emit(): Promise<string> {
|
||||
var emitter = IS_DART ? new DartEmitter(new DartImportGenerator()) :
|
||||
new TypeScriptEmitter(new SimpleJsImportGenerator());
|
||||
return compileComp(emitter, compAMetadata);
|
||||
}
|
||||
|
||||
// Generator
|
||||
export function main(args: string[]) {
|
||||
emit().then((source) => {
|
||||
// debug: console.error(source);
|
||||
print(source);
|
||||
});
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
// ATTENTION: This file will be overwritten with generated code by main()
|
||||
import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
|
||||
import {ComponentFactory} from '@angular/core/src/linker/component_factory';
|
||||
|
||||
import {print} from '../src/facade/lang';
|
||||
|
||||
import {compAMetadata, compileComp} from './offline_compiler_util';
|
||||
import {CompA, SimpleJsImportGenerator} from './offline_compiler_util';
|
||||
|
||||
export const CompANgFactory: ComponentFactory<CompA> = null;
|
||||
|
||||
export function emit() {
|
||||
var emitter = new JavaScriptEmitter(new SimpleJsImportGenerator());
|
||||
return compileComp(emitter, compAMetadata);
|
||||
}
|
||||
|
||||
// Generator
|
||||
export function main(args: string[]) {
|
||||
emit().then((source) => {
|
||||
// debug: console.error(source);
|
||||
print(source);
|
||||
});
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
|
||||
|
||||
export const styles = /*@ts2dart_const*/[`.greenStyle[_ngcontent-a-1] { color: green; }`];
|
@ -1,65 +0,0 @@
|
||||
/**
|
||||
* @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 {ddescribe, describe, xdescribe, it, iit, xit, expect, beforeEach, afterEach, inject, beforeEachProviders,} from '@angular/core/testing/testing_internal';
|
||||
|
||||
import {IS_DART} from '../src/facade/lang';
|
||||
import {Injector} from '@angular/core';
|
||||
|
||||
import {ComponentFactory} from '@angular/core/src/linker/component_factory';
|
||||
import * as typed from './offline_compiler_codegen_typed';
|
||||
import * as untyped from './offline_compiler_codegen_untyped';
|
||||
|
||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||
import {SharedStylesHost} from '@angular/platform-browser/src/dom/shared_styles_host';
|
||||
|
||||
import {CompA} from './offline_compiler_util';
|
||||
|
||||
export function main() {
|
||||
var typedComponentFactory = typed.CompANgFactory;
|
||||
var untypedComponentFactory = untyped.CompANgFactory;
|
||||
var fixtures: TestFixture[] = [];
|
||||
|
||||
if (IS_DART || !getDOM().supportsDOMEvents()) {
|
||||
// Our generator only works on node.js and Dart...
|
||||
fixtures.push(new TestFixture(typedComponentFactory, 'typed'));
|
||||
}
|
||||
if (!IS_DART) {
|
||||
// Our generator only works on node.js and Dart...
|
||||
if (!getDOM().supportsDOMEvents()) {
|
||||
fixtures.push(new TestFixture(untypedComponentFactory, 'untyped'));
|
||||
}
|
||||
}
|
||||
describe('OfflineCompiler', () => {
|
||||
var injector: Injector;
|
||||
var sharedStylesHost: SharedStylesHost;
|
||||
|
||||
beforeEach(inject(
|
||||
[Injector, SharedStylesHost],
|
||||
(_injector: Injector, _sharedStylesHost: SharedStylesHost) => {
|
||||
injector = _injector;
|
||||
sharedStylesHost = _sharedStylesHost;
|
||||
}));
|
||||
|
||||
fixtures.forEach((fixture) => {
|
||||
describe(`${fixture.name}`, () => {
|
||||
it('should compile components', () => {
|
||||
var hostEl = fixture.compFactory.create(injector);
|
||||
expect(hostEl.instance).toBeAnInstanceOf(CompA);
|
||||
var styles = sharedStylesHost.getAllStyles();
|
||||
expect(styles[0]).toContain('.redStyle[_ngcontent');
|
||||
expect(styles[1]).toContain('.greenStyle[_ngcontent');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class TestFixture {
|
||||
constructor(public compFactory: ComponentFactory<CompA>, public name: string) {}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
/**
|
||||
* @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 {CompileDirectiveMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import {CompilerConfig} from '@angular/compiler/src/config';
|
||||
import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer';
|
||||
import {Lexer} from '@angular/compiler/src/expression_parser/lexer';
|
||||
import {Parser} from '@angular/compiler/src/expression_parser/parser';
|
||||
import {HtmlParser} from '@angular/compiler/src/html_parser';
|
||||
import {NormalizedComponentWithViewDirectives, OfflineCompiler, SourceModule} from '@angular/compiler/src/offline_compiler';
|
||||
import {OutputEmitter} from '@angular/compiler/src/output/abstract_emitter';
|
||||
import {ImportGenerator} from '@angular/compiler/src/output/path_util';
|
||||
import {StyleCompiler} from '@angular/compiler/src/style_compiler';
|
||||
import {TemplateParser} from '@angular/compiler/src/template_parser';
|
||||
import {createOfflineCompileUrlResolver} from '@angular/compiler/src/url_resolver';
|
||||
import {MODULE_SUFFIX} from '@angular/compiler/src/util';
|
||||
import {ViewCompiler} from '@angular/compiler/src/view_compiler/view_compiler';
|
||||
import {XHR} from '@angular/compiler/src/xhr';
|
||||
|
||||
import {Console} from '../core_private';
|
||||
import {IS_DART, isPresent, print} from '../src/facade/lang';
|
||||
import {MockSchemaRegistry} from '../testing/schema_registry_mock';
|
||||
|
||||
|
||||
export class CompA { user: string; }
|
||||
|
||||
var THIS_MODULE_PATH = `asset:@angular/lib/compiler/test`;
|
||||
var THIS_MODULE_URL = `${THIS_MODULE_PATH}/offline_compiler_util${MODULE_SUFFIX}`;
|
||||
|
||||
export var compAMetadata = CompileDirectiveMetadata.create({
|
||||
isComponent: true,
|
||||
selector: 'comp-a',
|
||||
type: new CompileTypeMetadata(
|
||||
{name: 'CompA', moduleUrl: THIS_MODULE_URL, runtime: CompA, diDeps: []}),
|
||||
template: new CompileTemplateMetadata({
|
||||
templateUrl: './offline_compiler_compa.html',
|
||||
styles: ['.redStyle { color: red; }'],
|
||||
styleUrls: ['./offline_compiler_compa.css']
|
||||
})
|
||||
});
|
||||
|
||||
function _createOfflineCompiler(xhr: XHR, emitter: OutputEmitter): OfflineCompiler {
|
||||
var urlResolver = createOfflineCompileUrlResolver();
|
||||
var htmlParser = new HtmlParser();
|
||||
var config = new CompilerConfig({genDebugInfo: true, useJit: true});
|
||||
var normalizer = new DirectiveNormalizer(xhr, urlResolver, htmlParser, config);
|
||||
return new OfflineCompiler(
|
||||
normalizer,
|
||||
new TemplateParser(
|
||||
new Parser(new Lexer()), new MockSchemaRegistry({}, {}), htmlParser, new Console(), []),
|
||||
new StyleCompiler(urlResolver), new ViewCompiler(config), emitter);
|
||||
}
|
||||
|
||||
export function compileComp(
|
||||
emitter: OutputEmitter, comp: CompileDirectiveMetadata): Promise<string> {
|
||||
var xhr = new MockXhr();
|
||||
xhr.setResult(`${THIS_MODULE_PATH}/offline_compiler_compa.html`, '');
|
||||
xhr.setResult(`${THIS_MODULE_PATH}/offline_compiler_compa.css`, '');
|
||||
var compiler = _createOfflineCompiler(xhr, emitter);
|
||||
var result = compiler.normalizeDirectiveMetadata(comp).then((normComp) => {
|
||||
return compiler
|
||||
.compileTemplates([new NormalizedComponentWithViewDirectives(normComp, [], [])])[0]
|
||||
.source;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export class SimpleJsImportGenerator implements ImportGenerator {
|
||||
getImportPath(moduleUrlStr: string, importedUrlStr: string): string {
|
||||
var importedAssetUrl = ImportGenerator.parseAssetUrl(importedUrlStr);
|
||||
if (isPresent(importedAssetUrl)) {
|
||||
return `${importedAssetUrl.packageName}/${importedAssetUrl.modulePath}`;
|
||||
} else {
|
||||
return importedUrlStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MockXhr implements XHR {
|
||||
results: {[key: string]: string} = {};
|
||||
setResult(url: string, content: string) { this.results[url] = content; }
|
||||
|
||||
get(url: string): Promise<string> {
|
||||
if (url in this.results) {
|
||||
return Promise.resolve(this.results[url]);
|
||||
}
|
||||
return Promise.reject<any>(`Unknown url ${url}`);
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ import {isBlank} from '../../src/facade/lang';
|
||||
import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
|
||||
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {SimpleJsImportGenerator} from '../offline_compiler_util';
|
||||
import {SimpleJsImportGenerator} from './output_emitter_util';
|
||||
|
||||
var someModuleUrl = 'asset:somePackage/lib/somePath';
|
||||
var anotherModuleUrl = 'asset:somePackage/lib/someOtherPath';
|
||||
|
@ -15,9 +15,8 @@ import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
|
||||
import {unimplemented} from '../../src/facade/exceptions';
|
||||
import {IS_DART, print} from '../../src/facade/lang';
|
||||
import {assetUrl} from '../../src/util';
|
||||
import {SimpleJsImportGenerator} from '../offline_compiler_util';
|
||||
|
||||
import {codegenExportsVars, codegenStmts} from './output_emitter_util';
|
||||
import {SimpleJsImportGenerator, codegenExportsVars, codegenStmts} from './output_emitter_util';
|
||||
|
||||
export function getExpressions(): any {
|
||||
return unimplemented();
|
||||
|
@ -12,9 +12,8 @@ import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
|
||||
import {unimplemented} from '../../src/facade/exceptions';
|
||||
import {print} from '../../src/facade/lang';
|
||||
import {assetUrl} from '../../src/util';
|
||||
import {SimpleJsImportGenerator} from '../offline_compiler_util';
|
||||
|
||||
import {codegenExportsVars, codegenStmts} from './output_emitter_util';
|
||||
import {SimpleJsImportGenerator, codegenExportsVars, codegenStmts} from './output_emitter_util';
|
||||
|
||||
export function getExpressions(): any {
|
||||
return unimplemented();
|
||||
|
@ -14,7 +14,7 @@ import * as typed from './output_emitter_codegen_typed';
|
||||
import * as untyped from './output_emitter_codegen_untyped';
|
||||
import {jitStatements} from '@angular/compiler/src/output/output_jit';
|
||||
import {interpretStatements} from '@angular/compiler/src/output/output_interpreter';
|
||||
import {codegenStmts, ExternalClass, DynamicClassInstanceFactory} from './output_emitter_util';
|
||||
import {codegenStmts, ExternalClass} from './output_emitter_util';
|
||||
import {EventEmitter} from '@angular/core';
|
||||
import {ViewType} from '@angular/core/src/linker/view_type';
|
||||
import {BaseException} from '@angular/core';
|
||||
@ -23,8 +23,7 @@ import {browserDetection} from '@angular/platform-browser/testing/browser_util'
|
||||
|
||||
export function main() {
|
||||
var outputDefs: any[] /** TODO #9100 */ = []; outputDefs.push({
|
||||
'getExpressions': () => interpretStatements(
|
||||
codegenStmts, 'getExpressions', new DynamicClassInstanceFactory()),
|
||||
'getExpressions': () => interpretStatements(codegenStmts, 'getExpressions'),
|
||||
'name': 'interpreted'
|
||||
});
|
||||
if (IS_DART || !getDOM().supportsDOMEvents()) {
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {DynamicInstance, InstanceFactory} from '@angular/compiler/src/output/output_interpreter';
|
||||
import {ImportGenerator} from '@angular/compiler/src/output/path_util';
|
||||
import {assetUrl} from '@angular/compiler/src/util';
|
||||
import {EventEmitter} from '@angular/core';
|
||||
import {ViewType} from '@angular/core/src/linker/view_type';
|
||||
@ -253,22 +253,13 @@ function createOperatorFn(op: o.BinaryOperator) {
|
||||
o.DYNAMIC_TYPE);
|
||||
}
|
||||
|
||||
export class DynamicClassInstanceFactory implements InstanceFactory {
|
||||
createInstance(
|
||||
superClass: any, clazz: any, args: any[], props: Map<string, any>,
|
||||
getters: Map<string, Function>, methods: Map<string, Function>): any {
|
||||
if (superClass === ExternalClass) {
|
||||
return new _InterpretiveDynamicClass(args, clazz, props, getters, methods);
|
||||
export class SimpleJsImportGenerator implements ImportGenerator {
|
||||
getImportPath(moduleUrlStr: string, importedUrlStr: string): string {
|
||||
var importedAssetUrl = ImportGenerator.parseAssetUrl(importedUrlStr);
|
||||
if (importedAssetUrl) {
|
||||
return `${importedAssetUrl.packageName}/${importedAssetUrl.modulePath}`;
|
||||
} else {
|
||||
return importedUrlStr;
|
||||
}
|
||||
throw new BaseException(`Can't instantiate class ${superClass} in interpretative mode`);
|
||||
}
|
||||
}
|
||||
|
||||
class _InterpretiveDynamicClass extends ExternalClass implements DynamicInstance {
|
||||
constructor(
|
||||
args: any[], public clazz: any, public props: Map<string, any>,
|
||||
public getters: Map<string, Function>, public methods: Map<string, Function>) {
|
||||
super(args[0]);
|
||||
}
|
||||
childMethod(a: any /** TODO #9100 */) { return this.methods.get('childMethod')(a); }
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import {isBlank} from '../../src/facade/lang';
|
||||
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
|
||||
import {CompileIdentifierMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import * as o from '@angular/compiler/src/output/output_ast';
|
||||
import {SimpleJsImportGenerator} from '../offline_compiler_util';
|
||||
import {SimpleJsImportGenerator} from './output_emitter_util';
|
||||
|
||||
var someModuleUrl = 'asset:somePackage/lib/somePath';
|
||||
var anotherModuleUrl = 'asset:somePackage/lib/someOtherPath';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {beforeEach, ddescribe, xdescribe, describe, expect, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
|
||||
import {Injectable, Component, Input, ViewMetadata, Compiler, ComponentFactory, Injector} from '@angular/core';
|
||||
import {Injectable, Component, Input, ViewMetadata, Compiler, ComponentFactory, Injector, AppModule, AppModuleMetadata, AppModuleFactory} from '@angular/core';
|
||||
import {ConcreteType, stringify} from '../src/facade/lang';
|
||||
import {fakeAsync, tick, TestComponentBuilder, ComponentFixture} from '@angular/core/testing';
|
||||
import {XHR, ViewResolver} from '@angular/compiler';
|
||||
@ -19,6 +19,10 @@ class SomeComp {
|
||||
class SomeCompWithUrlTemplate {
|
||||
}
|
||||
|
||||
@AppModule({})
|
||||
class SomeModule {
|
||||
}
|
||||
|
||||
export function main() {
|
||||
describe('RuntimeCompiler', () => {
|
||||
let compiler: Compiler;
|
||||
@ -104,5 +108,51 @@ export function main() {
|
||||
expect(compFixture.nativeElement).toHaveText('hello');
|
||||
}));
|
||||
});
|
||||
|
||||
describe('compileAppModuleAsync', () => {
|
||||
it('should allow to use templateUrl components', fakeAsync(() => {
|
||||
xhr.spy('get').andCallFake(() => Promise.resolve('hello'));
|
||||
let appModuleFactory: AppModuleFactory<any>;
|
||||
compiler
|
||||
.compileAppModuleAsync(
|
||||
SomeModule, new AppModuleMetadata({precompile: [SomeCompWithUrlTemplate]}))
|
||||
.then((f) => appModuleFactory = f);
|
||||
tick();
|
||||
expect(appModuleFactory.moduleType).toBe(SomeModule);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('compileAppModuleSync', () => {
|
||||
it('should throw when using a templateUrl that has not been compiled before', () => {
|
||||
xhr.spy('get').andCallFake(() => Promise.resolve(''));
|
||||
expect(
|
||||
() => compiler.compileAppModuleSync(
|
||||
SomeModule, new AppModuleMetadata({precompile: [SomeCompWithUrlTemplate]})))
|
||||
.toThrowError(
|
||||
`Can't compile synchronously as ${stringify(SomeCompWithUrlTemplate)} is still being loaded!`);
|
||||
});
|
||||
|
||||
it('should throw when using a templateUrl in a nested component that has not been compiled before',
|
||||
() => {
|
||||
xhr.spy('get').andCallFake(() => Promise.resolve(''));
|
||||
viewResolver.setView(
|
||||
SomeComp, new ViewMetadata({template: '', directives: [ChildComp]}));
|
||||
viewResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'}));
|
||||
expect(
|
||||
() => compiler.compileAppModuleSync(
|
||||
SomeModule, new AppModuleMetadata({precompile: [SomeComp]})))
|
||||
.toThrowError(
|
||||
`Can't compile synchronously as ${stringify(ChildComp)} is still being loaded!`);
|
||||
});
|
||||
|
||||
it('should allow to use templateUrl components that have been loaded before',
|
||||
fakeAsync(() => {
|
||||
xhr.spy('get').andCallFake(() => Promise.resolve('hello'));
|
||||
tcb.createFakeAsync(SomeCompWithUrlTemplate);
|
||||
let appModuleFactory = compiler.compileAppModuleSync(
|
||||
SomeModule, new AppModuleMetadata({precompile: [SomeCompWithUrlTemplate]}));
|
||||
expect(appModuleFactory).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user