parent
faa3478514
commit
cb7643ccea
|
@ -11,6 +11,7 @@ import {Injectable} from '@angular/core';
|
||||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata} from './compile_metadata';
|
import {CompileDirectiveMetadata, CompileIdentifierMetadata} from './compile_metadata';
|
||||||
import {CompilerConfig} from './config';
|
import {CompilerConfig} from './config';
|
||||||
import {Identifiers, resolveIdentifier} from './identifiers';
|
import {Identifiers, resolveIdentifier} from './identifiers';
|
||||||
|
import {ClassBuilder, createClassStmt} from './output/class_builder';
|
||||||
import * as o from './output/output_ast';
|
import * as o from './output/output_ast';
|
||||||
import {LifecycleHooks, isDefaultChangeDetectionStrategy} from './private_import_core';
|
import {LifecycleHooks, isDefaultChangeDetectionStrategy} from './private_import_core';
|
||||||
|
|
||||||
|
@ -45,59 +46,68 @@ export class DirectiveWrapperCompiler {
|
||||||
constructor(private compilerConfig: CompilerConfig) {}
|
constructor(private compilerConfig: CompilerConfig) {}
|
||||||
|
|
||||||
compile(dirMeta: CompileDirectiveMetadata): DirectiveWrapperCompileResult {
|
compile(dirMeta: CompileDirectiveMetadata): DirectiveWrapperCompileResult {
|
||||||
|
const builder = new DirectiveWrapperBuilder(this.compilerConfig, dirMeta);
|
||||||
|
Object.keys(dirMeta.inputs).forEach((inputFieldName) => {
|
||||||
|
createCheckInputMethod(inputFieldName, builder);
|
||||||
|
});
|
||||||
|
createDetectChangesInternalMethod(builder);
|
||||||
|
const classStmt = builder.build();
|
||||||
|
return new DirectiveWrapperCompileResult([classStmt], classStmt.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DirectiveWrapperBuilder implements ClassBuilder {
|
||||||
|
fields: o.ClassField[] = [];
|
||||||
|
getters: o.ClassGetter[] = [];
|
||||||
|
methods: o.ClassMethod[] = [];
|
||||||
|
ctorStmts: o.Statement[] = [];
|
||||||
|
|
||||||
|
genChanges: boolean;
|
||||||
|
ngOnChanges: boolean;
|
||||||
|
ngOnInit: boolean;
|
||||||
|
ngDoCheck: boolean;
|
||||||
|
|
||||||
|
constructor(public compilerConfig: CompilerConfig, public dirMeta: CompileDirectiveMetadata) {
|
||||||
|
const dirLifecycleHooks = dirMeta.type.lifecycleHooks;
|
||||||
|
this.genChanges = dirLifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1 ||
|
||||||
|
this.compilerConfig.logBindingUpdate;
|
||||||
|
this.ngOnChanges = dirLifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1;
|
||||||
|
this.ngOnInit = dirLifecycleHooks.indexOf(LifecycleHooks.OnInit) !== -1;
|
||||||
|
this.ngDoCheck = dirLifecycleHooks.indexOf(LifecycleHooks.DoCheck) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
build(): o.ClassStmt {
|
||||||
const dirDepParamNames: string[] = [];
|
const dirDepParamNames: string[] = [];
|
||||||
for (let i = 0; i < dirMeta.type.diDeps.length; i++) {
|
for (let i = 0; i < this.dirMeta.type.diDeps.length; i++) {
|
||||||
dirDepParamNames.push(`p${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[] = [
|
const fields: o.ClassField[] = [
|
||||||
new o.ClassField(CONTEXT_FIELD_NAME, o.importType(dirMeta.type)),
|
new o.ClassField(CONTEXT_FIELD_NAME, o.importType(this.dirMeta.type)),
|
||||||
new o.ClassField(CHANGED_FIELD_NAME, o.BOOL_TYPE),
|
new o.ClassField(CHANGED_FIELD_NAME, o.BOOL_TYPE),
|
||||||
];
|
];
|
||||||
const ctorStmts: o.Statement[] =
|
const ctorStmts: o.Statement[] =
|
||||||
[o.THIS_EXPR.prop(CHANGED_FIELD_NAME).set(o.literal(false)).toStmt()];
|
[o.THIS_EXPR.prop(CHANGED_FIELD_NAME).set(o.literal(false)).toStmt()];
|
||||||
if (lifecycleHooks.genChanges) {
|
if (this.genChanges) {
|
||||||
fields.push(new o.ClassField(CHANGES_FIELD_NAME, new o.MapType(o.DYNAMIC_TYPE)));
|
fields.push(new o.ClassField(CHANGES_FIELD_NAME, new o.MapType(o.DYNAMIC_TYPE)));
|
||||||
ctorStmts.push(RESET_CHANGES_STMT);
|
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(
|
ctorStmts.push(
|
||||||
o.THIS_EXPR.prop(CONTEXT_FIELD_NAME)
|
o.THIS_EXPR.prop(CONTEXT_FIELD_NAME)
|
||||||
.set(o.importExpr(dirMeta.type)
|
.set(o.importExpr(this.dirMeta.type)
|
||||||
.instantiate(dirDepParamNames.map((paramName) => o.variable(paramName))))
|
.instantiate(dirDepParamNames.map((paramName) => o.variable(paramName))))
|
||||||
.toStmt());
|
.toStmt());
|
||||||
const ctor = new o.ClassMethod(
|
|
||||||
null, dirDepParamNames.map((paramName) => new o.FnParam(paramName, o.DYNAMIC_TYPE)),
|
|
||||||
ctorStmts);
|
|
||||||
|
|
||||||
const wrapperClassName = DirectiveWrapperCompiler.dirWrapperClassName(dirMeta.type);
|
return createClassStmt({
|
||||||
const classStmt = new o.ClassStmt(wrapperClassName, null, fields, [], ctor, methods);
|
name: DirectiveWrapperCompiler.dirWrapperClassName(this.dirMeta.type),
|
||||||
return new DirectiveWrapperCompileResult([classStmt], wrapperClassName);
|
ctorParams: dirDepParamNames.map((paramName) => new o.FnParam(paramName, o.DYNAMIC_TYPE)),
|
||||||
|
builders: [{fields: fields, ctorStmts: ctorStmts}, this]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function detectChangesInternalMethod(
|
function createDetectChangesInternalMethod(builder: DirectiveWrapperBuilder) {
|
||||||
lifecycleHooks: GenConfig, logBindingUpdate: boolean): o.ClassMethod {
|
|
||||||
const changedVar = o.variable('changed');
|
const changedVar = o.variable('changed');
|
||||||
const stmts: o.Statement[] = [
|
const stmts: o.Statement[] = [
|
||||||
changedVar.set(o.THIS_EXPR.prop(CHANGED_FIELD_NAME)).toDeclStmt(),
|
changedVar.set(o.THIS_EXPR.prop(CHANGED_FIELD_NAME)).toDeclStmt(),
|
||||||
|
@ -105,14 +115,14 @@ function detectChangesInternalMethod(
|
||||||
];
|
];
|
||||||
const lifecycleStmts: o.Statement[] = [];
|
const lifecycleStmts: o.Statement[] = [];
|
||||||
|
|
||||||
if (lifecycleHooks.genChanges) {
|
if (builder.genChanges) {
|
||||||
const onChangesStmts: o.Statement[] = [];
|
const onChangesStmts: o.Statement[] = [];
|
||||||
if (lifecycleHooks.ngOnChanges) {
|
if (builder.ngOnChanges) {
|
||||||
onChangesStmts.push(o.THIS_EXPR.prop(CONTEXT_FIELD_NAME)
|
onChangesStmts.push(o.THIS_EXPR.prop(CONTEXT_FIELD_NAME)
|
||||||
.callMethod('ngOnChanges', [o.THIS_EXPR.prop(CHANGES_FIELD_NAME)])
|
.callMethod('ngOnChanges', [o.THIS_EXPR.prop(CHANGES_FIELD_NAME)])
|
||||||
.toStmt());
|
.toStmt());
|
||||||
}
|
}
|
||||||
if (logBindingUpdate) {
|
if (builder.compilerConfig.logBindingUpdate) {
|
||||||
onChangesStmts.push(
|
onChangesStmts.push(
|
||||||
o.importExpr(resolveIdentifier(Identifiers.setBindingDebugInfoForChanges))
|
o.importExpr(resolveIdentifier(Identifiers.setBindingDebugInfoForChanges))
|
||||||
.callFn(
|
.callFn(
|
||||||
|
@ -123,12 +133,12 @@ function detectChangesInternalMethod(
|
||||||
lifecycleStmts.push(new o.IfStmt(changedVar, onChangesStmts));
|
lifecycleStmts.push(new o.IfStmt(changedVar, onChangesStmts));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lifecycleHooks.ngOnInit) {
|
if (builder.ngOnInit) {
|
||||||
lifecycleStmts.push(new o.IfStmt(
|
lifecycleStmts.push(new o.IfStmt(
|
||||||
VIEW_VAR.prop('numberOfChecks').identical(new o.LiteralExpr(0)),
|
VIEW_VAR.prop('numberOfChecks').identical(new o.LiteralExpr(0)),
|
||||||
[o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).callMethod('ngOnInit', []).toStmt()]));
|
[o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).callMethod('ngOnInit', []).toStmt()]));
|
||||||
}
|
}
|
||||||
if (lifecycleHooks.ngDoCheck) {
|
if (builder.ngDoCheck) {
|
||||||
lifecycleStmts.push(o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).callMethod('ngDoCheck', []).toStmt());
|
lifecycleStmts.push(o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).callMethod('ngDoCheck', []).toStmt());
|
||||||
}
|
}
|
||||||
if (lifecycleStmts.length > 0) {
|
if (lifecycleStmts.length > 0) {
|
||||||
|
@ -136,7 +146,7 @@ function detectChangesInternalMethod(
|
||||||
}
|
}
|
||||||
stmts.push(new o.ReturnStatement(changedVar));
|
stmts.push(new o.ReturnStatement(changedVar));
|
||||||
|
|
||||||
return new o.ClassMethod(
|
builder.methods.push(new o.ClassMethod(
|
||||||
'detectChangesInternal',
|
'detectChangesInternal',
|
||||||
[
|
[
|
||||||
new o.FnParam(
|
new o.FnParam(
|
||||||
|
@ -144,16 +154,22 @@ function detectChangesInternalMethod(
|
||||||
new o.FnParam(RENDER_EL_VAR.name, o.DYNAMIC_TYPE),
|
new o.FnParam(RENDER_EL_VAR.name, o.DYNAMIC_TYPE),
|
||||||
new o.FnParam(THROW_ON_CHANGE_VAR.name, o.BOOL_TYPE),
|
new o.FnParam(THROW_ON_CHANGE_VAR.name, o.BOOL_TYPE),
|
||||||
],
|
],
|
||||||
stmts, o.BOOL_TYPE);
|
stmts, o.BOOL_TYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkInputMethod(
|
function createCheckInputMethod(input: string, builder: DirectiveWrapperBuilder) {
|
||||||
input: string, fieldExpr: o.ReadPropExpr, lifecycleHooks: GenConfig): o.ClassMethod {
|
const fieldName = `_${input}`;
|
||||||
|
const fieldExpr = o.THIS_EXPR.prop(fieldName);
|
||||||
|
// private is fine here as no child view will reference the cached value...
|
||||||
|
builder.fields.push(new o.ClassField(fieldName, null, [o.StmtModifier.Private]));
|
||||||
|
builder.ctorStmts.push(o.THIS_EXPR.prop(fieldName)
|
||||||
|
.set(o.importExpr(resolveIdentifier(Identifiers.UNINITIALIZED)))
|
||||||
|
.toStmt());
|
||||||
var onChangeStatements: o.Statement[] = [
|
var onChangeStatements: o.Statement[] = [
|
||||||
o.THIS_EXPR.prop(CHANGED_FIELD_NAME).set(o.literal(true)).toStmt(),
|
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(),
|
o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).prop(input).set(CURR_VALUE_VAR).toStmt(),
|
||||||
];
|
];
|
||||||
if (lifecycleHooks.genChanges) {
|
if (builder.genChanges) {
|
||||||
onChangeStatements.push(o.THIS_EXPR.prop(CHANGES_FIELD_NAME)
|
onChangeStatements.push(o.THIS_EXPR.prop(CHANGES_FIELD_NAME)
|
||||||
.key(o.literal(input))
|
.key(o.literal(input))
|
||||||
.set(o.importExpr(resolveIdentifier(Identifiers.SimpleChange))
|
.set(o.importExpr(resolveIdentifier(Identifiers.SimpleChange))
|
||||||
|
@ -168,19 +184,12 @@ function checkInputMethod(
|
||||||
.callFn([THROW_ON_CHANGE_VAR, fieldExpr, CURR_VALUE_VAR])),
|
.callFn([THROW_ON_CHANGE_VAR, fieldExpr, CURR_VALUE_VAR])),
|
||||||
onChangeStatements),
|
onChangeStatements),
|
||||||
];
|
];
|
||||||
return new o.ClassMethod(
|
builder.methods.push(new o.ClassMethod(
|
||||||
`check_${input}`,
|
`check_${input}`,
|
||||||
[
|
[
|
||||||
new o.FnParam(CURR_VALUE_VAR.name, o.DYNAMIC_TYPE),
|
new o.FnParam(CURR_VALUE_VAR.name, o.DYNAMIC_TYPE),
|
||||||
new o.FnParam(THROW_ON_CHANGE_VAR.name, o.BOOL_TYPE),
|
new o.FnParam(THROW_ON_CHANGE_VAR.name, o.BOOL_TYPE),
|
||||||
new o.FnParam(FORCE_UPDATE_VAR.name, o.BOOL_TYPE),
|
new o.FnParam(FORCE_UPDATE_VAR.name, o.BOOL_TYPE),
|
||||||
],
|
],
|
||||||
methodBody);
|
methodBody));
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GenConfig {
|
|
||||||
genChanges: boolean;
|
|
||||||
ngOnChanges: boolean;
|
|
||||||
ngOnInit: boolean;
|
|
||||||
ngDoCheck: boolean;
|
|
||||||
}
|
|
|
@ -12,6 +12,7 @@ import {CompileDiDependencyMetadata, CompileIdentifierMetadata, CompileNgModuleM
|
||||||
import {createDiTokenExpression} from './compiler_util/identifier_util';
|
import {createDiTokenExpression} from './compiler_util/identifier_util';
|
||||||
import {isPresent} from './facade/lang';
|
import {isPresent} from './facade/lang';
|
||||||
import {Identifiers, resolveIdentifier, resolveIdentifierToken} from './identifiers';
|
import {Identifiers, resolveIdentifier, resolveIdentifierToken} from './identifiers';
|
||||||
|
import {ClassBuilder, createClassStmt} from './output/class_builder';
|
||||||
import * as o from './output/output_ast';
|
import * as o from './output/output_ast';
|
||||||
import {convertValueToOutputAst} from './output/value_util';
|
import {convertValueToOutputAst} from './output/value_util';
|
||||||
import {ParseLocation, ParseSourceFile, ParseSourceSpan} from './parse_util';
|
import {ParseLocation, ParseSourceFile, ParseSourceSpan} from './parse_util';
|
||||||
|
@ -82,13 +83,15 @@ export class NgModuleCompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _InjectorBuilder {
|
class _InjectorBuilder implements ClassBuilder {
|
||||||
private _tokens: CompileTokenMetadata[] = [];
|
private _tokens: CompileTokenMetadata[] = [];
|
||||||
private _instances = new Map<any, o.Expression>();
|
private _instances = new Map<any, o.Expression>();
|
||||||
private _fields: o.ClassField[] = [];
|
fields: o.ClassField[] = [];
|
||||||
private _createStmts: o.Statement[] = [];
|
private _createStmts: o.Statement[] = [];
|
||||||
private _destroyStmts: o.Statement[] = [];
|
private _destroyStmts: o.Statement[] = [];
|
||||||
private _getters: o.ClassGetter[] = [];
|
getters: o.ClassGetter[] = [];
|
||||||
|
methods: o.ClassMethod[] = [];
|
||||||
|
ctorStmts: o.Statement[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _ngModuleMeta: CompileNgModuleMetadata,
|
private _ngModuleMeta: CompileNgModuleMetadata,
|
||||||
|
@ -136,26 +139,23 @@ class _InjectorBuilder {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
var ctor = new o.ClassMethod(
|
var parentArgs = [
|
||||||
null,
|
o.variable(InjectorProps.parent.name),
|
||||||
[new o.FnParam(
|
o.literalArr(
|
||||||
InjectorProps.parent.name, o.importType(resolveIdentifier(Identifiers.Injector)))],
|
this._entryComponentFactories.map((componentFactory) => o.importExpr(componentFactory))),
|
||||||
[o.SUPER_EXPR
|
o.literalArr(this._bootstrapComponentFactories.map(
|
||||||
.callFn([
|
(componentFactory) => o.importExpr(componentFactory)))
|
||||||
o.variable(InjectorProps.parent.name),
|
];
|
||||||
o.literalArr(this._entryComponentFactories.map(
|
|
||||||
(componentFactory) => o.importExpr(componentFactory))),
|
|
||||||
o.literalArr(this._bootstrapComponentFactories.map(
|
|
||||||
(componentFactory) => o.importExpr(componentFactory)))
|
|
||||||
])
|
|
||||||
.toStmt()]);
|
|
||||||
|
|
||||||
var injClassName = `${this._ngModuleMeta.type.name}Injector`;
|
var injClassName = `${this._ngModuleMeta.type.name}Injector`;
|
||||||
return new o.ClassStmt(
|
return createClassStmt({
|
||||||
injClassName, o.importExpr(
|
name: injClassName,
|
||||||
resolveIdentifier(Identifiers.NgModuleInjector),
|
ctorParams: [new o.FnParam(
|
||||||
[o.importType(this._ngModuleMeta.type)]),
|
InjectorProps.parent.name, o.importType(resolveIdentifier(Identifiers.Injector)))],
|
||||||
this._fields, this._getters, ctor, methods);
|
parent: o.importExpr(
|
||||||
|
resolveIdentifier(Identifiers.NgModuleInjector), [o.importType(this._ngModuleMeta.type)]),
|
||||||
|
parentArgs: parentArgs,
|
||||||
|
builders: [{methods: methods}, this]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getProviderValue(provider: CompileProviderMetadata): o.Expression {
|
private _getProviderValue(provider: CompileProviderMetadata): o.Expression {
|
||||||
|
@ -194,11 +194,11 @@ class _InjectorBuilder {
|
||||||
type = o.DYNAMIC_TYPE;
|
type = o.DYNAMIC_TYPE;
|
||||||
}
|
}
|
||||||
if (isEager) {
|
if (isEager) {
|
||||||
this._fields.push(new o.ClassField(propName, type));
|
this.fields.push(new o.ClassField(propName, type));
|
||||||
this._createStmts.push(o.THIS_EXPR.prop(propName).set(resolvedProviderValueExpr).toStmt());
|
this._createStmts.push(o.THIS_EXPR.prop(propName).set(resolvedProviderValueExpr).toStmt());
|
||||||
} else {
|
} else {
|
||||||
var internalField = `_${propName}`;
|
var internalField = `_${propName}`;
|
||||||
this._fields.push(new o.ClassField(internalField, type));
|
this.fields.push(new o.ClassField(internalField, type));
|
||||||
// Note: Equals is important for JS so that it also checks the undefined case!
|
// Note: Equals is important for JS so that it also checks the undefined case!
|
||||||
var getterStmts = [
|
var getterStmts = [
|
||||||
new o.IfStmt(
|
new o.IfStmt(
|
||||||
|
@ -206,7 +206,7 @@ class _InjectorBuilder {
|
||||||
[o.THIS_EXPR.prop(internalField).set(resolvedProviderValueExpr).toStmt()]),
|
[o.THIS_EXPR.prop(internalField).set(resolvedProviderValueExpr).toStmt()]),
|
||||||
new o.ReturnStatement(o.THIS_EXPR.prop(internalField))
|
new o.ReturnStatement(o.THIS_EXPR.prop(internalField))
|
||||||
];
|
];
|
||||||
this._getters.push(new o.ClassGetter(propName, getterStmts, type));
|
this.getters.push(new o.ClassGetter(propName, getterStmts, type));
|
||||||
}
|
}
|
||||||
return o.THIS_EXPR.prop(propName);
|
return o.THIS_EXPR.prop(propName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**
|
||||||
|
* @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 * as o from './output_ast';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new class stmts based on the given data.
|
||||||
|
*/
|
||||||
|
export function createClassStmt(config: {
|
||||||
|
name: string,
|
||||||
|
parent?: o.Expression,
|
||||||
|
parentArgs?: o.Expression[],
|
||||||
|
ctorParams?: o.FnParam[],
|
||||||
|
builders: ClassBuilderPart | ClassBuilderPart[], modifiers?: o.StmtModifier[]
|
||||||
|
}): o.ClassStmt {
|
||||||
|
const parentArgs = config.parentArgs || [];
|
||||||
|
const superCtorStmts = config.parent ? [o.SUPER_EXPR.callFn(parentArgs).toStmt()] : [];
|
||||||
|
const builder =
|
||||||
|
concatClassBuilderParts(Array.isArray(config.builders) ? config.builders : [config.builders]);
|
||||||
|
const ctor =
|
||||||
|
new o.ClassMethod(null, config.ctorParams || [], superCtorStmts.concat(builder.ctorStmts));
|
||||||
|
|
||||||
|
return new o.ClassStmt(
|
||||||
|
config.name, config.parent, builder.fields, builder.getters, ctor, builder.methods,
|
||||||
|
config.modifiers || [])
|
||||||
|
}
|
||||||
|
|
||||||
|
function concatClassBuilderParts(builders: ClassBuilderPart[]): ClassBuilder {
|
||||||
|
return {
|
||||||
|
fields: [].concat(...builders.map(builder => builder.fields || [])),
|
||||||
|
methods: [].concat(...builders.map(builder => builder.methods || [])),
|
||||||
|
getters: [].concat(...builders.map(builder => builder.getters || [])),
|
||||||
|
ctorStmts: [].concat(...builders.map(builder => builder.ctorStmts || [])),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects data for a generated class.
|
||||||
|
*/
|
||||||
|
export interface ClassBuilderPart {
|
||||||
|
fields?: o.ClassField[];
|
||||||
|
methods?: o.ClassMethod[];
|
||||||
|
getters?: o.ClassGetter[];
|
||||||
|
ctorStmts?: o.Statement[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects data for a generated class.
|
||||||
|
*/
|
||||||
|
export interface ClassBuilder extends ClassBuilderPart {
|
||||||
|
fields: o.ClassField[];
|
||||||
|
methods: o.ClassMethod[];
|
||||||
|
getters: o.ClassGetter[];
|
||||||
|
ctorStmts: o.Statement[];
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import {CompilerConfig} from '../config';
|
||||||
import {MapWrapper} from '../facade/collection';
|
import {MapWrapper} from '../facade/collection';
|
||||||
import {isPresent} from '../facade/lang';
|
import {isPresent} from '../facade/lang';
|
||||||
import {Identifiers, resolveIdentifier} from '../identifiers';
|
import {Identifiers, resolveIdentifier} from '../identifiers';
|
||||||
|
import {ClassBuilder} from '../output/class_builder';
|
||||||
import * as o from '../output/output_ast';
|
import * as o from '../output/output_ast';
|
||||||
import {ViewType} from '../private_import_core';
|
import {ViewType} from '../private_import_core';
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ import {EventHandlerVars} from './constants';
|
||||||
import {NameResolver} from './expression_converter';
|
import {NameResolver} from './expression_converter';
|
||||||
import {createPureProxy, getPropertyInView, getViewFactoryName} from './util';
|
import {createPureProxy, getPropertyInView, getViewFactoryName} from './util';
|
||||||
|
|
||||||
export class CompileView implements NameResolver {
|
export class CompileView implements NameResolver, ClassBuilder {
|
||||||
public viewType: ViewType;
|
public viewType: ViewType;
|
||||||
public viewQueries: Map<any, CompileQuery[]>;
|
public viewQueries: Map<any, CompileQuery[]>;
|
||||||
|
|
||||||
|
@ -34,7 +35,6 @@ export class CompileView implements NameResolver {
|
||||||
|
|
||||||
public bindings: CompileBinding[] = [];
|
public bindings: CompileBinding[] = [];
|
||||||
|
|
||||||
public classStatements: o.Statement[] = [];
|
|
||||||
public createMethod: CompileMethod;
|
public createMethod: CompileMethod;
|
||||||
public animationBindingsMethod: CompileMethod;
|
public animationBindingsMethod: CompileMethod;
|
||||||
public injectorGetMethod: CompileMethod;
|
public injectorGetMethod: CompileMethod;
|
||||||
|
@ -47,8 +47,9 @@ export class CompileView implements NameResolver {
|
||||||
public afterViewLifecycleCallbacksMethod: CompileMethod;
|
public afterViewLifecycleCallbacksMethod: CompileMethod;
|
||||||
public destroyMethod: CompileMethod;
|
public destroyMethod: CompileMethod;
|
||||||
public detachMethod: CompileMethod;
|
public detachMethod: CompileMethod;
|
||||||
public eventHandlerMethods: o.ClassMethod[] = [];
|
public methods: o.ClassMethod[] = [];
|
||||||
|
|
||||||
|
public ctorStmts: o.Statement[] = [];
|
||||||
public fields: o.ClassField[] = [];
|
public fields: o.ClassField[] = [];
|
||||||
public getters: o.ClassGetter[] = [];
|
public getters: o.ClassGetter[] = [];
|
||||||
public disposables: o.Expression[] = [];
|
public disposables: o.Expression[] = [];
|
||||||
|
|
|
@ -92,7 +92,7 @@ export class CompileEventListener {
|
||||||
.concat(this._method.finish())
|
.concat(this._method.finish())
|
||||||
.concat([new o.ReturnStatement(resultExpr)]);
|
.concat([new o.ReturnStatement(resultExpr)]);
|
||||||
// private is fine here as no child view will reference the event handler...
|
// private is fine here as no child view will reference the event handler...
|
||||||
this.compileElement.view.eventHandlerMethods.push(new o.ClassMethod(
|
this.compileElement.view.methods.push(new o.ClassMethod(
|
||||||
this._methodName, [this._eventParam], stmts, o.BOOL_TYPE, [o.StmtModifier.Private]));
|
this._methodName, [this._eventParam], stmts, o.BOOL_TYPE, [o.StmtModifier.Private]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileTokenMetadat
|
||||||
import {createDiTokenExpression, createFastArray} from '../compiler_util/identifier_util';
|
import {createDiTokenExpression, createFastArray} from '../compiler_util/identifier_util';
|
||||||
import {isPresent} from '../facade/lang';
|
import {isPresent} from '../facade/lang';
|
||||||
import {Identifiers, identifierToken, resolveIdentifier} from '../identifiers';
|
import {Identifiers, identifierToken, resolveIdentifier} from '../identifiers';
|
||||||
|
import {createClassStmt} from '../output/class_builder';
|
||||||
import * as o from '../output/output_ast';
|
import * as o from '../output/output_ast';
|
||||||
import {ChangeDetectorStatus, ViewType, isDefaultChangeDetectionStrategy} from '../private_import_core';
|
import {ChangeDetectorStatus, ViewType, isDefaultChangeDetectionStrategy} from '../private_import_core';
|
||||||
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast';
|
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '../template_parser/template_ast';
|
||||||
|
@ -432,9 +433,6 @@ function createViewClass(
|
||||||
if (view.genConfig.genDebugInfo) {
|
if (view.genConfig.genDebugInfo) {
|
||||||
superConstructorArgs.push(nodeDebugInfosVar);
|
superConstructorArgs.push(nodeDebugInfosVar);
|
||||||
}
|
}
|
||||||
var viewConstructor = new o.ClassMethod(
|
|
||||||
null, viewConstructorArgs, [o.SUPER_EXPR.callFn(superConstructorArgs).toStmt()]);
|
|
||||||
|
|
||||||
var viewMethods = [
|
var viewMethods = [
|
||||||
new o.ClassMethod(
|
new o.ClassMethod(
|
||||||
'createInternal', [new o.FnParam(rootSelectorVar.name, o.STRING_TYPE)],
|
'createInternal', [new o.FnParam(rootSelectorVar.name, o.STRING_TYPE)],
|
||||||
|
@ -455,12 +453,16 @@ function createViewClass(
|
||||||
new o.ClassMethod('dirtyParentQueriesInternal', [], view.dirtyParentQueriesMethod.finish()),
|
new o.ClassMethod('dirtyParentQueriesInternal', [], view.dirtyParentQueriesMethod.finish()),
|
||||||
new o.ClassMethod('destroyInternal', [], view.destroyMethod.finish()),
|
new o.ClassMethod('destroyInternal', [], view.destroyMethod.finish()),
|
||||||
new o.ClassMethod('detachInternal', [], view.detachMethod.finish())
|
new o.ClassMethod('detachInternal', [], view.detachMethod.finish())
|
||||||
].concat(view.eventHandlerMethods);
|
].filter((method) => method.body.length > 0);
|
||||||
var superClass = view.genConfig.genDebugInfo ? Identifiers.DebugAppView : Identifiers.AppView;
|
var superClass = view.genConfig.genDebugInfo ? Identifiers.DebugAppView : Identifiers.AppView;
|
||||||
var viewClass = new o.ClassStmt(
|
|
||||||
view.className, o.importExpr(resolveIdentifier(superClass), [getContextType(view)]),
|
var viewClass = createClassStmt({
|
||||||
view.fields, view.getters, viewConstructor,
|
name: view.className,
|
||||||
viewMethods.filter((method) => method.body.length > 0));
|
parent: o.importExpr(resolveIdentifier(superClass), [getContextType(view)]),
|
||||||
|
parentArgs: superConstructorArgs,
|
||||||
|
ctorParams: viewConstructorArgs,
|
||||||
|
builders: [{methods: viewMethods}, view]
|
||||||
|
});
|
||||||
return viewClass;
|
return viewClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue