refactor(compiler): introduce directive wrappers to generate less code
- for now only wraps the `@Input` properties and calls to `ngOnInit`, `ngDoCheck` and `ngOnChanges` of directives. - also groups eval sources by NgModule. Part of #11683
This commit is contained in:
parent
c951822c35
commit
b0a03fcab3
@ -11,7 +11,7 @@
|
|||||||
* Intended to be used in a build step.
|
* Intended to be used in a build step.
|
||||||
*/
|
*/
|
||||||
import * as compiler from '@angular/compiler';
|
import * as compiler from '@angular/compiler';
|
||||||
import {Component, NgModule, ViewEncapsulation} from '@angular/core';
|
import {Directive, NgModule, ViewEncapsulation} from '@angular/core';
|
||||||
import {AngularCompilerOptions, NgcCliOptions} from '@angular/tsc-wrapped';
|
import {AngularCompilerOptions, NgcCliOptions} from '@angular/tsc-wrapped';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
@ -58,7 +58,7 @@ export class CodeGeneratorModuleCollector {
|
|||||||
|
|
||||||
private readFileMetadata(absSourcePath: string): FileMetadata {
|
private readFileMetadata(absSourcePath: string): FileMetadata {
|
||||||
const moduleMetadata = this.staticReflector.getModuleMetadata(absSourcePath);
|
const moduleMetadata = this.staticReflector.getModuleMetadata(absSourcePath);
|
||||||
const result: FileMetadata = {components: [], ngModules: [], fileUrl: absSourcePath};
|
const result: FileMetadata = {directives: [], ngModules: [], fileUrl: absSourcePath};
|
||||||
if (!moduleMetadata) {
|
if (!moduleMetadata) {
|
||||||
console.log(`WARNING: no metadata found for ${absSourcePath}`);
|
console.log(`WARNING: no metadata found for ${absSourcePath}`);
|
||||||
return result;
|
return result;
|
||||||
@ -78,8 +78,8 @@ export class CodeGeneratorModuleCollector {
|
|||||||
annotations.forEach((annotation) => {
|
annotations.forEach((annotation) => {
|
||||||
if (annotation instanceof NgModule) {
|
if (annotation instanceof NgModule) {
|
||||||
result.ngModules.push(staticType);
|
result.ngModules.push(staticType);
|
||||||
} else if (annotation instanceof Component) {
|
} else if (annotation instanceof Directive) {
|
||||||
result.components.push(staticType);
|
result.directives.push(staticType);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ export class CodeGenerator {
|
|||||||
(fileMeta) =>
|
(fileMeta) =>
|
||||||
this.compiler
|
this.compiler
|
||||||
.compile(
|
.compile(
|
||||||
fileMeta.fileUrl, analyzedNgModules, fileMeta.components, fileMeta.ngModules)
|
fileMeta.fileUrl, analyzedNgModules, fileMeta.directives, fileMeta.ngModules)
|
||||||
.then((generatedModules) => {
|
.then((generatedModules) => {
|
||||||
generatedModules.forEach((generatedModule) => {
|
generatedModules.forEach((generatedModule) => {
|
||||||
const sourceFile = this.program.getSourceFile(fileMeta.fileUrl);
|
const sourceFile = this.program.getSourceFile(fileMeta.fileUrl);
|
||||||
@ -193,8 +193,9 @@ export class CodeGenerator {
|
|||||||
// TODO(vicb): do not pass cliOptions.i18nFormat here
|
// TODO(vicb): do not pass cliOptions.i18nFormat here
|
||||||
const offlineCompiler = new compiler.OfflineCompiler(
|
const offlineCompiler = new compiler.OfflineCompiler(
|
||||||
resolver, normalizer, tmplParser, new compiler.StyleCompiler(urlResolver),
|
resolver, normalizer, tmplParser, new compiler.StyleCompiler(urlResolver),
|
||||||
new compiler.ViewCompiler(config), new compiler.NgModuleCompiler(),
|
new compiler.ViewCompiler(config), new compiler.DirectiveWrapperCompiler(config),
|
||||||
new compiler.TypeScriptEmitter(reflectorHost), cliOptions.locale, cliOptions.i18nFormat);
|
new compiler.NgModuleCompiler(), new compiler.TypeScriptEmitter(reflectorHost),
|
||||||
|
cliOptions.locale, cliOptions.i18nFormat);
|
||||||
|
|
||||||
return new CodeGenerator(
|
return new CodeGenerator(
|
||||||
options, program, compilerHost, staticReflector, offlineCompiler, reflectorHost);
|
options, program, compilerHost, staticReflector, offlineCompiler, reflectorHost);
|
||||||
@ -203,6 +204,6 @@ export class CodeGenerator {
|
|||||||
|
|
||||||
export interface FileMetadata {
|
export interface FileMetadata {
|
||||||
fileUrl: string;
|
fileUrl: string;
|
||||||
components: StaticSymbol[];
|
directives: StaticSymbol[];
|
||||||
ngModules: StaticSymbol[];
|
ngModules: StaticSymbol[];
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ export class Extractor {
|
|||||||
const url = fileMeta.fileUrl;
|
const url = fileMeta.fileUrl;
|
||||||
return Promise.all(fileMeta.components.map(compType => {
|
return Promise.all(fileMeta.components.map(compType => {
|
||||||
const compMeta = this.metadataResolver.getDirectiveMetadata(<any>compType);
|
const compMeta = this.metadataResolver.getDirectiveMetadata(<any>compType);
|
||||||
const ngModule = analyzedNgModules.ngModuleByComponent.get(compType);
|
const ngModule = analyzedNgModules.ngModuleByDirective.get(compType);
|
||||||
if (!ngModule) {
|
if (!ngModule) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Cannot determine the module for component ${compMeta.type.name}!`);
|
`Cannot determine the module for component ${compMeta.type.name}!`);
|
||||||
|
@ -44,6 +44,7 @@ export * from './src/metadata_resolver';
|
|||||||
export * from './src/ml_parser/html_parser';
|
export * from './src/ml_parser/html_parser';
|
||||||
export * from './src/ml_parser/interpolation_config';
|
export * from './src/ml_parser/interpolation_config';
|
||||||
export {NgModuleCompiler} from './src/ng_module_compiler';
|
export {NgModuleCompiler} from './src/ng_module_compiler';
|
||||||
|
export {DirectiveWrapperCompiler} from './src/directive_wrapper_compiler';
|
||||||
export * from './src/output/path_util';
|
export * from './src/output/path_util';
|
||||||
export * from './src/output/ts_emitter';
|
export * from './src/output/ts_emitter';
|
||||||
export * from './src/parse_util';
|
export * from './src/parse_util';
|
||||||
|
@ -11,6 +11,7 @@ import {COMPILER_OPTIONS, Compiler, CompilerFactory, CompilerOptions, Inject, In
|
|||||||
import {CompilerConfig} from './config';
|
import {CompilerConfig} from './config';
|
||||||
import {DirectiveNormalizer} from './directive_normalizer';
|
import {DirectiveNormalizer} from './directive_normalizer';
|
||||||
import {DirectiveResolver} from './directive_resolver';
|
import {DirectiveResolver} from './directive_resolver';
|
||||||
|
import {DirectiveWrapperCompiler} from './directive_wrapper_compiler';
|
||||||
import {Lexer} from './expression_parser/lexer';
|
import {Lexer} from './expression_parser/lexer';
|
||||||
import {Parser} from './expression_parser/parser';
|
import {Parser} from './expression_parser/parser';
|
||||||
import * as i18n from './i18n/index';
|
import * as i18n from './i18n/index';
|
||||||
@ -64,6 +65,7 @@ export const COMPILER_PROVIDERS: Array<any|Type<any>|{[k: string]: any}|any[]> =
|
|||||||
StyleCompiler,
|
StyleCompiler,
|
||||||
ViewCompiler,
|
ViewCompiler,
|
||||||
NgModuleCompiler,
|
NgModuleCompiler,
|
||||||
|
DirectiveWrapperCompiler,
|
||||||
{provide: CompilerConfig, useValue: new CompilerConfig()},
|
{provide: CompilerConfig, useValue: new CompilerConfig()},
|
||||||
RuntimeCompiler,
|
RuntimeCompiler,
|
||||||
{provide: Compiler, useExisting: RuntimeCompiler},
|
{provide: Compiler, useExisting: RuntimeCompiler},
|
||||||
|
186
modules/@angular/compiler/src/directive_wrapper_compiler.ts
Normal file
186
modules/@angular/compiler/src/directive_wrapper_compiler.ts
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/**
|
||||||
|
* @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 {CompileDirectiveMetadata, CompileIdentifierMetadata} from './compile_metadata';
|
||||||
|
import {CompilerConfig} from './config';
|
||||||
|
import {Identifiers, resolveIdentifier} from './identifiers';
|
||||||
|
import * as o from './output/output_ast';
|
||||||
|
import {LifecycleHooks, isDefaultChangeDetectionStrategy} from './private_import_core';
|
||||||
|
|
||||||
|
export class DirectiveWrapperCompileResult {
|
||||||
|
constructor(public statements: o.Statement[], public dirWrapperClassVar: string) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CONTEXT_FIELD_NAME = 'context';
|
||||||
|
const CHANGES_FIELD_NAME = 'changes';
|
||||||
|
const CHANGED_FIELD_NAME = 'changed';
|
||||||
|
|
||||||
|
const CURR_VALUE_VAR = o.variable('currValue');
|
||||||
|
const THROW_ON_CHANGE_VAR = o.variable('throwOnChange');
|
||||||
|
const FORCE_UPDATE_VAR = o.variable('forceUpdate');
|
||||||
|
const VIEW_VAR = o.variable('view');
|
||||||
|
const RENDER_EL_VAR = o.variable('el');
|
||||||
|
|
||||||
|
const RESET_CHANGES_STMT = o.THIS_EXPR.prop(CHANGES_FIELD_NAME).set(o.literalMap([])).toStmt();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We generate directive wrappers to prevent code bloat when a directive is used.
|
||||||
|
* A directive wrapper encapsulates
|
||||||
|
* the dirty checking for `@Input`, the handling of `@HostListener` / `@HostBinding`
|
||||||
|
* and calling the lifecyclehooks `ngOnInit`, `ngOnChanges`, `ngDoCheck`.
|
||||||
|
*
|
||||||
|
* So far, only `@Input` and the lifecycle hooks have been implemented.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class DirectiveWrapperCompiler {
|
||||||
|
static dirWrapperClassName(id: CompileIdentifierMetadata) { return `Wrapper_${id.name}`; }
|
||||||
|
|
||||||
|
constructor(private compilerConfig: CompilerConfig) {}
|
||||||
|
|
||||||
|
compile(dirMeta: CompileDirectiveMetadata): DirectiveWrapperCompileResult {
|
||||||
|
const dirDepParamNames: string[] = [];
|
||||||
|
for (let i = 0; i < dirMeta.type.diDeps.length; i++) {
|
||||||
|
dirDepParamNames.push(`p${i}`);
|
||||||
|
}
|
||||||
|
const dirLifecycleHooks = dirMeta.type.lifecycleHooks;
|
||||||
|
let lifecycleHooks: GenConfig = {
|
||||||
|
genChanges: dirLifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1 ||
|
||||||
|
this.compilerConfig.logBindingUpdate,
|
||||||
|
ngOnChanges: dirLifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1,
|
||||||
|
ngOnInit: dirLifecycleHooks.indexOf(LifecycleHooks.OnInit) !== -1,
|
||||||
|
ngDoCheck: dirLifecycleHooks.indexOf(LifecycleHooks.DoCheck) !== -1
|
||||||
|
};
|
||||||
|
|
||||||
|
const fields: o.ClassField[] = [
|
||||||
|
new o.ClassField(CONTEXT_FIELD_NAME, o.importType(dirMeta.type)),
|
||||||
|
new o.ClassField(CHANGED_FIELD_NAME, o.BOOL_TYPE),
|
||||||
|
];
|
||||||
|
const ctorStmts: o.Statement[] =
|
||||||
|
[o.THIS_EXPR.prop(CHANGED_FIELD_NAME).set(o.literal(false)).toStmt()];
|
||||||
|
if (lifecycleHooks.genChanges) {
|
||||||
|
fields.push(new o.ClassField(CHANGES_FIELD_NAME, new o.MapType(o.DYNAMIC_TYPE)));
|
||||||
|
ctorStmts.push(RESET_CHANGES_STMT);
|
||||||
|
}
|
||||||
|
|
||||||
|
const methods: o.ClassMethod[] = [];
|
||||||
|
Object.keys(dirMeta.inputs).forEach((inputFieldName, idx) => {
|
||||||
|
const fieldName = `_${inputFieldName}`;
|
||||||
|
// private is fine here as no child view will reference the cached value...
|
||||||
|
fields.push(new o.ClassField(fieldName, null, [o.StmtModifier.Private]));
|
||||||
|
ctorStmts.push(o.THIS_EXPR.prop(fieldName)
|
||||||
|
.set(o.importExpr(resolveIdentifier(Identifiers.UNINITIALIZED)))
|
||||||
|
.toStmt());
|
||||||
|
methods.push(checkInputMethod(inputFieldName, o.THIS_EXPR.prop(fieldName), lifecycleHooks));
|
||||||
|
});
|
||||||
|
methods.push(detectChangesInternalMethod(lifecycleHooks, this.compilerConfig.genDebugInfo));
|
||||||
|
|
||||||
|
ctorStmts.push(
|
||||||
|
o.THIS_EXPR.prop(CONTEXT_FIELD_NAME)
|
||||||
|
.set(o.importExpr(dirMeta.type)
|
||||||
|
.instantiate(dirDepParamNames.map((paramName) => o.variable(paramName))))
|
||||||
|
.toStmt());
|
||||||
|
const ctor = new o.ClassMethod(
|
||||||
|
null, dirDepParamNames.map((paramName) => new o.FnParam(paramName, o.DYNAMIC_TYPE)),
|
||||||
|
ctorStmts);
|
||||||
|
|
||||||
|
const wrapperClassName = DirectiveWrapperCompiler.dirWrapperClassName(dirMeta.type);
|
||||||
|
const classStmt = new o.ClassStmt(wrapperClassName, null, fields, [], ctor, methods);
|
||||||
|
return new DirectiveWrapperCompileResult([classStmt], wrapperClassName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function detectChangesInternalMethod(
|
||||||
|
lifecycleHooks: GenConfig, logBindingUpdate: boolean): o.ClassMethod {
|
||||||
|
const changedVar = o.variable('changed');
|
||||||
|
const stmts: o.Statement[] = [
|
||||||
|
changedVar.set(o.THIS_EXPR.prop(CHANGED_FIELD_NAME)).toDeclStmt(),
|
||||||
|
o.THIS_EXPR.prop(CHANGED_FIELD_NAME).set(o.literal(false)).toStmt(),
|
||||||
|
];
|
||||||
|
const lifecycleStmts: o.Statement[] = [];
|
||||||
|
|
||||||
|
if (lifecycleHooks.genChanges) {
|
||||||
|
const onChangesStmts: o.Statement[] = [];
|
||||||
|
if (lifecycleHooks.ngOnChanges) {
|
||||||
|
onChangesStmts.push(o.THIS_EXPR.prop(CONTEXT_FIELD_NAME)
|
||||||
|
.callMethod('ngOnChanges', [o.THIS_EXPR.prop(CHANGES_FIELD_NAME)])
|
||||||
|
.toStmt());
|
||||||
|
}
|
||||||
|
if (logBindingUpdate) {
|
||||||
|
onChangesStmts.push(
|
||||||
|
o.importExpr(resolveIdentifier(Identifiers.setBindingDebugInfoForChanges))
|
||||||
|
.callFn(
|
||||||
|
[VIEW_VAR.prop('renderer'), RENDER_EL_VAR, o.THIS_EXPR.prop(CHANGES_FIELD_NAME)])
|
||||||
|
.toStmt());
|
||||||
|
}
|
||||||
|
onChangesStmts.push(RESET_CHANGES_STMT);
|
||||||
|
lifecycleStmts.push(new o.IfStmt(changedVar, onChangesStmts));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lifecycleHooks.ngOnInit) {
|
||||||
|
lifecycleStmts.push(new o.IfStmt(
|
||||||
|
VIEW_VAR.prop('numberOfChecks').identical(new o.LiteralExpr(0)),
|
||||||
|
[o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).callMethod('ngOnInit', []).toStmt()]));
|
||||||
|
}
|
||||||
|
if (lifecycleHooks.ngDoCheck) {
|
||||||
|
lifecycleStmts.push(o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).callMethod('ngDoCheck', []).toStmt());
|
||||||
|
}
|
||||||
|
if (lifecycleStmts.length > 0) {
|
||||||
|
stmts.push(new o.IfStmt(o.not(THROW_ON_CHANGE_VAR), lifecycleStmts));
|
||||||
|
}
|
||||||
|
stmts.push(new o.ReturnStatement(changedVar));
|
||||||
|
|
||||||
|
return new o.ClassMethod(
|
||||||
|
'detectChangesInternal',
|
||||||
|
[
|
||||||
|
new o.FnParam(
|
||||||
|
VIEW_VAR.name, o.importType(resolveIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
|
||||||
|
new o.FnParam(RENDER_EL_VAR.name, o.DYNAMIC_TYPE),
|
||||||
|
new o.FnParam(THROW_ON_CHANGE_VAR.name, o.BOOL_TYPE),
|
||||||
|
],
|
||||||
|
stmts, o.BOOL_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInputMethod(
|
||||||
|
input: string, fieldExpr: o.ReadPropExpr, lifecycleHooks: GenConfig): o.ClassMethod {
|
||||||
|
var onChangeStatements: o.Statement[] = [
|
||||||
|
o.THIS_EXPR.prop(CHANGED_FIELD_NAME).set(o.literal(true)).toStmt(),
|
||||||
|
o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).prop(input).set(CURR_VALUE_VAR).toStmt(),
|
||||||
|
];
|
||||||
|
if (lifecycleHooks.genChanges) {
|
||||||
|
onChangeStatements.push(o.THIS_EXPR.prop(CHANGES_FIELD_NAME)
|
||||||
|
.key(o.literal(input))
|
||||||
|
.set(o.importExpr(resolveIdentifier(Identifiers.SimpleChange))
|
||||||
|
.instantiate([fieldExpr, CURR_VALUE_VAR]))
|
||||||
|
.toStmt());
|
||||||
|
}
|
||||||
|
onChangeStatements.push(fieldExpr.set(CURR_VALUE_VAR).toStmt());
|
||||||
|
|
||||||
|
var methodBody: o.Statement[] = [
|
||||||
|
new o.IfStmt(
|
||||||
|
FORCE_UPDATE_VAR.or(o.importExpr(resolveIdentifier(Identifiers.checkBinding))
|
||||||
|
.callFn([THROW_ON_CHANGE_VAR, fieldExpr, CURR_VALUE_VAR])),
|
||||||
|
onChangeStatements),
|
||||||
|
];
|
||||||
|
return new o.ClassMethod(
|
||||||
|
`check_${input}`,
|
||||||
|
[
|
||||||
|
new o.FnParam(CURR_VALUE_VAR.name, o.DYNAMIC_TYPE),
|
||||||
|
new o.FnParam(THROW_ON_CHANGE_VAR.name, o.BOOL_TYPE),
|
||||||
|
new o.FnParam(FORCE_UPDATE_VAR.name, o.BOOL_TYPE),
|
||||||
|
],
|
||||||
|
methodBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GenConfig {
|
||||||
|
genChanges: boolean;
|
||||||
|
ngOnChanges: boolean;
|
||||||
|
ngOnInit: boolean;
|
||||||
|
ngDoCheck: boolean;
|
||||||
|
}
|
@ -6,10 +6,10 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {ANALYZE_FOR_ENTRY_COMPONENTS, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, LOCALE_ID as LOCALE_ID_, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT as TRANSLATIONS_FORMAT_, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
import {ANALYZE_FOR_ENTRY_COMPONENTS, AnimationTransitionEvent, ChangeDetectionStrategy, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ElementRef, Injector, LOCALE_ID, NgModuleFactory, QueryList, RenderComponentType, Renderer, SecurityContext, SimpleChange, TRANSLATIONS_FORMAT, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
|
||||||
|
|
||||||
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
|
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
|
||||||
import {AnimationGroupPlayer, AnimationKeyframe, AnimationSequencePlayer, AnimationStyles, AnimationTransition, AppElement, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NgModuleInjector, NoOpAnimationPlayer, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes, castByValue, checkBinding, clearStyles, collectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, prepareFinalAnimationStyles, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, reflector, registerModuleFactory, renderStyles} from './private_import_core';
|
import {AnimationGroupPlayer, AnimationKeyframe, AnimationSequencePlayer, AnimationStyles, AnimationTransition, AppElement, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, DebugAppView, DebugContext, NgModuleInjector, NoOpAnimationPlayer, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewType, balanceAnimationKeyframes, clearStyles, collectAndResolveStyles, devModeEqual, prepareFinalAnimationStyles, reflector, registerModuleFactory, renderStyles, view_utils} from './private_import_core';
|
||||||
import {assetUrl} from './util';
|
import {assetUrl} from './util';
|
||||||
|
|
||||||
var APP_VIEW_MODULE_URL = assetUrl('core', 'linker/view');
|
var APP_VIEW_MODULE_URL = assetUrl('core', 'linker/view');
|
||||||
@ -33,7 +33,7 @@ export class Identifiers {
|
|||||||
static ViewUtils: IdentifierSpec = {
|
static ViewUtils: IdentifierSpec = {
|
||||||
name: 'ViewUtils',
|
name: 'ViewUtils',
|
||||||
moduleUrl: assetUrl('core', 'linker/view_utils'),
|
moduleUrl: assetUrl('core', 'linker/view_utils'),
|
||||||
runtime: ViewUtils
|
runtime: view_utils.ViewUtils
|
||||||
};
|
};
|
||||||
static AppView:
|
static AppView:
|
||||||
IdentifierSpec = {name: 'AppView', moduleUrl: APP_VIEW_MODULE_URL, runtime: AppView};
|
IdentifierSpec = {name: 'AppView', moduleUrl: APP_VIEW_MODULE_URL, runtime: AppView};
|
||||||
@ -161,45 +161,48 @@ export class Identifiers {
|
|||||||
static checkBinding: IdentifierSpec = {
|
static checkBinding: IdentifierSpec = {
|
||||||
name: 'checkBinding',
|
name: 'checkBinding',
|
||||||
moduleUrl: VIEW_UTILS_MODULE_URL,
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
runtime: checkBinding
|
runtime: view_utils.checkBinding
|
||||||
};
|
};
|
||||||
static flattenNestedViewRenderNodes: IdentifierSpec = {
|
static flattenNestedViewRenderNodes: IdentifierSpec = {
|
||||||
name: 'flattenNestedViewRenderNodes',
|
name: 'flattenNestedViewRenderNodes',
|
||||||
moduleUrl: VIEW_UTILS_MODULE_URL,
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
runtime: flattenNestedViewRenderNodes
|
runtime: view_utils.flattenNestedViewRenderNodes
|
||||||
};
|
};
|
||||||
static devModeEqual:
|
static devModeEqual:
|
||||||
IdentifierSpec = {name: 'devModeEqual', moduleUrl: CD_MODULE_URL, runtime: devModeEqual};
|
IdentifierSpec = {name: 'devModeEqual', moduleUrl: CD_MODULE_URL, runtime: devModeEqual};
|
||||||
static interpolate: IdentifierSpec = {
|
static interpolate: IdentifierSpec = {
|
||||||
name: 'interpolate',
|
name: 'interpolate',
|
||||||
moduleUrl: VIEW_UTILS_MODULE_URL,
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
runtime: interpolate
|
runtime: view_utils.interpolate
|
||||||
};
|
};
|
||||||
static castByValue: IdentifierSpec = {
|
static castByValue: IdentifierSpec = {
|
||||||
name: 'castByValue',
|
name: 'castByValue',
|
||||||
moduleUrl: VIEW_UTILS_MODULE_URL,
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
runtime: castByValue
|
runtime: view_utils.castByValue
|
||||||
};
|
};
|
||||||
static EMPTY_ARRAY: IdentifierSpec = {
|
static EMPTY_ARRAY: IdentifierSpec = {
|
||||||
name: 'EMPTY_ARRAY',
|
name: 'EMPTY_ARRAY',
|
||||||
moduleUrl: VIEW_UTILS_MODULE_URL,
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
runtime: EMPTY_ARRAY
|
runtime: view_utils.EMPTY_ARRAY
|
||||||
|
};
|
||||||
|
static EMPTY_MAP: IdentifierSpec = {
|
||||||
|
name: 'EMPTY_MAP',
|
||||||
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
|
runtime: view_utils.EMPTY_MAP
|
||||||
};
|
};
|
||||||
static EMPTY_MAP:
|
|
||||||
IdentifierSpec = {name: 'EMPTY_MAP', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: EMPTY_MAP};
|
|
||||||
|
|
||||||
static pureProxies = [
|
static pureProxies = [
|
||||||
null,
|
null,
|
||||||
{name: 'pureProxy1', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy1},
|
{name: 'pureProxy1', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy1},
|
||||||
{name: 'pureProxy2', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy2},
|
{name: 'pureProxy2', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy2},
|
||||||
{name: 'pureProxy3', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy3},
|
{name: 'pureProxy3', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy3},
|
||||||
{name: 'pureProxy4', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy4},
|
{name: 'pureProxy4', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy4},
|
||||||
{name: 'pureProxy5', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy5},
|
{name: 'pureProxy5', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy5},
|
||||||
{name: 'pureProxy6', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy6},
|
{name: 'pureProxy6', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy6},
|
||||||
{name: 'pureProxy7', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy7},
|
{name: 'pureProxy7', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy7},
|
||||||
{name: 'pureProxy8', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy8},
|
{name: 'pureProxy8', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy8},
|
||||||
{name: 'pureProxy9', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy9},
|
{name: 'pureProxy9', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy9},
|
||||||
{name: 'pureProxy10', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: pureProxy10},
|
{name: 'pureProxy10', moduleUrl: VIEW_UTILS_MODULE_URL, runtime: view_utils.pureProxy10},
|
||||||
];
|
];
|
||||||
static SecurityContext: IdentifierSpec = {
|
static SecurityContext: IdentifierSpec = {
|
||||||
name: 'SecurityContext',
|
name: 'SecurityContext',
|
||||||
@ -259,12 +262,22 @@ export class Identifiers {
|
|||||||
static LOCALE_ID: IdentifierSpec = {
|
static LOCALE_ID: IdentifierSpec = {
|
||||||
name: 'LOCALE_ID',
|
name: 'LOCALE_ID',
|
||||||
moduleUrl: assetUrl('core', 'i18n/tokens'),
|
moduleUrl: assetUrl('core', 'i18n/tokens'),
|
||||||
runtime: LOCALE_ID_
|
runtime: LOCALE_ID
|
||||||
};
|
};
|
||||||
static TRANSLATIONS_FORMAT: IdentifierSpec = {
|
static TRANSLATIONS_FORMAT: IdentifierSpec = {
|
||||||
name: 'TRANSLATIONS_FORMAT',
|
name: 'TRANSLATIONS_FORMAT',
|
||||||
moduleUrl: assetUrl('core', 'i18n/tokens'),
|
moduleUrl: assetUrl('core', 'i18n/tokens'),
|
||||||
runtime: TRANSLATIONS_FORMAT_
|
runtime: TRANSLATIONS_FORMAT
|
||||||
|
};
|
||||||
|
static setBindingDebugInfo: IdentifierSpec = {
|
||||||
|
name: 'setBindingDebugInfo',
|
||||||
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
|
runtime: view_utils.setBindingDebugInfo
|
||||||
|
};
|
||||||
|
static setBindingDebugInfoForChanges: IdentifierSpec = {
|
||||||
|
name: 'setBindingDebugInfoForChanges',
|
||||||
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
|
runtime: view_utils.setBindingDebugInfoForChanges
|
||||||
};
|
};
|
||||||
static AnimationTransition: IdentifierSpec = {
|
static AnimationTransition: IdentifierSpec = {
|
||||||
name: 'AnimationTransition',
|
name: 'AnimationTransition',
|
||||||
|
@ -116,8 +116,7 @@ export class CompileMetadataResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDirectiveMetadata(directiveType: Type<any>, throwIfNotFound = true):
|
getDirectiveMetadata(directiveType: any, throwIfNotFound = true): cpl.CompileDirectiveMetadata {
|
||||||
cpl.CompileDirectiveMetadata {
|
|
||||||
directiveType = resolveForwardRef(directiveType);
|
directiveType = resolveForwardRef(directiveType);
|
||||||
let meta = this._directiveCache.get(directiveType);
|
let meta = this._directiveCache.get(directiveType);
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
|
@ -12,6 +12,7 @@ import {AnimationCompiler} from './animation/animation_compiler';
|
|||||||
import {AnimationParser} from './animation/animation_parser';
|
import {AnimationParser} from './animation/animation_parser';
|
||||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, CompileProviderMetadata, StaticSymbol, createHostComponentMeta} from './compile_metadata';
|
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, CompileProviderMetadata, StaticSymbol, createHostComponentMeta} from './compile_metadata';
|
||||||
import {DirectiveNormalizer} from './directive_normalizer';
|
import {DirectiveNormalizer} from './directive_normalizer';
|
||||||
|
import {DirectiveWrapperCompileResult, DirectiveWrapperCompiler} from './directive_wrapper_compiler';
|
||||||
import {Identifiers, resolveIdentifier, resolveIdentifierToken} from './identifiers';
|
import {Identifiers, resolveIdentifier, resolveIdentifierToken} from './identifiers';
|
||||||
import {CompileMetadataResolver} from './metadata_resolver';
|
import {CompileMetadataResolver} from './metadata_resolver';
|
||||||
import {NgModuleCompiler} from './ng_module_compiler';
|
import {NgModuleCompiler} from './ng_module_compiler';
|
||||||
@ -19,7 +20,7 @@ import {OutputEmitter} from './output/abstract_emitter';
|
|||||||
import * as o from './output/output_ast';
|
import * as o from './output/output_ast';
|
||||||
import {CompiledStylesheet, StyleCompiler} from './style_compiler';
|
import {CompiledStylesheet, StyleCompiler} from './style_compiler';
|
||||||
import {TemplateParser} from './template_parser/template_parser';
|
import {TemplateParser} from './template_parser/template_parser';
|
||||||
import {ComponentFactoryDependency, ViewCompileResult, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
|
import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewCompileResult, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
|
||||||
|
|
||||||
export class SourceModule {
|
export class SourceModule {
|
||||||
constructor(public moduleUrl: string, public source: string) {}
|
constructor(public moduleUrl: string, public source: string) {}
|
||||||
@ -27,25 +28,23 @@ export class SourceModule {
|
|||||||
|
|
||||||
export class NgModulesSummary {
|
export class NgModulesSummary {
|
||||||
constructor(
|
constructor(
|
||||||
public ngModuleByComponent: Map<StaticSymbol, CompileNgModuleMetadata>,
|
public ngModuleByDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
|
||||||
public ngModules: CompileNgModuleMetadata[]) {}
|
public ngModules: CompileNgModuleMetadata[]) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function analyzeModules(
|
export function analyzeModules(
|
||||||
ngModules: StaticSymbol[], metadataResolver: CompileMetadataResolver) {
|
ngModules: StaticSymbol[], metadataResolver: CompileMetadataResolver) {
|
||||||
const ngModuleByComponent = new Map<StaticSymbol, CompileNgModuleMetadata>();
|
const ngModuleByDirective = new Map<StaticSymbol, CompileNgModuleMetadata>();
|
||||||
const modules: CompileNgModuleMetadata[] = [];
|
const modules: CompileNgModuleMetadata[] = [];
|
||||||
|
|
||||||
ngModules.forEach((ngModule) => {
|
ngModules.forEach((ngModule) => {
|
||||||
const ngModuleMeta = metadataResolver.getNgModuleMetadata(<any>ngModule);
|
const ngModuleMeta = metadataResolver.getNgModuleMetadata(<any>ngModule);
|
||||||
modules.push(ngModuleMeta);
|
modules.push(ngModuleMeta);
|
||||||
ngModuleMeta.declaredDirectives.forEach((dirMeta: CompileDirectiveMetadata) => {
|
ngModuleMeta.declaredDirectives.forEach((dirMeta: CompileDirectiveMetadata) => {
|
||||||
if (dirMeta.isComponent) {
|
ngModuleByDirective.set(dirMeta.type.reference, ngModuleMeta);
|
||||||
ngModuleByComponent.set(dirMeta.type.reference, ngModuleMeta);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return new NgModulesSummary(ngModuleByComponent, modules);
|
return new NgModulesSummary(ngModuleByDirective, modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OfflineCompiler {
|
export class OfflineCompiler {
|
||||||
@ -56,6 +55,7 @@ export class OfflineCompiler {
|
|||||||
private _metadataResolver: CompileMetadataResolver,
|
private _metadataResolver: CompileMetadataResolver,
|
||||||
private _directiveNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
|
private _directiveNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
|
||||||
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
|
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
|
||||||
|
private _dirWrapperCompiler: DirectiveWrapperCompiler,
|
||||||
private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter,
|
private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter,
|
||||||
private _localeId: string, private _translationFormat: string) {}
|
private _localeId: string, private _translationFormat: string) {}
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ export class OfflineCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compile(
|
compile(
|
||||||
moduleUrl: string, ngModulesSummary: NgModulesSummary, components: StaticSymbol[],
|
moduleUrl: string, ngModulesSummary: NgModulesSummary, directives: StaticSymbol[],
|
||||||
ngModules: StaticSymbol[]): Promise<SourceModule[]> {
|
ngModules: StaticSymbol[]): Promise<SourceModule[]> {
|
||||||
const fileSuffix = _splitTypescriptSuffix(moduleUrl)[1];
|
const fileSuffix = _splitTypescriptSuffix(moduleUrl)[1];
|
||||||
const statements: o.Statement[] = [];
|
const statements: o.Statement[] = [];
|
||||||
@ -80,11 +80,18 @@ export class OfflineCompiler {
|
|||||||
exportedVars.push(
|
exportedVars.push(
|
||||||
...ngModules.map((ngModuleType) => this._compileModule(ngModuleType, statements)));
|
...ngModules.map((ngModuleType) => this._compileModule(ngModuleType, statements)));
|
||||||
|
|
||||||
|
// compile directive wrappers
|
||||||
|
exportedVars.push(...directives.map(
|
||||||
|
(directiveType) => this._compileDirectiveWrapper(directiveType, statements)));
|
||||||
|
|
||||||
// compile components
|
// compile components
|
||||||
return Promise
|
return Promise
|
||||||
.all(components.map((compType) => {
|
.all(directives.map((dirType) => {
|
||||||
const compMeta = this._metadataResolver.getDirectiveMetadata(<any>compType);
|
const compMeta = this._metadataResolver.getDirectiveMetadata(<any>dirType);
|
||||||
const ngModule = ngModulesSummary.ngModuleByComponent.get(compType);
|
if (!compMeta.isComponent) {
|
||||||
|
return Promise.resolve(null);
|
||||||
|
}
|
||||||
|
const ngModule = ngModulesSummary.ngModuleByDirective.get(dirType);
|
||||||
if (!ngModule) {
|
if (!ngModule) {
|
||||||
throw new Error(`Cannot determine the module for component ${compMeta.type.name}!`);
|
throw new Error(`Cannot determine the module for component ${compMeta.type.name}!`);
|
||||||
}
|
}
|
||||||
@ -148,6 +155,15 @@ export class OfflineCompiler {
|
|||||||
return appCompileResult.ngModuleFactoryVar;
|
return appCompileResult.ngModuleFactoryVar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _compileDirectiveWrapper(directiveType: StaticSymbol, targetStatements: o.Statement[]):
|
||||||
|
string {
|
||||||
|
const dirMeta = this._metadataResolver.getDirectiveMetadata(directiveType);
|
||||||
|
const dirCompileResult = this._dirWrapperCompiler.compile(dirMeta);
|
||||||
|
|
||||||
|
targetStatements.push(...dirCompileResult.statements);
|
||||||
|
return dirCompileResult.dirWrapperClassVar;
|
||||||
|
}
|
||||||
|
|
||||||
private _compileComponentFactory(
|
private _compileComponentFactory(
|
||||||
compMeta: CompileDirectiveMetadata, fileSuffix: string,
|
compMeta: CompileDirectiveMetadata, fileSuffix: string,
|
||||||
targetStatements: o.Statement[]): string {
|
targetStatements: o.Statement[]): string {
|
||||||
@ -217,6 +233,9 @@ function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[]
|
|||||||
const cfd = <ComponentFactoryDependency>dep;
|
const cfd = <ComponentFactoryDependency>dep;
|
||||||
cfd.placeholder.name = _componentFactoryName(cfd.comp);
|
cfd.placeholder.name = _componentFactoryName(cfd.comp);
|
||||||
cfd.placeholder.moduleUrl = _ngfactoryModuleUrl(cfd.comp.moduleUrl);
|
cfd.placeholder.moduleUrl = _ngfactoryModuleUrl(cfd.comp.moduleUrl);
|
||||||
|
} else if (dep instanceof DirectiveWrapperDependency) {
|
||||||
|
const dwd = <DirectiveWrapperDependency>dep;
|
||||||
|
dwd.placeholder.moduleUrl = _ngfactoryModuleUrl(dwd.dir.moduleUrl);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return compileResult.statements;
|
return compileResult.statements;
|
||||||
@ -231,8 +250,8 @@ function _resolveStyleStatements(
|
|||||||
return compileResult.statements;
|
return compileResult.statements;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _ngfactoryModuleUrl(compUrl: string): string {
|
function _ngfactoryModuleUrl(dirUrl: string): string {
|
||||||
const urlWithSuffix = _splitTypescriptSuffix(compUrl);
|
const urlWithSuffix = _splitTypescriptSuffix(dirUrl);
|
||||||
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
|
return `${urlWithSuffix[0]}.ngfactory${urlWithSuffix[1]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ function createDynamicClass(
|
|||||||
_executeFunctionStatements(
|
_executeFunctionStatements(
|
||||||
ctorParamNames, args, _classStmt.constructorMethod.body, instanceCtx, _visitor);
|
ctorParamNames, args, _classStmt.constructorMethod.body, instanceCtx, _visitor);
|
||||||
};
|
};
|
||||||
var superClass = _classStmt.parent.visitExpression(_visitor, _ctx);
|
var superClass = _classStmt.parent ? _classStmt.parent.visitExpression(_visitor, _ctx) : Object;
|
||||||
ctor.prototype = Object.create(superClass.prototype, propertyDescriptors);
|
ctor.prototype = Object.create(superClass.prototype, propertyDescriptors);
|
||||||
return ctor;
|
return ctor;
|
||||||
}
|
}
|
||||||
|
@ -27,13 +27,7 @@ export const NgModuleInjector: typeof r.NgModuleInjector = r.NgModuleInjector;
|
|||||||
export const registerModuleFactory: typeof r.registerModuleFactory = r.registerModuleFactory;
|
export const registerModuleFactory: typeof r.registerModuleFactory = r.registerModuleFactory;
|
||||||
export type ViewType = typeof r._ViewType;
|
export type ViewType = typeof r._ViewType;
|
||||||
export const ViewType: typeof r.ViewType = r.ViewType;
|
export const ViewType: typeof r.ViewType = r.ViewType;
|
||||||
export const MAX_INTERPOLATION_VALUES: typeof r.MAX_INTERPOLATION_VALUES =
|
export const view_utils: typeof r.view_utils = r.view_utils;
|
||||||
r.MAX_INTERPOLATION_VALUES;
|
|
||||||
export const checkBinding: typeof r.checkBinding = r.checkBinding;
|
|
||||||
export const flattenNestedViewRenderNodes: typeof r.flattenNestedViewRenderNodes =
|
|
||||||
r.flattenNestedViewRenderNodes;
|
|
||||||
export const interpolate: typeof r.interpolate = r.interpolate;
|
|
||||||
export const ViewUtils: typeof r.ViewUtils = r.ViewUtils;
|
|
||||||
export const DebugContext: typeof r.DebugContext = r.DebugContext;
|
export const DebugContext: typeof r.DebugContext = r.DebugContext;
|
||||||
export const StaticNodeDebugInfo: typeof r.StaticNodeDebugInfo = r.StaticNodeDebugInfo;
|
export const StaticNodeDebugInfo: typeof r.StaticNodeDebugInfo = r.StaticNodeDebugInfo;
|
||||||
export const devModeEqual: typeof r.devModeEqual = r.devModeEqual;
|
export const devModeEqual: typeof r.devModeEqual = r.devModeEqual;
|
||||||
@ -42,19 +36,6 @@ export const ValueUnwrapper: typeof r.ValueUnwrapper = r.ValueUnwrapper;
|
|||||||
export const TemplateRef_: typeof r.TemplateRef_ = r.TemplateRef_;
|
export const TemplateRef_: typeof r.TemplateRef_ = r.TemplateRef_;
|
||||||
export type RenderDebugInfo = typeof r._RenderDebugInfo;
|
export type RenderDebugInfo = typeof r._RenderDebugInfo;
|
||||||
export const RenderDebugInfo: typeof r.RenderDebugInfo = r.RenderDebugInfo;
|
export const RenderDebugInfo: typeof r.RenderDebugInfo = r.RenderDebugInfo;
|
||||||
export const EMPTY_ARRAY: typeof r.EMPTY_ARRAY = r.EMPTY_ARRAY;
|
|
||||||
export const EMPTY_MAP: typeof r.EMPTY_MAP = r.EMPTY_MAP;
|
|
||||||
export const pureProxy1: typeof r.pureProxy1 = r.pureProxy1;
|
|
||||||
export const pureProxy2: typeof r.pureProxy2 = r.pureProxy2;
|
|
||||||
export const pureProxy3: typeof r.pureProxy3 = r.pureProxy3;
|
|
||||||
export const pureProxy4: typeof r.pureProxy4 = r.pureProxy4;
|
|
||||||
export const pureProxy5: typeof r.pureProxy5 = r.pureProxy5;
|
|
||||||
export const pureProxy6: typeof r.pureProxy6 = r.pureProxy6;
|
|
||||||
export const pureProxy7: typeof r.pureProxy7 = r.pureProxy7;
|
|
||||||
export const pureProxy8: typeof r.pureProxy8 = r.pureProxy8;
|
|
||||||
export const pureProxy9: typeof r.pureProxy9 = r.pureProxy9;
|
|
||||||
export const pureProxy10: typeof r.pureProxy10 = r.pureProxy10;
|
|
||||||
export const castByValue: typeof r.castByValue = r.castByValue;
|
|
||||||
export type Console = typeof r._Console;
|
export type Console = typeof r._Console;
|
||||||
export const Console: typeof r.Console = r.Console;
|
export const Console: typeof r.Console = r.Console;
|
||||||
export const reflector: typeof r.reflector = r.reflector;
|
export const reflector: typeof r.reflector = r.reflector;
|
||||||
|
@ -7,11 +7,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Compiler, ComponentFactory, Injectable, Injector, ModuleWithComponentFactories, NgModuleFactory, SchemaMetadata, Type} from '@angular/core';
|
import {Compiler, ComponentFactory, Injectable, Injector, ModuleWithComponentFactories, NgModuleFactory, SchemaMetadata, Type} from '@angular/core';
|
||||||
|
|
||||||
import {AnimationCompiler} from './animation/animation_compiler';
|
import {AnimationCompiler} from './animation/animation_compiler';
|
||||||
import {AnimationParser} from './animation/animation_parser';
|
import {AnimationParser} from './animation/animation_parser';
|
||||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, ProviderMeta, createHostComponentMeta} from './compile_metadata';
|
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, ProviderMeta, createHostComponentMeta} from './compile_metadata';
|
||||||
import {CompilerConfig} from './config';
|
import {CompilerConfig} from './config';
|
||||||
import {DirectiveNormalizer} from './directive_normalizer';
|
import {DirectiveNormalizer} from './directive_normalizer';
|
||||||
|
import {DirectiveWrapperCompiler} from './directive_wrapper_compiler';
|
||||||
import {stringify} from './facade/lang';
|
import {stringify} from './facade/lang';
|
||||||
import {CompileMetadataResolver} from './metadata_resolver';
|
import {CompileMetadataResolver} from './metadata_resolver';
|
||||||
import {NgModuleCompiler} from './ng_module_compiler';
|
import {NgModuleCompiler} from './ng_module_compiler';
|
||||||
@ -22,7 +24,8 @@ import {ComponentStillLoadingError} from './private_import_core';
|
|||||||
import {CompiledStylesheet, StyleCompiler} from './style_compiler';
|
import {CompiledStylesheet, StyleCompiler} from './style_compiler';
|
||||||
import {TemplateParser} from './template_parser/template_parser';
|
import {TemplateParser} from './template_parser/template_parser';
|
||||||
import {SyncAsyncResult} from './util';
|
import {SyncAsyncResult} from './util';
|
||||||
import {ComponentFactoryDependency, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
|
import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An internal module of the Angular compiler that begins with component types,
|
* An internal module of the Angular compiler that begins with component types,
|
||||||
@ -37,6 +40,7 @@ import {ComponentFactoryDependency, ViewCompiler, ViewFactoryDependency} from '.
|
|||||||
export class RuntimeCompiler implements Compiler {
|
export class RuntimeCompiler implements Compiler {
|
||||||
private _compiledTemplateCache = new Map<Type<any>, CompiledTemplate>();
|
private _compiledTemplateCache = new Map<Type<any>, CompiledTemplate>();
|
||||||
private _compiledHostTemplateCache = new Map<Type<any>, CompiledTemplate>();
|
private _compiledHostTemplateCache = new Map<Type<any>, CompiledTemplate>();
|
||||||
|
private _compiledDirectiveWrapperCache = new Map<Type<any>, Type<any>>();
|
||||||
private _compiledNgModuleCache = new Map<Type<any>, NgModuleFactory<any>>();
|
private _compiledNgModuleCache = new Map<Type<any>, NgModuleFactory<any>>();
|
||||||
private _animationParser = new AnimationParser();
|
private _animationParser = new AnimationParser();
|
||||||
private _animationCompiler = new AnimationCompiler();
|
private _animationCompiler = new AnimationCompiler();
|
||||||
@ -45,7 +49,9 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
private _injector: Injector, private _metadataResolver: CompileMetadataResolver,
|
private _injector: Injector, private _metadataResolver: CompileMetadataResolver,
|
||||||
private _templateNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
|
private _templateNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
|
||||||
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
|
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
|
||||||
private _ngModuleCompiler: NgModuleCompiler, private _compilerConfig: CompilerConfig) {}
|
private _ngModuleCompiler: NgModuleCompiler,
|
||||||
|
private _directiveWrapperCompiler: DirectiveWrapperCompiler,
|
||||||
|
private _compilerConfig: CompilerConfig) {}
|
||||||
|
|
||||||
get injector(): Injector { return this._injector; }
|
get injector(): Injector { return this._injector; }
|
||||||
|
|
||||||
@ -80,10 +86,11 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
const moduleMeta = this._metadataResolver.getNgModuleMetadata(moduleType);
|
const moduleMeta = this._metadataResolver.getNgModuleMetadata(moduleType);
|
||||||
const componentFactories: ComponentFactory<any>[] = [];
|
const componentFactories: ComponentFactory<any>[] = [];
|
||||||
const templates = new Set<CompiledTemplate>();
|
const templates = new Set<CompiledTemplate>();
|
||||||
moduleMeta.transitiveModule.modules.forEach((moduleMeta) => {
|
moduleMeta.transitiveModule.modules.forEach((localModuleMeta) => {
|
||||||
moduleMeta.declaredDirectives.forEach((dirMeta) => {
|
localModuleMeta.declaredDirectives.forEach((dirMeta) => {
|
||||||
if (dirMeta.isComponent) {
|
if (dirMeta.isComponent) {
|
||||||
const template = this._createCompiledHostTemplate(dirMeta.type.reference);
|
const template =
|
||||||
|
this._createCompiledHostTemplate(dirMeta.type.reference, localModuleMeta);
|
||||||
templates.add(template);
|
templates.add(template);
|
||||||
componentFactories.push(template.proxyComponentFactory);
|
componentFactories.push(template.proxyComponentFactory);
|
||||||
}
|
}
|
||||||
@ -119,7 +126,7 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
interpretStatements(compileResult.statements, compileResult.ngModuleFactoryVar);
|
interpretStatements(compileResult.statements, compileResult.ngModuleFactoryVar);
|
||||||
} else {
|
} else {
|
||||||
ngModuleFactory = jitStatements(
|
ngModuleFactory = jitStatements(
|
||||||
`${moduleMeta.type.name}.ngfactory.js`, compileResult.statements,
|
`/${moduleMeta.type.name}/module.ngfactory.js`, compileResult.statements,
|
||||||
compileResult.ngModuleFactoryVar);
|
compileResult.ngModuleFactoryVar);
|
||||||
}
|
}
|
||||||
this._compiledNgModuleCache.set(moduleMeta.type.reference, ngModuleFactory);
|
this._compiledNgModuleCache.set(moduleMeta.type.reference, ngModuleFactory);
|
||||||
@ -135,22 +142,32 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
var loadingPromises: Promise<any>[] = [];
|
var loadingPromises: Promise<any>[] = [];
|
||||||
|
|
||||||
const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule);
|
const ngModule = this._metadataResolver.getNgModuleMetadata(mainModule);
|
||||||
|
const moduleByDirective = new Map<any, CompileNgModuleMetadata>();
|
||||||
|
ngModule.transitiveModule.modules.forEach((localModuleMeta) => {
|
||||||
|
localModuleMeta.declaredDirectives.forEach((dirMeta) => {
|
||||||
|
moduleByDirective.set(dirMeta.type.reference, localModuleMeta);
|
||||||
|
this._compileDirectiveWrapper(dirMeta, localModuleMeta);
|
||||||
|
if (dirMeta.isComponent) {
|
||||||
|
templates.add(this._createCompiledTemplate(dirMeta, localModuleMeta));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
ngModule.transitiveModule.modules.forEach((localModuleMeta) => {
|
ngModule.transitiveModule.modules.forEach((localModuleMeta) => {
|
||||||
localModuleMeta.declaredDirectives.forEach((dirMeta) => {
|
localModuleMeta.declaredDirectives.forEach((dirMeta) => {
|
||||||
if (dirMeta.isComponent) {
|
if (dirMeta.isComponent) {
|
||||||
templates.add(this._createCompiledTemplate(dirMeta, localModuleMeta));
|
|
||||||
dirMeta.entryComponents.forEach((entryComponentType) => {
|
dirMeta.entryComponents.forEach((entryComponentType) => {
|
||||||
templates.add(this._createCompiledHostTemplate(entryComponentType.reference));
|
const moduleMeta = moduleByDirective.get(entryComponentType.reference);
|
||||||
|
templates.add(
|
||||||
|
this._createCompiledHostTemplate(entryComponentType.reference, moduleMeta));
|
||||||
});
|
});
|
||||||
// TODO: what about entryComponents of entryComponents? maybe skip here and just do the
|
|
||||||
// below?
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
localModuleMeta.entryComponents.forEach((entryComponentType) => {
|
localModuleMeta.entryComponents.forEach((entryComponentType) => {
|
||||||
templates.add(this._createCompiledHostTemplate(entryComponentType.reference));
|
const moduleMeta = moduleByDirective.get(entryComponentType.reference);
|
||||||
// TODO: what about entryComponents of entryComponents?
|
templates.add(this._createCompiledHostTemplate(entryComponentType.reference, moduleMeta));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
templates.forEach((template) => {
|
templates.forEach((template) => {
|
||||||
if (template.loading) {
|
if (template.loading) {
|
||||||
if (isSync) {
|
if (isSync) {
|
||||||
@ -189,14 +206,19 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
this._compiledNgModuleCache.clear();
|
this._compiledNgModuleCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createCompiledHostTemplate(compType: Type<any>): CompiledTemplate {
|
private _createCompiledHostTemplate(compType: Type<any>, ngModule: CompileNgModuleMetadata):
|
||||||
|
CompiledTemplate {
|
||||||
|
if (!ngModule) {
|
||||||
|
throw new Error(
|
||||||
|
`Component ${stringify(compType)} is not part of any NgModule or the module has not been imported into your module.`);
|
||||||
|
}
|
||||||
var compiledTemplate = this._compiledHostTemplateCache.get(compType);
|
var compiledTemplate = this._compiledHostTemplateCache.get(compType);
|
||||||
if (!compiledTemplate) {
|
if (!compiledTemplate) {
|
||||||
var compMeta = this._metadataResolver.getDirectiveMetadata(compType);
|
var compMeta = this._metadataResolver.getDirectiveMetadata(compType);
|
||||||
assertComponent(compMeta);
|
assertComponent(compMeta);
|
||||||
var hostMeta = createHostComponentMeta(compMeta);
|
var hostMeta = createHostComponentMeta(compMeta);
|
||||||
compiledTemplate = new CompiledTemplate(
|
compiledTemplate = new CompiledTemplate(
|
||||||
true, compMeta.selector, compMeta.type, [compMeta], [], [],
|
true, compMeta.selector, compMeta.type, ngModule, [compMeta],
|
||||||
this._templateNormalizer.normalizeDirective(hostMeta));
|
this._templateNormalizer.normalizeDirective(hostMeta));
|
||||||
this._compiledHostTemplateCache.set(compType, compiledTemplate);
|
this._compiledHostTemplateCache.set(compType, compiledTemplate);
|
||||||
}
|
}
|
||||||
@ -209,8 +231,7 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
if (!compiledTemplate) {
|
if (!compiledTemplate) {
|
||||||
assertComponent(compMeta);
|
assertComponent(compMeta);
|
||||||
compiledTemplate = new CompiledTemplate(
|
compiledTemplate = new CompiledTemplate(
|
||||||
false, compMeta.selector, compMeta.type, ngModule.transitiveModule.directives,
|
false, compMeta.selector, compMeta.type, ngModule, ngModule.transitiveModule.directives,
|
||||||
ngModule.transitiveModule.pipes, ngModule.schemas,
|
|
||||||
this._templateNormalizer.normalizeDirective(compMeta));
|
this._templateNormalizer.normalizeDirective(compMeta));
|
||||||
this._compiledTemplateCache.set(compMeta.type.reference, compiledTemplate);
|
this._compiledTemplateCache.set(compMeta.type.reference, compiledTemplate);
|
||||||
}
|
}
|
||||||
@ -221,13 +242,8 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
const compiledTemplate = isHost ? this._compiledHostTemplateCache.get(compType) :
|
const compiledTemplate = isHost ? this._compiledHostTemplateCache.get(compType) :
|
||||||
this._compiledTemplateCache.get(compType);
|
this._compiledTemplateCache.get(compType);
|
||||||
if (!compiledTemplate) {
|
if (!compiledTemplate) {
|
||||||
if (isHost) {
|
throw new Error(
|
||||||
throw new Error(
|
`Illegal state: Compiled view for component ${stringify(compType)} does not exist!`);
|
||||||
`Illegal state: Compiled view for component ${stringify(compType)} does not exist!`);
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
`Component ${stringify(compType)} is not part of any NgModule or the module has not been imported into your module.`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return compiledTemplate;
|
return compiledTemplate;
|
||||||
}
|
}
|
||||||
@ -241,6 +257,30 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
return compiledTemplate;
|
return compiledTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _assertDirectiveWrapper(dirType: any): Type<any> {
|
||||||
|
const dirWrapper = this._compiledDirectiveWrapperCache.get(dirType);
|
||||||
|
if (!dirWrapper) {
|
||||||
|
throw new Error(
|
||||||
|
`Illegal state: Directive wrapper for ${stringify(dirType)} has not been compiled!`);
|
||||||
|
}
|
||||||
|
return dirWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _compileDirectiveWrapper(
|
||||||
|
dirMeta: CompileDirectiveMetadata, moduleMeta: CompileNgModuleMetadata): void {
|
||||||
|
const compileResult = this._directiveWrapperCompiler.compile(dirMeta);
|
||||||
|
const statements = compileResult.statements;
|
||||||
|
let directiveWrapperClass: any;
|
||||||
|
if (!this._compilerConfig.useJit) {
|
||||||
|
directiveWrapperClass = interpretStatements(statements, compileResult.dirWrapperClassVar);
|
||||||
|
} else {
|
||||||
|
directiveWrapperClass = jitStatements(
|
||||||
|
`/${moduleMeta.type.name}/${dirMeta.type.name}/wrapper.ngfactory.js`, statements,
|
||||||
|
compileResult.dirWrapperClassVar);
|
||||||
|
}
|
||||||
|
this._compiledDirectiveWrapperCache.set(dirMeta.type.reference, directiveWrapperClass);
|
||||||
|
}
|
||||||
|
|
||||||
private _compileTemplate(template: CompiledTemplate) {
|
private _compileTemplate(template: CompiledTemplate) {
|
||||||
if (template.isCompiled) {
|
if (template.isCompiled) {
|
||||||
return;
|
return;
|
||||||
@ -275,6 +315,9 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
depTemplate = this._assertComponentLoaded(cfd.comp.reference, true);
|
depTemplate = this._assertComponentLoaded(cfd.comp.reference, true);
|
||||||
cfd.placeholder.reference = depTemplate.proxyComponentFactory;
|
cfd.placeholder.reference = depTemplate.proxyComponentFactory;
|
||||||
cfd.placeholder.name = `compFactory_${cfd.comp.name}`;
|
cfd.placeholder.name = `compFactory_${cfd.comp.name}`;
|
||||||
|
} else if (dep instanceof DirectiveWrapperDependency) {
|
||||||
|
let dwd = <DirectiveWrapperDependency>dep;
|
||||||
|
dwd.placeholder.reference = this._assertDirectiveWrapper(dwd.dir.reference);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const statements =
|
const statements =
|
||||||
@ -286,8 +329,8 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
factory = interpretStatements(statements, compileResult.viewFactoryVar);
|
factory = interpretStatements(statements, compileResult.viewFactoryVar);
|
||||||
} else {
|
} else {
|
||||||
factory = jitStatements(
|
factory = jitStatements(
|
||||||
`${template.compType.name}${template.isHost?'_Host':''}.ngfactory.js`, statements,
|
`/${template.ngModule.type.name}/${template.compType.name}/${template.isHost?'host':'component'}.ngfactory.js`,
|
||||||
compileResult.viewFactoryVar);
|
statements, compileResult.viewFactoryVar);
|
||||||
}
|
}
|
||||||
template.compiled(factory);
|
template.compiled(factory);
|
||||||
}
|
}
|
||||||
@ -310,7 +353,7 @@ export class RuntimeCompiler implements Compiler {
|
|||||||
if (!this._compilerConfig.useJit) {
|
if (!this._compilerConfig.useJit) {
|
||||||
return interpretStatements(result.statements, result.stylesVar);
|
return interpretStatements(result.statements, result.stylesVar);
|
||||||
} else {
|
} else {
|
||||||
return jitStatements(`${result.meta.moduleUrl}.css.js`, result.statements, result.stylesVar);
|
return jitStatements(`/${result.meta.moduleUrl}.css.js`, result.statements, result.stylesVar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,13 +368,17 @@ class CompiledTemplate {
|
|||||||
isCompiledWithDeps = false;
|
isCompiledWithDeps = false;
|
||||||
viewComponentTypes: Type<any>[] = [];
|
viewComponentTypes: Type<any>[] = [];
|
||||||
viewDirectives: CompileDirectiveMetadata[] = [];
|
viewDirectives: CompileDirectiveMetadata[] = [];
|
||||||
|
viewPipes: CompilePipeMetadata[];
|
||||||
|
schemas: SchemaMetadata[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public isHost: boolean, selector: string, public compType: CompileIdentifierMetadata,
|
public isHost: boolean, selector: string, public compType: CompileIdentifierMetadata,
|
||||||
viewDirectivesAndComponents: CompileDirectiveMetadata[],
|
public ngModule: CompileNgModuleMetadata,
|
||||||
public viewPipes: CompilePipeMetadata[], public schemas: SchemaMetadata[],
|
viewDirectiveAndComponents: CompileDirectiveMetadata[],
|
||||||
_normalizeResult: SyncAsyncResult<CompileDirectiveMetadata>) {
|
_normalizeResult: SyncAsyncResult<CompileDirectiveMetadata>) {
|
||||||
viewDirectivesAndComponents.forEach((dirMeta) => {
|
this.viewPipes = ngModule.transitiveModule.pipes;
|
||||||
|
this.schemas = ngModule.schemas;
|
||||||
|
viewDirectiveAndComponents.forEach((dirMeta) => {
|
||||||
if (dirMeta.isComponent) {
|
if (dirMeta.isComponent) {
|
||||||
this.viewComponentTypes.push(dirMeta.type.reference);
|
this.viewComponentTypes.push(dirMeta.type.reference);
|
||||||
} else {
|
} else {
|
||||||
|
@ -20,7 +20,7 @@ import {expandNodes} from '../ml_parser/icu_ast_expander';
|
|||||||
import {InterpolationConfig} from '../ml_parser/interpolation_config';
|
import {InterpolationConfig} from '../ml_parser/interpolation_config';
|
||||||
import {mergeNsAndName, splitNsName} from '../ml_parser/tags';
|
import {mergeNsAndName, splitNsName} from '../ml_parser/tags';
|
||||||
import {ParseError, ParseErrorLevel, ParseSourceSpan} from '../parse_util';
|
import {ParseError, ParseErrorLevel, ParseSourceSpan} from '../parse_util';
|
||||||
import {Console, MAX_INTERPOLATION_VALUES} from '../private_import_core';
|
import {Console, view_utils} from '../private_import_core';
|
||||||
import {ProviderElementContext, ProviderViewContext} from '../provider_analyzer';
|
import {ProviderElementContext, ProviderViewContext} from '../provider_analyzer';
|
||||||
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
|
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
|
||||||
import {CssSelector, SelectorMatcher} from '../selector';
|
import {CssSelector, SelectorMatcher} from '../selector';
|
||||||
@ -246,8 +246,9 @@ class TemplateParseVisitor implements html.Visitor {
|
|||||||
if (ast) this._reportParserErrors(ast.errors, sourceSpan);
|
if (ast) this._reportParserErrors(ast.errors, sourceSpan);
|
||||||
this._checkPipes(ast, sourceSpan);
|
this._checkPipes(ast, sourceSpan);
|
||||||
if (isPresent(ast) &&
|
if (isPresent(ast) &&
|
||||||
(<Interpolation>ast.ast).expressions.length > MAX_INTERPOLATION_VALUES) {
|
(<Interpolation>ast.ast).expressions.length > view_utils.MAX_INTERPOLATION_VALUES) {
|
||||||
throw new Error(`Only support at most ${MAX_INTERPOLATION_VALUES} interpolation values!`);
|
throw new Error(
|
||||||
|
`Only support at most ${view_utils.MAX_INTERPOLATION_VALUES} interpolation values!`);
|
||||||
}
|
}
|
||||||
return ast;
|
return ast;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileIdentifierMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata} from '../compile_metadata';
|
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileIdentifierMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMetadata} from '../compile_metadata';
|
||||||
|
import {DirectiveWrapperCompiler} from '../directive_wrapper_compiler';
|
||||||
import {ListWrapper, MapWrapper} from '../facade/collection';
|
import {ListWrapper, MapWrapper} from '../facade/collection';
|
||||||
import {isPresent} from '../facade/lang';
|
import {isPresent} from '../facade/lang';
|
||||||
import {Identifiers, identifierToken, resolveIdentifier, resolveIdentifierToken} from '../identifiers';
|
import {Identifiers, identifierToken, resolveIdentifier, resolveIdentifierToken} from '../identifiers';
|
||||||
@ -19,7 +20,8 @@ import {createDiTokenExpression} from '../util';
|
|||||||
import {CompileMethod} from './compile_method';
|
import {CompileMethod} from './compile_method';
|
||||||
import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query';
|
import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query';
|
||||||
import {CompileView} from './compile_view';
|
import {CompileView} from './compile_view';
|
||||||
import {InjectMethodVars} from './constants';
|
import {InjectMethodVars, ViewProperties} from './constants';
|
||||||
|
import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewFactoryDependency} from './deps';
|
||||||
import {getPropertyInView, injectFromViewParentInjector} from './util';
|
import {getPropertyInView, injectFromViewParentInjector} from './util';
|
||||||
|
|
||||||
export class CompileNode {
|
export class CompileNode {
|
||||||
@ -34,7 +36,7 @@ export class CompileNode {
|
|||||||
|
|
||||||
export class CompileElement extends CompileNode {
|
export class CompileElement extends CompileNode {
|
||||||
static createNull(): CompileElement {
|
static createNull(): CompileElement {
|
||||||
return new CompileElement(null, null, null, null, null, null, [], [], false, false, []);
|
return new CompileElement(null, null, null, null, null, null, [], [], false, false, [], []);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _compViewExpr: o.Expression = null;
|
private _compViewExpr: o.Expression = null;
|
||||||
@ -42,6 +44,7 @@ export class CompileElement extends CompileNode {
|
|||||||
public elementRef: o.Expression;
|
public elementRef: o.Expression;
|
||||||
public injector: o.Expression;
|
public injector: o.Expression;
|
||||||
public instances = new Map<any, o.Expression>();
|
public instances = new Map<any, o.Expression>();
|
||||||
|
public directiveWrapperInstance = new Map<any, o.Expression>();
|
||||||
private _resolvedProviders: Map<any, ProviderAst>;
|
private _resolvedProviders: Map<any, ProviderAst>;
|
||||||
|
|
||||||
private _queryCount = 0;
|
private _queryCount = 0;
|
||||||
@ -57,7 +60,9 @@ export class CompileElement extends CompileNode {
|
|||||||
sourceAst: TemplateAst, public component: CompileDirectiveMetadata,
|
sourceAst: TemplateAst, public component: CompileDirectiveMetadata,
|
||||||
private _directives: CompileDirectiveMetadata[],
|
private _directives: CompileDirectiveMetadata[],
|
||||||
private _resolvedProvidersArray: ProviderAst[], public hasViewContainer: boolean,
|
private _resolvedProvidersArray: ProviderAst[], public hasViewContainer: boolean,
|
||||||
public hasEmbeddedView: boolean, references: ReferenceAst[]) {
|
public hasEmbeddedView: boolean, references: ReferenceAst[],
|
||||||
|
private _targetDependencies:
|
||||||
|
Array<ViewFactoryDependency|ComponentFactoryDependency|DirectiveWrapperDependency>) {
|
||||||
super(parent, view, nodeIndex, renderNode, sourceAst);
|
super(parent, view, nodeIndex, renderNode, sourceAst);
|
||||||
this.referenceTokens = {};
|
this.referenceTokens = {};
|
||||||
references.forEach(ref => this.referenceTokens[ref.name] = ref.value);
|
references.forEach(ref => this.referenceTokens[ref.name] = ref.value);
|
||||||
@ -72,6 +77,9 @@ export class CompileElement extends CompileNode {
|
|||||||
if (this.hasViewContainer || this.hasEmbeddedView || isPresent(this.component)) {
|
if (this.hasViewContainer || this.hasEmbeddedView || isPresent(this.component)) {
|
||||||
this._createAppElement();
|
this._createAppElement();
|
||||||
}
|
}
|
||||||
|
if (this.component) {
|
||||||
|
this._createComponentFactoryResolver();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createAppElement() {
|
private _createAppElement() {
|
||||||
@ -92,7 +100,13 @@ export class CompileElement extends CompileNode {
|
|||||||
this.instances.set(resolveIdentifierToken(Identifiers.AppElement).reference, this.appElement);
|
this.instances.set(resolveIdentifierToken(Identifiers.AppElement).reference, this.appElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
public createComponentFactoryResolver(entryComponents: CompileIdentifierMetadata[]) {
|
private _createComponentFactoryResolver() {
|
||||||
|
let entryComponents =
|
||||||
|
this.component.entryComponents.map((entryComponent: CompileIdentifierMetadata) => {
|
||||||
|
var id = new CompileIdentifierMetadata({name: entryComponent.name});
|
||||||
|
this._targetDependencies.push(new ComponentFactoryDependency(entryComponent, id));
|
||||||
|
return id;
|
||||||
|
});
|
||||||
if (!entryComponents || entryComponents.length === 0) {
|
if (!entryComponents || entryComponents.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -155,6 +169,8 @@ export class CompileElement extends CompileNode {
|
|||||||
// create all the provider instances, some in the view constructor,
|
// create all the provider instances, some in the view constructor,
|
||||||
// some as getters. We rely on the fact that they are already sorted topologically.
|
// some as getters. We rely on the fact that they are already sorted topologically.
|
||||||
MapWrapper.values(this._resolvedProviders).forEach((resolvedProvider) => {
|
MapWrapper.values(this._resolvedProviders).forEach((resolvedProvider) => {
|
||||||
|
const isDirectiveWrapper = resolvedProvider.providerType === ProviderAstType.Component ||
|
||||||
|
resolvedProvider.providerType === ProviderAstType.Directive;
|
||||||
var providerValueExpressions = resolvedProvider.providers.map((provider) => {
|
var providerValueExpressions = resolvedProvider.providers.map((provider) => {
|
||||||
if (isPresent(provider.useExisting)) {
|
if (isPresent(provider.useExisting)) {
|
||||||
return this._getDependency(
|
return this._getDependency(
|
||||||
@ -167,8 +183,17 @@ export class CompileElement extends CompileNode {
|
|||||||
} else if (isPresent(provider.useClass)) {
|
} else if (isPresent(provider.useClass)) {
|
||||||
var deps = provider.deps || provider.useClass.diDeps;
|
var deps = provider.deps || provider.useClass.diDeps;
|
||||||
var depsExpr = deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep));
|
var depsExpr = deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep));
|
||||||
return o.importExpr(provider.useClass)
|
if (isDirectiveWrapper) {
|
||||||
.instantiate(depsExpr, o.importType(provider.useClass));
|
const directiveWrapperIdentifier = new CompileIdentifierMetadata(
|
||||||
|
{name: DirectiveWrapperCompiler.dirWrapperClassName(provider.useClass)});
|
||||||
|
this._targetDependencies.push(
|
||||||
|
new DirectiveWrapperDependency(provider.useClass, directiveWrapperIdentifier));
|
||||||
|
return o.importExpr(directiveWrapperIdentifier)
|
||||||
|
.instantiate(depsExpr, o.importType(directiveWrapperIdentifier));
|
||||||
|
} else {
|
||||||
|
return o.importExpr(provider.useClass)
|
||||||
|
.instantiate(depsExpr, o.importType(provider.useClass));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return convertValueToOutputAst(provider.useValue);
|
return convertValueToOutputAst(provider.useValue);
|
||||||
}
|
}
|
||||||
@ -177,7 +202,12 @@ export class CompileElement extends CompileNode {
|
|||||||
var instance = createProviderProperty(
|
var instance = createProviderProperty(
|
||||||
propName, resolvedProvider, providerValueExpressions, resolvedProvider.multiProvider,
|
propName, resolvedProvider, providerValueExpressions, resolvedProvider.multiProvider,
|
||||||
resolvedProvider.eager, this);
|
resolvedProvider.eager, this);
|
||||||
this.instances.set(resolvedProvider.token.reference, instance);
|
if (isDirectiveWrapper) {
|
||||||
|
this.directiveWrapperInstance.set(resolvedProvider.token.reference, instance);
|
||||||
|
this.instances.set(resolvedProvider.token.reference, instance.prop('context'));
|
||||||
|
} else {
|
||||||
|
this.instances.set(resolvedProvider.token.reference, instance);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (var i = 0; i < this._directives.length; i++) {
|
for (var i = 0; i < this._directives.length; i++) {
|
||||||
|
24
modules/@angular/compiler/src/view_compiler/deps.ts
Normal file
24
modules/@angular/compiler/src/view_compiler/deps.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* @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 {CompileIdentifierMetadata} from '../compile_metadata';
|
||||||
|
|
||||||
|
export class ViewFactoryDependency {
|
||||||
|
constructor(
|
||||||
|
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ComponentFactoryDependency {
|
||||||
|
constructor(
|
||||||
|
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DirectiveWrapperDependency {
|
||||||
|
constructor(
|
||||||
|
public dir: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
|
||||||
|
}
|
@ -20,27 +20,6 @@ import {DetectChangesVars} from './constants';
|
|||||||
var STATE_IS_NEVER_CHECKED = o.THIS_EXPR.prop('numberOfChecks').identical(new o.LiteralExpr(0));
|
var STATE_IS_NEVER_CHECKED = o.THIS_EXPR.prop('numberOfChecks').identical(new o.LiteralExpr(0));
|
||||||
var NOT_THROW_ON_CHANGES = o.not(DetectChangesVars.throwOnChange);
|
var NOT_THROW_ON_CHANGES = o.not(DetectChangesVars.throwOnChange);
|
||||||
|
|
||||||
export function bindDirectiveDetectChangesLifecycleCallbacks(
|
|
||||||
directiveAst: DirectiveAst, directiveInstance: o.Expression, compileElement: CompileElement) {
|
|
||||||
var view = compileElement.view;
|
|
||||||
var detectChangesInInputsMethod = view.detectChangesInInputsMethod;
|
|
||||||
var lifecycleHooks = directiveAst.directive.type.lifecycleHooks;
|
|
||||||
if (lifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1 && directiveAst.inputs.length > 0) {
|
|
||||||
detectChangesInInputsMethod.addStmt(new o.IfStmt(
|
|
||||||
DetectChangesVars.changes.notIdentical(o.NULL_EXPR),
|
|
||||||
[directiveInstance.callMethod('ngOnChanges', [DetectChangesVars.changes]).toStmt()]));
|
|
||||||
}
|
|
||||||
if (lifecycleHooks.indexOf(LifecycleHooks.OnInit) !== -1) {
|
|
||||||
detectChangesInInputsMethod.addStmt(new o.IfStmt(
|
|
||||||
STATE_IS_NEVER_CHECKED.and(NOT_THROW_ON_CHANGES),
|
|
||||||
[directiveInstance.callMethod('ngOnInit', []).toStmt()]));
|
|
||||||
}
|
|
||||||
if (lifecycleHooks.indexOf(LifecycleHooks.DoCheck) !== -1) {
|
|
||||||
detectChangesInInputsMethod.addStmt(new o.IfStmt(
|
|
||||||
NOT_THROW_ON_CHANGES, [directiveInstance.callMethod('ngDoCheck', []).toStmt()]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function bindDirectiveAfterContentLifecycleCallbacks(
|
export function bindDirectiveAfterContentLifecycleCallbacks(
|
||||||
directiveMeta: CompileDirectiveMetadata, directiveInstance: o.Expression,
|
directiveMeta: CompileDirectiveMetadata, directiveInstance: o.Expression,
|
||||||
compileElement: CompileElement) {
|
compileElement: CompileElement) {
|
||||||
|
@ -32,15 +32,18 @@ function createCurrValueExpr(exprIndex: number): o.ReadVarExpr {
|
|||||||
return o.variable(`currVal_${exprIndex}`); // fix syntax highlighting: `
|
return o.variable(`currVal_${exprIndex}`); // fix syntax highlighting: `
|
||||||
}
|
}
|
||||||
|
|
||||||
function bind(
|
class EvalResult {
|
||||||
view: CompileView, currValExpr: o.ReadVarExpr, fieldExpr: o.ReadPropExpr,
|
constructor(public forceUpdate: o.Expression) {}
|
||||||
parsedExpression: cdAst.AST, context: o.Expression, actions: o.Statement[],
|
}
|
||||||
method: CompileMethod, bindingIndex: number) {
|
|
||||||
|
function evalCdAst(
|
||||||
|
view: CompileView, currValExpr: o.ReadVarExpr, parsedExpression: cdAst.AST,
|
||||||
|
context: o.Expression, method: CompileMethod, bindingIndex: number): EvalResult {
|
||||||
var checkExpression = convertCdExpressionToIr(
|
var checkExpression = convertCdExpressionToIr(
|
||||||
view, context, parsedExpression, DetectChangesVars.valUnwrapper, bindingIndex);
|
view, context, parsedExpression, DetectChangesVars.valUnwrapper, bindingIndex);
|
||||||
if (!checkExpression.expression) {
|
if (!checkExpression.expression) {
|
||||||
// e.g. an empty expression was given
|
// e.g. an empty expression was given
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkExpression.temporaryCount) {
|
if (checkExpression.temporaryCount) {
|
||||||
@ -49,24 +52,39 @@ function bind(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private is fine here as no child view will reference the cached value...
|
|
||||||
view.fields.push(new o.ClassField(fieldExpr.name, null, [o.StmtModifier.Private]));
|
|
||||||
view.createMethod.addStmt(o.THIS_EXPR.prop(fieldExpr.name)
|
|
||||||
.set(o.importExpr(resolveIdentifier(Identifiers.UNINITIALIZED)))
|
|
||||||
.toStmt());
|
|
||||||
|
|
||||||
if (checkExpression.needsValueUnwrapper) {
|
if (checkExpression.needsValueUnwrapper) {
|
||||||
var initValueUnwrapperStmt = DetectChangesVars.valUnwrapper.callMethod('reset', []).toStmt();
|
var initValueUnwrapperStmt = DetectChangesVars.valUnwrapper.callMethod('reset', []).toStmt();
|
||||||
method.addStmt(initValueUnwrapperStmt);
|
method.addStmt(initValueUnwrapperStmt);
|
||||||
}
|
}
|
||||||
method.addStmt(
|
method.addStmt(
|
||||||
currValExpr.set(checkExpression.expression).toDeclStmt(null, [o.StmtModifier.Final]));
|
currValExpr.set(checkExpression.expression).toDeclStmt(null, [o.StmtModifier.Final]));
|
||||||
|
if (checkExpression.needsValueUnwrapper) {
|
||||||
|
return new EvalResult(DetectChangesVars.valUnwrapper.prop('hasWrappedValue'));
|
||||||
|
} else {
|
||||||
|
return new EvalResult(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function bind(
|
||||||
|
view: CompileView, currValExpr: o.ReadVarExpr, fieldExpr: o.ReadPropExpr,
|
||||||
|
parsedExpression: cdAst.AST, context: o.Expression, actions: o.Statement[],
|
||||||
|
method: CompileMethod, bindingIndex: number) {
|
||||||
|
const evalResult = evalCdAst(view, currValExpr, parsedExpression, context, method, bindingIndex);
|
||||||
|
if (!evalResult) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private is fine here as no child view will reference the cached value...
|
||||||
|
view.fields.push(new o.ClassField(fieldExpr.name, null, [o.StmtModifier.Private]));
|
||||||
|
view.createMethod.addStmt(o.THIS_EXPR.prop(fieldExpr.name)
|
||||||
|
.set(o.importExpr(resolveIdentifier(Identifiers.UNINITIALIZED)))
|
||||||
|
.toStmt());
|
||||||
|
|
||||||
var condition: o.Expression = o.importExpr(resolveIdentifier(Identifiers.checkBinding)).callFn([
|
var condition: o.Expression = o.importExpr(resolveIdentifier(Identifiers.checkBinding)).callFn([
|
||||||
DetectChangesVars.throwOnChange, fieldExpr, currValExpr
|
DetectChangesVars.throwOnChange, fieldExpr, currValExpr
|
||||||
]);
|
]);
|
||||||
if (checkExpression.needsValueUnwrapper) {
|
if (evalResult.forceUpdate) {
|
||||||
condition = DetectChangesVars.valUnwrapper.prop('hasWrappedValue').or(condition);
|
condition = evalResult.forceUpdate.or(condition);
|
||||||
}
|
}
|
||||||
method.addStmt(new o.IfStmt(
|
method.addStmt(new o.IfStmt(
|
||||||
condition,
|
condition,
|
||||||
@ -237,82 +255,48 @@ export function bindDirectiveHostProps(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function bindDirectiveInputs(
|
export function bindDirectiveInputs(
|
||||||
directiveAst: DirectiveAst, directiveInstance: o.Expression, compileElement: CompileElement) {
|
directiveAst: DirectiveAst, directiveWrapperInstance: o.Expression,
|
||||||
if (directiveAst.inputs.length === 0) {
|
compileElement: CompileElement) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
var view = compileElement.view;
|
var view = compileElement.view;
|
||||||
var detectChangesInInputsMethod = view.detectChangesInInputsMethod;
|
var detectChangesInInputsMethod = view.detectChangesInInputsMethod;
|
||||||
detectChangesInInputsMethod.resetDebugInfo(compileElement.nodeIndex, compileElement.sourceAst);
|
detectChangesInInputsMethod.resetDebugInfo(compileElement.nodeIndex, compileElement.sourceAst);
|
||||||
|
|
||||||
var lifecycleHooks = directiveAst.directive.type.lifecycleHooks;
|
|
||||||
var calcChangesMap = lifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1;
|
|
||||||
var isOnPushComp = directiveAst.directive.isComponent &&
|
|
||||||
!isDefaultChangeDetectionStrategy(directiveAst.directive.changeDetection);
|
|
||||||
if (calcChangesMap) {
|
|
||||||
detectChangesInInputsMethod.addStmt(DetectChangesVars.changes.set(o.NULL_EXPR).toStmt());
|
|
||||||
}
|
|
||||||
if (isOnPushComp) {
|
|
||||||
detectChangesInInputsMethod.addStmt(DetectChangesVars.changed.set(o.literal(false)).toStmt());
|
|
||||||
}
|
|
||||||
directiveAst.inputs.forEach((input) => {
|
directiveAst.inputs.forEach((input) => {
|
||||||
var bindingIndex = view.bindings.length;
|
var bindingIndex = view.bindings.length;
|
||||||
view.bindings.push(new CompileBinding(compileElement, input));
|
view.bindings.push(new CompileBinding(compileElement, input));
|
||||||
detectChangesInInputsMethod.resetDebugInfo(compileElement.nodeIndex, input);
|
detectChangesInInputsMethod.resetDebugInfo(compileElement.nodeIndex, input);
|
||||||
var fieldExpr = createBindFieldExpr(bindingIndex);
|
|
||||||
var currValExpr = createCurrValueExpr(bindingIndex);
|
var currValExpr = createCurrValueExpr(bindingIndex);
|
||||||
var statements: o.Statement[] =
|
const evalResult = evalCdAst(
|
||||||
[directiveInstance.prop(input.directiveName).set(currValExpr).toStmt()];
|
view, currValExpr, input.value, view.componentContext, detectChangesInInputsMethod,
|
||||||
if (calcChangesMap) {
|
bindingIndex);
|
||||||
statements.push(new o.IfStmt(
|
if (!evalResult) {
|
||||||
DetectChangesVars.changes.identical(o.NULL_EXPR),
|
return;
|
||||||
[DetectChangesVars.changes
|
|
||||||
.set(o.literalMap(
|
|
||||||
[], new o.MapType(o.importType(resolveIdentifier(Identifiers.SimpleChange)))))
|
|
||||||
.toStmt()]));
|
|
||||||
statements.push(DetectChangesVars.changes.key(o.literal(input.directiveName))
|
|
||||||
.set(o.importExpr(resolveIdentifier(Identifiers.SimpleChange))
|
|
||||||
.instantiate([fieldExpr, currValExpr]))
|
|
||||||
.toStmt());
|
|
||||||
}
|
}
|
||||||
if (isOnPushComp) {
|
detectChangesInInputsMethod.addStmt(directiveWrapperInstance
|
||||||
statements.push(DetectChangesVars.changed.set(o.literal(true)).toStmt());
|
.callMethod(
|
||||||
}
|
`check_${input.directiveName}`,
|
||||||
if (view.genConfig.logBindingUpdate) {
|
[
|
||||||
statements.push(
|
currValExpr, DetectChangesVars.throwOnChange,
|
||||||
logBindingUpdateStmt(compileElement.renderNode, input.directiveName, currValExpr));
|
evalResult.forceUpdate || o.literal(false)
|
||||||
}
|
])
|
||||||
bind(
|
.toStmt());
|
||||||
view, currValExpr, fieldExpr, input.value, view.componentContext, statements,
|
|
||||||
detectChangesInInputsMethod, bindingIndex);
|
|
||||||
});
|
});
|
||||||
if (isOnPushComp) {
|
var isOnPushComp = directiveAst.directive.isComponent &&
|
||||||
detectChangesInInputsMethod.addStmt(new o.IfStmt(DetectChangesVars.changed, [
|
!isDefaultChangeDetectionStrategy(directiveAst.directive.changeDetection);
|
||||||
compileElement.appElement.prop('componentView').callMethod('markAsCheckOnce', []).toStmt()
|
let directiveDetectChangesExpr = directiveWrapperInstance.callMethod(
|
||||||
]));
|
'detectChangesInternal',
|
||||||
}
|
[o.THIS_EXPR, compileElement.renderNode, DetectChangesVars.throwOnChange]);
|
||||||
|
const directiveDetectChangesStmt = isOnPushComp ?
|
||||||
|
new o.IfStmt(directiveDetectChangesExpr, [compileElement.appElement.prop('componentView')
|
||||||
|
.callMethod('markAsCheckOnce', [])
|
||||||
|
.toStmt()]) :
|
||||||
|
directiveDetectChangesExpr.toStmt();
|
||||||
|
detectChangesInInputsMethod.addStmt(directiveDetectChangesStmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
function logBindingUpdateStmt(
|
function logBindingUpdateStmt(
|
||||||
renderNode: o.Expression, propName: string, value: o.Expression): o.Statement {
|
renderNode: o.Expression, propName: string, value: o.Expression): o.Statement {
|
||||||
const tryStmt =
|
return o.importExpr(resolveIdentifier(Identifiers.setBindingDebugInfo))
|
||||||
o.THIS_EXPR.prop('renderer')
|
.callFn([o.THIS_EXPR.prop('renderer'), renderNode, o.literal(propName), value])
|
||||||
.callMethod(
|
.toStmt();
|
||||||
'setBindingDebugInfo',
|
|
||||||
[
|
|
||||||
renderNode, o.literal(`ng-reflect-${camelCaseToDashCase(propName)}`),
|
|
||||||
value.isBlank().conditional(o.NULL_EXPR, value.callMethod('toString', []))
|
|
||||||
])
|
|
||||||
.toStmt();
|
|
||||||
|
|
||||||
const catchStmt = o.THIS_EXPR.prop('renderer')
|
|
||||||
.callMethod(
|
|
||||||
'setBindingDebugInfo',
|
|
||||||
[
|
|
||||||
renderNode, o.literal(`ng-reflect-${camelCaseToDashCase(propName)}`),
|
|
||||||
o.literal('[ERROR] Exception while trying to serialize the value')
|
|
||||||
])
|
|
||||||
.toStmt();
|
|
||||||
|
|
||||||
return new o.TryCatchStmt([tryStmt], [catchStmt]);
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import {CompileDirectiveMetadata, CompileTokenMetadata} from '../compile_metadata';
|
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileTokenMetadata} from '../compile_metadata';
|
||||||
import {isPresent} from '../facade/lang';
|
import {isPresent} from '../facade/lang';
|
||||||
import {Identifiers, resolveIdentifier} from '../identifiers';
|
import {Identifiers, resolveIdentifier} from '../identifiers';
|
||||||
import * as o from '../output/output_ast';
|
import * as o from '../output/output_ast';
|
||||||
@ -30,15 +30,28 @@ export function getPropertyInView(
|
|||||||
throw new Error(
|
throw new Error(
|
||||||
`Internal error: Could not calculate a property in a parent view: ${property}`);
|
`Internal error: Could not calculate a property in a parent view: ${property}`);
|
||||||
}
|
}
|
||||||
if (property instanceof o.ReadPropExpr) {
|
return property.visitExpression(new _ReplaceViewTransformer(viewProp, definedView), null);
|
||||||
let readPropExpr: o.ReadPropExpr = property;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ReplaceViewTransformer extends o.ExpressionTransformer {
|
||||||
|
constructor(private _viewExpr: o.Expression, private _view: CompileView) { super(); }
|
||||||
|
private _isThis(expr: o.Expression): boolean {
|
||||||
|
return expr instanceof o.ReadVarExpr && expr.builtin === o.BuiltinVar.This;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitReadVarExpr(ast: o.ReadVarExpr, context: any): any {
|
||||||
|
return this._isThis(ast) ? this._viewExpr : ast;
|
||||||
|
}
|
||||||
|
visitReadPropExpr(ast: o.ReadPropExpr, context: any): any {
|
||||||
|
if (this._isThis(ast.receiver)) {
|
||||||
// Note: Don't cast for members of the AppView base class...
|
// Note: Don't cast for members of the AppView base class...
|
||||||
if (definedView.fields.some((field) => field.name == readPropExpr.name) ||
|
if (this._view.fields.some((field) => field.name == ast.name) ||
|
||||||
definedView.getters.some((field) => field.name == readPropExpr.name)) {
|
this._view.getters.some((field) => field.name == ast.name)) {
|
||||||
viewProp = viewProp.cast(definedView.classType);
|
return this._viewExpr.cast(this._view.classType).prop(ast.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return o.replaceVarInExpression(o.THIS_EXPR.name, viewProp, property);
|
return super.visitReadPropExpr(ast, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventA
|
|||||||
import {CompileElement} from './compile_element';
|
import {CompileElement} from './compile_element';
|
||||||
import {CompileView} from './compile_view';
|
import {CompileView} from './compile_view';
|
||||||
import {CompileEventListener, bindDirectiveOutputs, bindRenderOutputs, collectEventListeners} from './event_binder';
|
import {CompileEventListener, bindDirectiveOutputs, bindRenderOutputs, collectEventListeners} from './event_binder';
|
||||||
import {bindDirectiveAfterContentLifecycleCallbacks, bindDirectiveAfterViewLifecycleCallbacks, bindDirectiveDetectChangesLifecycleCallbacks, bindInjectableDestroyLifecycleCallbacks, bindPipeDestroyLifecycleCallbacks} from './lifecycle_binder';
|
import {bindDirectiveAfterContentLifecycleCallbacks, bindDirectiveAfterViewLifecycleCallbacks, bindInjectableDestroyLifecycleCallbacks, bindPipeDestroyLifecycleCallbacks} from './lifecycle_binder';
|
||||||
import {bindDirectiveHostProps, bindDirectiveInputs, bindRenderInputs, bindRenderText} from './property_binder';
|
import {bindDirectiveHostProps, bindDirectiveInputs, bindRenderInputs, bindRenderText} from './property_binder';
|
||||||
|
|
||||||
export function bindView(view: CompileView, parsedTemplate: TemplateAst[]): void {
|
export function bindView(view: CompileView, parsedTemplate: TemplateAst[]): void {
|
||||||
@ -48,8 +48,9 @@ class ViewBinderVisitor implements TemplateAstVisitor {
|
|||||||
bindRenderOutputs(eventListeners);
|
bindRenderOutputs(eventListeners);
|
||||||
ast.directives.forEach((directiveAst) => {
|
ast.directives.forEach((directiveAst) => {
|
||||||
var directiveInstance = compileElement.instances.get(directiveAst.directive.type.reference);
|
var directiveInstance = compileElement.instances.get(directiveAst.directive.type.reference);
|
||||||
bindDirectiveInputs(directiveAst, directiveInstance, compileElement);
|
var directiveWrapperInstance =
|
||||||
bindDirectiveDetectChangesLifecycleCallbacks(directiveAst, directiveInstance, compileElement);
|
compileElement.directiveWrapperInstance.get(directiveAst.directive.type.reference);
|
||||||
|
bindDirectiveInputs(directiveAst, directiveWrapperInstance, compileElement);
|
||||||
|
|
||||||
bindDirectiveHostProps(directiveAst, directiveInstance, compileElement, eventListeners);
|
bindDirectiveHostProps(directiveAst, directiveInstance, compileElement, eventListeners);
|
||||||
bindDirectiveOutputs(directiveAst, directiveInstance, eventListeners);
|
bindDirectiveOutputs(directiveAst, directiveInstance, eventListeners);
|
||||||
@ -76,8 +77,10 @@ class ViewBinderVisitor implements TemplateAstVisitor {
|
|||||||
var eventListeners = collectEventListeners(ast.outputs, ast.directives, compileElement);
|
var eventListeners = collectEventListeners(ast.outputs, ast.directives, compileElement);
|
||||||
ast.directives.forEach((directiveAst) => {
|
ast.directives.forEach((directiveAst) => {
|
||||||
var directiveInstance = compileElement.instances.get(directiveAst.directive.type.reference);
|
var directiveInstance = compileElement.instances.get(directiveAst.directive.type.reference);
|
||||||
bindDirectiveInputs(directiveAst, directiveInstance, compileElement);
|
var directiveWrapperInstance =
|
||||||
bindDirectiveDetectChangesLifecycleCallbacks(directiveAst, directiveInstance, compileElement);
|
compileElement.directiveWrapperInstance.get(directiveAst.directive.type.reference);
|
||||||
|
bindDirectiveInputs(directiveAst, directiveWrapperInstance, compileElement);
|
||||||
|
|
||||||
bindDirectiveOutputs(directiveAst, directiveInstance, eventListeners);
|
bindDirectiveOutputs(directiveAst, directiveInstance, eventListeners);
|
||||||
bindDirectiveAfterContentLifecycleCallbacks(
|
bindDirectiveAfterContentLifecycleCallbacks(
|
||||||
directiveAst.directive, directiveInstance, compileElement);
|
directiveAst.directive, directiveInstance, compileElement);
|
||||||
|
@ -20,6 +20,7 @@ import {createDiTokenExpression} from '../util';
|
|||||||
import {CompileElement, CompileNode} from './compile_element';
|
import {CompileElement, CompileNode} from './compile_element';
|
||||||
import {CompileView} from './compile_view';
|
import {CompileView} from './compile_view';
|
||||||
import {ChangeDetectorStatusEnum, DetectChangesVars, InjectMethodVars, ViewConstructorVars, ViewEncapsulationEnum, ViewProperties, ViewTypeEnum} from './constants';
|
import {ChangeDetectorStatusEnum, DetectChangesVars, InjectMethodVars, ViewConstructorVars, ViewEncapsulationEnum, ViewProperties, ViewTypeEnum} from './constants';
|
||||||
|
import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewFactoryDependency} from './deps';
|
||||||
import {createFlatArray, getViewFactoryName} from './util';
|
import {createFlatArray, getViewFactoryName} from './util';
|
||||||
|
|
||||||
const IMPLICIT_TEMPLATE_VAR = '\$implicit';
|
const IMPLICIT_TEMPLATE_VAR = '\$implicit';
|
||||||
@ -30,20 +31,11 @@ const NG_CONTAINER_TAG = 'ng-container';
|
|||||||
var parentRenderNodeVar = o.variable('parentRenderNode');
|
var parentRenderNodeVar = o.variable('parentRenderNode');
|
||||||
var rootSelectorVar = o.variable('rootSelector');
|
var rootSelectorVar = o.variable('rootSelector');
|
||||||
|
|
||||||
export class ViewFactoryDependency {
|
|
||||||
constructor(
|
|
||||||
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ComponentFactoryDependency {
|
|
||||||
constructor(
|
|
||||||
public comp: CompileIdentifierMetadata, public placeholder: CompileIdentifierMetadata) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function buildView(
|
export function buildView(
|
||||||
view: CompileView, template: TemplateAst[],
|
view: CompileView, template: TemplateAst[],
|
||||||
targetDependencies: Array<ViewFactoryDependency|ComponentFactoryDependency>): number {
|
targetDependencies:
|
||||||
|
Array<ViewFactoryDependency|ComponentFactoryDependency|DirectiveWrapperDependency>):
|
||||||
|
number {
|
||||||
var builderVisitor = new ViewBuilderVisitor(view, targetDependencies);
|
var builderVisitor = new ViewBuilderVisitor(view, targetDependencies);
|
||||||
templateVisitAll(
|
templateVisitAll(
|
||||||
builderVisitor, template,
|
builderVisitor, template,
|
||||||
@ -66,7 +58,8 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public view: CompileView,
|
public view: CompileView,
|
||||||
public targetDependencies: Array<ViewFactoryDependency|ComponentFactoryDependency>) {}
|
public targetDependencies:
|
||||||
|
Array<ViewFactoryDependency|ComponentFactoryDependency|DirectiveWrapperDependency>) {}
|
||||||
|
|
||||||
private _isRootNode(parent: CompileElement): boolean { return parent.view !== this.view; }
|
private _isRootNode(parent: CompileElement): boolean { return parent.view !== this.view; }
|
||||||
|
|
||||||
@ -204,7 +197,7 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
|
|||||||
}
|
}
|
||||||
var compileElement = new CompileElement(
|
var compileElement = new CompileElement(
|
||||||
parent, this.view, nodeIndex, renderNode, ast, component, directives, ast.providers,
|
parent, this.view, nodeIndex, renderNode, ast, component, directives, ast.providers,
|
||||||
ast.hasViewContainer, false, ast.references);
|
ast.hasViewContainer, false, ast.references, this.targetDependencies);
|
||||||
this.view.nodes.push(compileElement);
|
this.view.nodes.push(compileElement);
|
||||||
var compViewExpr: o.ReadVarExpr = null;
|
var compViewExpr: o.ReadVarExpr = null;
|
||||||
if (isPresent(component)) {
|
if (isPresent(component)) {
|
||||||
@ -212,13 +205,6 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
|
|||||||
new CompileIdentifierMetadata({name: getViewFactoryName(component, 0)});
|
new CompileIdentifierMetadata({name: getViewFactoryName(component, 0)});
|
||||||
this.targetDependencies.push(
|
this.targetDependencies.push(
|
||||||
new ViewFactoryDependency(component.type, nestedComponentIdentifier));
|
new ViewFactoryDependency(component.type, nestedComponentIdentifier));
|
||||||
let entryComponentIdentifiers =
|
|
||||||
component.entryComponents.map((entryComponent: CompileIdentifierMetadata) => {
|
|
||||||
var id = new CompileIdentifierMetadata({name: entryComponent.name});
|
|
||||||
this.targetDependencies.push(new ComponentFactoryDependency(entryComponent, id));
|
|
||||||
return id;
|
|
||||||
});
|
|
||||||
compileElement.createComponentFactoryResolver(entryComponentIdentifiers);
|
|
||||||
|
|
||||||
compViewExpr = o.variable(`compView_${nodeIndex}`); // fix highlighting: `
|
compViewExpr = o.variable(`compView_${nodeIndex}`); // fix highlighting: `
|
||||||
compileElement.setComponentView(compViewExpr);
|
compileElement.setComponentView(compViewExpr);
|
||||||
@ -273,7 +259,7 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
|
|||||||
var directives = ast.directives.map(directiveAst => directiveAst.directive);
|
var directives = ast.directives.map(directiveAst => directiveAst.directive);
|
||||||
var compileElement = new CompileElement(
|
var compileElement = new CompileElement(
|
||||||
parent, this.view, nodeIndex, renderNode, ast, null, directives, ast.providers,
|
parent, this.view, nodeIndex, renderNode, ast, null, directives, ast.providers,
|
||||||
ast.hasViewContainer, true, ast.references);
|
ast.hasViewContainer, true, ast.references, this.targetDependencies);
|
||||||
this.view.nodes.push(compileElement);
|
this.view.nodes.push(compileElement);
|
||||||
|
|
||||||
this.nestedViewCount++;
|
this.nestedViewCount++;
|
||||||
|
@ -16,15 +16,17 @@ import {TemplateAst} from '../template_parser/template_ast';
|
|||||||
|
|
||||||
import {CompileElement} from './compile_element';
|
import {CompileElement} from './compile_element';
|
||||||
import {CompileView} from './compile_view';
|
import {CompileView} from './compile_view';
|
||||||
|
import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewFactoryDependency} from './deps';
|
||||||
import {bindView} from './view_binder';
|
import {bindView} from './view_binder';
|
||||||
import {ComponentFactoryDependency, ViewFactoryDependency, buildView, finishView} from './view_builder';
|
import {buildView, finishView} from './view_builder';
|
||||||
|
|
||||||
export {ComponentFactoryDependency, ViewFactoryDependency} from './view_builder';
|
export {ComponentFactoryDependency, DirectiveWrapperDependency, ViewFactoryDependency} from './deps';
|
||||||
|
|
||||||
export class ViewCompileResult {
|
export class ViewCompileResult {
|
||||||
constructor(
|
constructor(
|
||||||
public statements: o.Statement[], public viewFactoryVar: string,
|
public statements: o.Statement[], public viewFactoryVar: string,
|
||||||
public dependencies: Array<ViewFactoryDependency|ComponentFactoryDependency>) {}
|
public dependencies:
|
||||||
|
Array<ViewFactoryDependency|ComponentFactoryDependency|DirectiveWrapperDependency>) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -35,7 +37,8 @@ export class ViewCompiler {
|
|||||||
component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression,
|
component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression,
|
||||||
pipes: CompilePipeMetadata[],
|
pipes: CompilePipeMetadata[],
|
||||||
compiledAnimations: AnimationEntryCompileResult[]): ViewCompileResult {
|
compiledAnimations: AnimationEntryCompileResult[]): ViewCompileResult {
|
||||||
const dependencies: Array<ViewFactoryDependency|ComponentFactoryDependency> = [];
|
const dependencies:
|
||||||
|
Array<ViewFactoryDependency|ComponentFactoryDependency|DirectiveWrapperDependency> = [];
|
||||||
const view = new CompileView(
|
const view = new CompileView(
|
||||||
component, this._genConfig, pipes, styles, compiledAnimations, 0,
|
component, this._genConfig, pipes, styles, compiledAnimations, 0,
|
||||||
CompileElement.createNull(), []);
|
CompileElement.createNull(), []);
|
||||||
|
65
modules/@angular/compiler/test/view_compiler/util_spec.ts
Normal file
65
modules/@angular/compiler/test/view_compiler/util_spec.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* @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 {CompileIdentifierMetadata} from '../../src/compile_metadata';
|
||||||
|
import * as o from '../../src/output/output_ast';
|
||||||
|
import {CompileView} from '../../src/view_compiler/compile_view';
|
||||||
|
import {getPropertyInView} from '../../src/view_compiler/util';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('getPropertyInView', () => {
|
||||||
|
it('should return the expression if it is the same view', () => {
|
||||||
|
const expr = o.THIS_EXPR.prop('someProp');
|
||||||
|
const callingView = createCompileView({className: 'view'});
|
||||||
|
expect(getPropertyInView(expr, callingView, callingView)).toBe(expr);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should access an unknown property in a parent view', () => {
|
||||||
|
const expr = o.THIS_EXPR.prop('someProp');
|
||||||
|
const definedView = createCompileView({className: 'parentView'});
|
||||||
|
const callingView = createCompileView({className: 'childView', parent: definedView});
|
||||||
|
expect(getPropertyInView(expr, callingView, definedView))
|
||||||
|
.toEqual(o.THIS_EXPR.prop('parent').prop('someProp'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should access a known property in a parent view with cast', () => {
|
||||||
|
const expr = o.THIS_EXPR.prop('someProp');
|
||||||
|
const definedView = createCompileView({className: 'parentView', fields: ['someProp']});
|
||||||
|
const callingView = createCompileView({className: 'childView', parent: definedView});
|
||||||
|
expect(getPropertyInView(expr, callingView, definedView))
|
||||||
|
.toEqual(o.THIS_EXPR.prop('parent').cast(definedView.classType).prop('someProp'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should access a known property in a parent view with cast also for property chain expressions',
|
||||||
|
() => {
|
||||||
|
const expr = o.THIS_EXPR.prop('someProp').prop('context');
|
||||||
|
const definedView = createCompileView({className: 'parentView', fields: ['someProp']});
|
||||||
|
const callingView = createCompileView({className: 'childView', parent: definedView});
|
||||||
|
expect(getPropertyInView(expr, callingView, definedView))
|
||||||
|
.toEqual(o.THIS_EXPR.prop('parent')
|
||||||
|
.cast(definedView.classType)
|
||||||
|
.prop('someProp')
|
||||||
|
.prop('context'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCompileView(config: {className: string, parent?: CompileView, fields?: string[]}):
|
||||||
|
CompileView {
|
||||||
|
const declarationElement: any = config.parent ? {view: config.parent} : {view: null};
|
||||||
|
const fields: o.ClassField[] = [];
|
||||||
|
if (config.fields) {
|
||||||
|
config.fields.forEach((fieldName) => { fields.push(new o.ClassField(fieldName)); });
|
||||||
|
}
|
||||||
|
return <any>{
|
||||||
|
classType: o.importType(new CompileIdentifierMetadata({name: config.className})),
|
||||||
|
fields: fields,
|
||||||
|
getters: [],
|
||||||
|
declarationElement: declarationElement
|
||||||
|
};
|
||||||
|
}
|
@ -64,11 +64,6 @@ export var __core_private__: {
|
|||||||
_NgModuleInjector?: ng_module_factory.NgModuleInjector<any>,
|
_NgModuleInjector?: ng_module_factory.NgModuleInjector<any>,
|
||||||
registerModuleFactory: typeof ng_module_factory_loader.registerModuleFactory,
|
registerModuleFactory: typeof ng_module_factory_loader.registerModuleFactory,
|
||||||
ViewType: typeof view_type.ViewType, _ViewType?: view_type.ViewType,
|
ViewType: typeof view_type.ViewType, _ViewType?: view_type.ViewType,
|
||||||
MAX_INTERPOLATION_VALUES: typeof view_utils.MAX_INTERPOLATION_VALUES,
|
|
||||||
checkBinding: typeof view_utils.checkBinding,
|
|
||||||
flattenNestedViewRenderNodes: typeof view_utils.flattenNestedViewRenderNodes,
|
|
||||||
interpolate: typeof view_utils.interpolate,
|
|
||||||
ViewUtils: typeof view_utils.ViewUtils, _ViewUtils?: view_utils.ViewUtils,
|
|
||||||
ViewMetadata: typeof metadata_view.ViewMetadata, _ViewMetadata?: metadata_view.ViewMetadata,
|
ViewMetadata: typeof metadata_view.ViewMetadata, _ViewMetadata?: metadata_view.ViewMetadata,
|
||||||
DebugContext: typeof debug_context.DebugContext, _DebugContext?: debug_context.DebugContext,
|
DebugContext: typeof debug_context.DebugContext, _DebugContext?: debug_context.DebugContext,
|
||||||
StaticNodeDebugInfo: typeof debug_context.StaticNodeDebugInfo,
|
StaticNodeDebugInfo: typeof debug_context.StaticNodeDebugInfo,
|
||||||
@ -84,19 +79,6 @@ export var __core_private__: {
|
|||||||
makeDecorator: typeof decorators.makeDecorator,
|
makeDecorator: typeof decorators.makeDecorator,
|
||||||
DebugDomRootRenderer: typeof debug.DebugDomRootRenderer,
|
DebugDomRootRenderer: typeof debug.DebugDomRootRenderer,
|
||||||
_DebugDomRootRenderer?: debug.DebugDomRootRenderer,
|
_DebugDomRootRenderer?: debug.DebugDomRootRenderer,
|
||||||
EMPTY_ARRAY: typeof view_utils.EMPTY_ARRAY,
|
|
||||||
EMPTY_MAP: typeof view_utils.EMPTY_MAP,
|
|
||||||
pureProxy1: typeof view_utils.pureProxy1,
|
|
||||||
pureProxy2: typeof view_utils.pureProxy2,
|
|
||||||
pureProxy3: typeof view_utils.pureProxy3,
|
|
||||||
pureProxy4: typeof view_utils.pureProxy4,
|
|
||||||
pureProxy5: typeof view_utils.pureProxy5,
|
|
||||||
pureProxy6: typeof view_utils.pureProxy6,
|
|
||||||
pureProxy7: typeof view_utils.pureProxy7,
|
|
||||||
pureProxy8: typeof view_utils.pureProxy8,
|
|
||||||
pureProxy9: typeof view_utils.pureProxy9,
|
|
||||||
pureProxy10: typeof view_utils.pureProxy10,
|
|
||||||
castByValue: typeof view_utils.castByValue,
|
|
||||||
Console: typeof console.Console, _Console?: console.Console,
|
Console: typeof console.Console, _Console?: console.Console,
|
||||||
reflector: typeof reflection.reflector,
|
reflector: typeof reflection.reflector,
|
||||||
Reflector: typeof reflection.Reflector, _Reflector?: reflection.Reflector,
|
Reflector: typeof reflection.Reflector, _Reflector?: reflection.Reflector,
|
||||||
@ -121,6 +103,7 @@ export var __core_private__: {
|
|||||||
ComponentStillLoadingError: typeof ComponentStillLoadingError,
|
ComponentStillLoadingError: typeof ComponentStillLoadingError,
|
||||||
isPromise: typeof isPromise,
|
isPromise: typeof isPromise,
|
||||||
AnimationTransition: typeof AnimationTransition
|
AnimationTransition: typeof AnimationTransition
|
||||||
|
view_utils: typeof view_utils,
|
||||||
} = {
|
} = {
|
||||||
isDefaultChangeDetectionStrategy: constants.isDefaultChangeDetectionStrategy,
|
isDefaultChangeDetectionStrategy: constants.isDefaultChangeDetectionStrategy,
|
||||||
ChangeDetectorStatus: constants.ChangeDetectorStatus,
|
ChangeDetectorStatus: constants.ChangeDetectorStatus,
|
||||||
@ -135,11 +118,7 @@ export var __core_private__: {
|
|||||||
NgModuleInjector: ng_module_factory.NgModuleInjector,
|
NgModuleInjector: ng_module_factory.NgModuleInjector,
|
||||||
registerModuleFactory: ng_module_factory_loader.registerModuleFactory,
|
registerModuleFactory: ng_module_factory_loader.registerModuleFactory,
|
||||||
ViewType: view_type.ViewType,
|
ViewType: view_type.ViewType,
|
||||||
MAX_INTERPOLATION_VALUES: view_utils.MAX_INTERPOLATION_VALUES,
|
view_utils: view_utils,
|
||||||
checkBinding: view_utils.checkBinding,
|
|
||||||
flattenNestedViewRenderNodes: view_utils.flattenNestedViewRenderNodes,
|
|
||||||
interpolate: view_utils.interpolate,
|
|
||||||
ViewUtils: view_utils.ViewUtils,
|
|
||||||
ViewMetadata: metadata_view.ViewMetadata,
|
ViewMetadata: metadata_view.ViewMetadata,
|
||||||
DebugContext: debug_context.DebugContext,
|
DebugContext: debug_context.DebugContext,
|
||||||
StaticNodeDebugInfo: debug_context.StaticNodeDebugInfo,
|
StaticNodeDebugInfo: debug_context.StaticNodeDebugInfo,
|
||||||
@ -151,19 +130,6 @@ export var __core_private__: {
|
|||||||
ReflectionCapabilities: reflection_capabilities.ReflectionCapabilities,
|
ReflectionCapabilities: reflection_capabilities.ReflectionCapabilities,
|
||||||
makeDecorator: decorators.makeDecorator,
|
makeDecorator: decorators.makeDecorator,
|
||||||
DebugDomRootRenderer: debug.DebugDomRootRenderer,
|
DebugDomRootRenderer: debug.DebugDomRootRenderer,
|
||||||
EMPTY_ARRAY: view_utils.EMPTY_ARRAY,
|
|
||||||
EMPTY_MAP: view_utils.EMPTY_MAP,
|
|
||||||
pureProxy1: view_utils.pureProxy1,
|
|
||||||
pureProxy2: view_utils.pureProxy2,
|
|
||||||
pureProxy3: view_utils.pureProxy3,
|
|
||||||
pureProxy4: view_utils.pureProxy4,
|
|
||||||
pureProxy5: view_utils.pureProxy5,
|
|
||||||
pureProxy6: view_utils.pureProxy6,
|
|
||||||
pureProxy7: view_utils.pureProxy7,
|
|
||||||
pureProxy8: view_utils.pureProxy8,
|
|
||||||
pureProxy9: view_utils.pureProxy9,
|
|
||||||
pureProxy10: view_utils.pureProxy10,
|
|
||||||
castByValue: view_utils.castByValue,
|
|
||||||
Console: console.Console,
|
Console: console.Console,
|
||||||
reflector: reflection.reflector,
|
reflector: reflection.reflector,
|
||||||
Reflector: reflection.Reflector,
|
Reflector: reflection.Reflector,
|
||||||
|
@ -7,13 +7,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {APP_ID} from '../application_tokens';
|
import {APP_ID} from '../application_tokens';
|
||||||
import {devModeEqual} from '../change_detection/change_detection';
|
import {SimpleChange, devModeEqual} from '../change_detection/change_detection';
|
||||||
import {UNINITIALIZED} from '../change_detection/change_detection_util';
|
import {UNINITIALIZED} from '../change_detection/change_detection_util';
|
||||||
import {Inject, Injectable} from '../di';
|
import {Inject, Injectable} from '../di';
|
||||||
import {isPresent, looseIdentical} from '../facade/lang';
|
import {isPresent, looseIdentical} from '../facade/lang';
|
||||||
import {ViewEncapsulation} from '../metadata/view';
|
import {ViewEncapsulation} from '../metadata/view';
|
||||||
import {RenderComponentType, Renderer, RootRenderer} from '../render/api';
|
import {RenderComponentType, Renderer, RootRenderer} from '../render/api';
|
||||||
import {Sanitizer} from '../security';
|
import {Sanitizer} from '../security';
|
||||||
|
|
||||||
import {AppElement} from './element';
|
import {AppElement} from './element';
|
||||||
import {ExpressionChangedAfterItHasBeenCheckedError} from './errors';
|
import {ExpressionChangedAfterItHasBeenCheckedError} from './errors';
|
||||||
|
|
||||||
@ -352,3 +353,27 @@ export function pureProxy10<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, R>(
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setBindingDebugInfoForChanges(
|
||||||
|
renderer: Renderer, el: any, changes: {[key: string]: SimpleChange}) {
|
||||||
|
Object.keys(changes).forEach((propName) => {
|
||||||
|
setBindingDebugInfo(renderer, el, propName, changes[propName].currentValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setBindingDebugInfo(renderer: Renderer, el: any, propName: string, value: any) {
|
||||||
|
try {
|
||||||
|
renderer.setBindingDebugInfo(
|
||||||
|
el, `ng-reflect-${camelCaseToDashCase(propName)}`, value ? value.toString() : null);
|
||||||
|
} catch (e) {
|
||||||
|
renderer.setBindingDebugInfo(
|
||||||
|
el, `ng-reflect-${camelCaseToDashCase(propName)}`,
|
||||||
|
'[ERROR] Exception while trying to serialize the value');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CAMEL_CASE_REGEXP = /([A-Z])/g;
|
||||||
|
|
||||||
|
function camelCaseToDashCase(input: string): string {
|
||||||
|
return input.replace(CAMEL_CASE_REGEXP, (...m: any[]) => '-' + m[1].toLowerCase());
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user