refactor(compiler): generate less code for bindings to DOM elements
Detailed changes: - remove `UNINITIALIZED`, initialize change detection fields with `undefined`. * we use `view.numberOfChecks === 0` now everywhere as indicator whether we are in the first change detection cycle (previously we used this only in a couple of places). * we keep the initialization itself as change detection get slower without it. - remove passing around `throwOnChange` in various generated calls, and store it on the view as property instead. - change generated code for bindings to DOM elements as follows: Before: ``` var currVal_10 = self.context.bgColor; if (jit_checkBinding15(self.throwOnChange,self._expr_10,currVal_10)) { self.renderer.setElementStyle(self._el_0,'backgroundColor',((self.viewUtils.sanitizer.sanitize(jit_21,currVal_10) == null)? null: self.viewUtils.sanitizer.sanitize(jit_21,currVal_10).toString())); self._expr_10 = currVal_10; } var currVal_11 = jit_inlineInterpolate16(1,' ',self.context.data.value,' '); if (jit_checkBinding15(self.throwOnChange,self._expr_11,currVal_11)) { self.renderer.setText(self._text_1,currVal_11); self._expr_11 = currVal_11; } ```, After: ``` var currVal_10 = self.context.bgColor; jit_checkRenderStyle14(self,self._el_0,'backgroundColor',null,self._expr_10,self._expr_10=currVal_10,false,jit_21); var currVal_11 = jit_inlineInterpolate15(1,' ',self.context.data.value,' '); jit_checkRenderText16(self,self._text_1,self._expr_11,self._expr_11=currVal_11,false); ``` Performance impact: - None seen (checked against internal latency lab) Part of #13651
This commit is contained in:
parent
8ed92d75b0
commit
db49d422f2
|
@ -21,28 +21,14 @@ export function createCheckBindingField(builder: ClassBuilder): CheckBindingFiel
|
||||||
const fieldExpr = createBindFieldExpr(bindingId);
|
const fieldExpr = createBindFieldExpr(bindingId);
|
||||||
// private is fine here as no child view will reference the cached value...
|
// private is fine here as no child view will reference the cached value...
|
||||||
builder.fields.push(new o.ClassField(fieldExpr.name, null, [o.StmtModifier.Private]));
|
builder.fields.push(new o.ClassField(fieldExpr.name, null, [o.StmtModifier.Private]));
|
||||||
builder.ctorStmts.push(o.THIS_EXPR.prop(fieldExpr.name)
|
builder.ctorStmts.push(o.THIS_EXPR.prop(fieldExpr.name).set(o.literal(undefined)).toStmt());
|
||||||
.set(o.importExpr(createIdentifier(Identifiers.UNINITIALIZED)))
|
|
||||||
.toStmt());
|
|
||||||
return new CheckBindingField(fieldExpr, bindingId);
|
return new CheckBindingField(fieldExpr, bindingId);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createCheckBindingStmt(
|
|
||||||
evalResult: ConvertPropertyBindingResult, fieldExpr: o.ReadPropExpr,
|
|
||||||
throwOnChangeVar: o.Expression, actions: o.Statement[]): o.Statement[] {
|
|
||||||
let condition: o.Expression = o.importExpr(createIdentifier(Identifiers.checkBinding)).callFn([
|
|
||||||
throwOnChangeVar, fieldExpr, evalResult.currValExpr
|
|
||||||
]);
|
|
||||||
if (evalResult.forceUpdate) {
|
|
||||||
condition = evalResult.forceUpdate.or(condition);
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
...evalResult.stmts, new o.IfStmt(condition, actions.concat([
|
|
||||||
<o.Statement>o.THIS_EXPR.prop(fieldExpr.name).set(evalResult.currValExpr).toStmt()
|
|
||||||
]))
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
function createBindFieldExpr(bindingId: string): o.ReadPropExpr {
|
function createBindFieldExpr(bindingId: string): o.ReadPropExpr {
|
||||||
return o.THIS_EXPR.prop(`_expr_${bindingId}`);
|
return o.THIS_EXPR.prop(`_expr_${bindingId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isFirstViewCheck(view: o.Expression): o.Expression {
|
||||||
|
return o.not(view.prop('numberOfChecks'));
|
||||||
|
}
|
|
@ -13,69 +13,64 @@ import * as o from '../output/output_ast';
|
||||||
import {EMPTY_STATE as EMPTY_ANIMATION_STATE} from '../private_import_core';
|
import {EMPTY_STATE as EMPTY_ANIMATION_STATE} from '../private_import_core';
|
||||||
import {BoundElementPropertyAst, BoundEventAst, PropertyBindingType} from '../template_parser/template_ast';
|
import {BoundElementPropertyAst, BoundEventAst, PropertyBindingType} from '../template_parser/template_ast';
|
||||||
|
|
||||||
|
import {isFirstViewCheck} from './binding_util';
|
||||||
|
import {ConvertPropertyBindingResult} from './expression_converter';
|
||||||
import {createEnumExpression} from './identifier_util';
|
import {createEnumExpression} from './identifier_util';
|
||||||
|
|
||||||
export function writeToRenderer(
|
export function createCheckRenderBindingStmt(
|
||||||
view: o.Expression, boundProp: BoundElementPropertyAst, renderElement: o.Expression,
|
view: o.Expression, renderElement: o.Expression, boundProp: BoundElementPropertyAst,
|
||||||
renderValue: o.Expression, logBindingUpdate: boolean,
|
oldValue: o.ReadPropExpr, evalResult: ConvertPropertyBindingResult,
|
||||||
securityContextExpression?: o.Expression): o.Statement[] {
|
securityContextExpression?: o.Expression): o.Statement[] {
|
||||||
const updateStmts: o.Statement[] = [];
|
const checkStmts: o.Statement[] = [...evalResult.stmts];
|
||||||
const renderer = view.prop('renderer');
|
const securityContext = calcSecurityContext(boundProp, securityContextExpression);
|
||||||
renderValue = sanitizedValue(view, boundProp, renderValue, securityContextExpression);
|
|
||||||
switch (boundProp.type) {
|
switch (boundProp.type) {
|
||||||
case PropertyBindingType.Property:
|
case PropertyBindingType.Property:
|
||||||
if (logBindingUpdate) {
|
checkStmts.push(o.importExpr(createIdentifier(Identifiers.checkRenderProperty))
|
||||||
updateStmts.push(
|
.callFn([
|
||||||
o.importExpr(createIdentifier(Identifiers.setBindingDebugInfo))
|
view, renderElement, o.literal(boundProp.name), oldValue,
|
||||||
.callFn([renderer, renderElement, o.literal(boundProp.name), renderValue])
|
oldValue.set(evalResult.currValExpr),
|
||||||
.toStmt());
|
evalResult.forceUpdate || o.literal(false), securityContext
|
||||||
}
|
])
|
||||||
updateStmts.push(
|
|
||||||
renderer
|
|
||||||
.callMethod(
|
|
||||||
'setElementProperty', [renderElement, o.literal(boundProp.name), renderValue])
|
|
||||||
.toStmt());
|
.toStmt());
|
||||||
break;
|
break;
|
||||||
case PropertyBindingType.Attribute:
|
case PropertyBindingType.Attribute:
|
||||||
renderValue =
|
checkStmts.push(o.importExpr(createIdentifier(Identifiers.checkRenderAttribute))
|
||||||
renderValue.isBlank().conditional(o.NULL_EXPR, renderValue.callMethod('toString', []));
|
.callFn([
|
||||||
updateStmts.push(
|
view, renderElement, o.literal(boundProp.name), oldValue,
|
||||||
renderer
|
oldValue.set(evalResult.currValExpr),
|
||||||
.callMethod(
|
evalResult.forceUpdate || o.literal(false), securityContext
|
||||||
'setElementAttribute', [renderElement, o.literal(boundProp.name), renderValue])
|
])
|
||||||
.toStmt());
|
.toStmt());
|
||||||
break;
|
break;
|
||||||
case PropertyBindingType.Class:
|
case PropertyBindingType.Class:
|
||||||
updateStmts.push(
|
checkStmts.push(
|
||||||
renderer
|
o.importExpr(createIdentifier(Identifiers.checkRenderClass))
|
||||||
.callMethod(
|
.callFn([
|
||||||
'setElementClass', [renderElement, o.literal(boundProp.name), renderValue])
|
view, renderElement, o.literal(boundProp.name), oldValue,
|
||||||
|
oldValue.set(evalResult.currValExpr), evalResult.forceUpdate || o.literal(false)
|
||||||
|
])
|
||||||
.toStmt());
|
.toStmt());
|
||||||
break;
|
break;
|
||||||
case PropertyBindingType.Style:
|
case PropertyBindingType.Style:
|
||||||
let strValue: o.Expression = renderValue.callMethod('toString', []);
|
checkStmts.push(
|
||||||
if (isPresent(boundProp.unit)) {
|
o.importExpr(createIdentifier(Identifiers.checkRenderStyle))
|
||||||
strValue = strValue.plus(o.literal(boundProp.unit));
|
.callFn([
|
||||||
}
|
view, renderElement, o.literal(boundProp.name), o.literal(boundProp.unit), oldValue,
|
||||||
|
oldValue.set(evalResult.currValExpr), evalResult.forceUpdate || o.literal(false),
|
||||||
renderValue = renderValue.isBlank().conditional(o.NULL_EXPR, strValue);
|
securityContext
|
||||||
updateStmts.push(
|
])
|
||||||
renderer
|
|
||||||
.callMethod(
|
|
||||||
'setElementStyle', [renderElement, o.literal(boundProp.name), renderValue])
|
|
||||||
.toStmt());
|
.toStmt());
|
||||||
break;
|
break;
|
||||||
case PropertyBindingType.Animation:
|
case PropertyBindingType.Animation:
|
||||||
throw new Error('Illegal state: Should not come here!');
|
throw new Error('Illegal state: Should not come here!');
|
||||||
}
|
}
|
||||||
return updateStmts;
|
return checkStmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sanitizedValue(
|
function calcSecurityContext(
|
||||||
view: o.Expression, boundProp: BoundElementPropertyAst, renderValue: o.Expression,
|
boundProp: BoundElementPropertyAst, securityContextExpression?: o.Expression): o.Expression {
|
||||||
securityContextExpression?: o.Expression): o.Expression {
|
|
||||||
if (boundProp.securityContext === SecurityContext.NONE) {
|
if (boundProp.securityContext === SecurityContext.NONE) {
|
||||||
return renderValue; // No sanitization needed.
|
return o.NULL_EXPR; // No sanitization needed.
|
||||||
}
|
}
|
||||||
if (!boundProp.needsRuntimeSecurityContext) {
|
if (!boundProp.needsRuntimeSecurityContext) {
|
||||||
securityContextExpression =
|
securityContextExpression =
|
||||||
|
@ -84,15 +79,13 @@ function sanitizedValue(
|
||||||
if (!securityContextExpression) {
|
if (!securityContextExpression) {
|
||||||
throw new Error(`internal error, no SecurityContext given ${boundProp.name}`);
|
throw new Error(`internal error, no SecurityContext given ${boundProp.name}`);
|
||||||
}
|
}
|
||||||
const ctx = view.prop('viewUtils').prop('sanitizer');
|
return securityContextExpression;
|
||||||
const args = [securityContextExpression, renderValue];
|
|
||||||
return ctx.callMethod('sanitize', args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function triggerAnimation(
|
export function createCheckAnimationBindingStmts(
|
||||||
view: o.Expression, componentView: o.Expression, boundProp: BoundElementPropertyAst,
|
view: o.Expression, componentView: o.Expression, boundProp: BoundElementPropertyAst,
|
||||||
boundOutputs: BoundEventAst[], eventListener: o.Expression, renderElement: o.Expression,
|
boundOutputs: BoundEventAst[], eventListener: o.Expression, renderElement: o.Expression,
|
||||||
renderValue: o.Expression, lastRenderValue: o.Expression) {
|
oldValue: o.ReadPropExpr, evalResult: ConvertPropertyBindingResult) {
|
||||||
const detachStmts: o.Statement[] = [];
|
const detachStmts: o.Statement[] = [];
|
||||||
const updateStmts: o.Statement[] = [];
|
const updateStmts: o.Statement[] = [];
|
||||||
|
|
||||||
|
@ -104,21 +97,20 @@ export function triggerAnimation(
|
||||||
// it's important to normalize the void value as `void` explicitly
|
// it's important to normalize the void value as `void` explicitly
|
||||||
// so that the styles data can be obtained from the stringmap
|
// so that the styles data can be obtained from the stringmap
|
||||||
const emptyStateValue = o.literal(EMPTY_ANIMATION_STATE);
|
const emptyStateValue = o.literal(EMPTY_ANIMATION_STATE);
|
||||||
const unitializedValue = o.importExpr(createIdentifier(Identifiers.UNINITIALIZED));
|
|
||||||
const animationTransitionVar = o.variable('animationTransition_' + animationName);
|
const animationTransitionVar = o.variable('animationTransition_' + animationName);
|
||||||
|
|
||||||
updateStmts.push(
|
updateStmts.push(
|
||||||
animationTransitionVar
|
animationTransitionVar
|
||||||
.set(animationFnExpr.callFn([
|
.set(animationFnExpr.callFn([
|
||||||
view, renderElement,
|
view, renderElement, isFirstViewCheck(view).conditional(emptyStateValue, oldValue),
|
||||||
lastRenderValue.equals(unitializedValue).conditional(emptyStateValue, lastRenderValue),
|
evalResult.currValExpr
|
||||||
renderValue.equals(unitializedValue).conditional(emptyStateValue, renderValue)
|
|
||||||
]))
|
]))
|
||||||
.toDeclStmt());
|
.toDeclStmt());
|
||||||
|
updateStmts.push(oldValue.set(evalResult.currValExpr).toStmt());
|
||||||
|
|
||||||
detachStmts.push(
|
detachStmts.push(animationTransitionVar
|
||||||
animationTransitionVar
|
.set(animationFnExpr.callFn(
|
||||||
.set(animationFnExpr.callFn([view, renderElement, lastRenderValue, emptyStateValue]))
|
[view, renderElement, evalResult.currValExpr, emptyStateValue]))
|
||||||
.toDeclStmt());
|
.toDeclStmt());
|
||||||
|
|
||||||
const registerStmts: o.Statement[] = [];
|
const registerStmts: o.Statement[] = [];
|
||||||
|
@ -151,5 +143,14 @@ export function triggerAnimation(
|
||||||
updateStmts.push(...registerStmts);
|
updateStmts.push(...registerStmts);
|
||||||
detachStmts.push(...registerStmts);
|
detachStmts.push(...registerStmts);
|
||||||
|
|
||||||
return {updateStmts, detachStmts};
|
const checkUpdateStmts: o.Statement[] = [
|
||||||
|
...evalResult.stmts,
|
||||||
|
new o.IfStmt(
|
||||||
|
o.importExpr(createIdentifier(Identifiers.checkBinding)).callFn([
|
||||||
|
view, oldValue, evalResult.currValExpr, evalResult.forceUpdate || o.literal(false)
|
||||||
|
]),
|
||||||
|
updateStmts)
|
||||||
|
];
|
||||||
|
const checkDetachStmts: o.Statement[] = [...evalResult.stmts, ...detachStmts];
|
||||||
|
return {checkUpdateStmts, checkDetachStmts};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, dirWrapperClassName, identifierModuleUrl, identifierName} from './compile_metadata';
|
import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, dirWrapperClassName, identifierModuleUrl, identifierName} from './compile_metadata';
|
||||||
import {createCheckBindingField, createCheckBindingStmt} from './compiler_util/binding_util';
|
import {createCheckBindingField, isFirstViewCheck} from './compiler_util/binding_util';
|
||||||
import {EventHandlerVars, convertActionBinding, convertPropertyBinding} from './compiler_util/expression_converter';
|
import {EventHandlerVars, convertActionBinding, convertPropertyBinding} from './compiler_util/expression_converter';
|
||||||
import {triggerAnimation, writeToRenderer} from './compiler_util/render_util';
|
import {createCheckAnimationBindingStmts, createCheckRenderBindingStmt} from './compiler_util/render_util';
|
||||||
import {CompilerConfig} from './config';
|
import {CompilerConfig} from './config';
|
||||||
import {Parser} from './expression_parser/parser';
|
import {Parser} from './expression_parser/parser';
|
||||||
import {Identifiers, createIdentifier} from './identifiers';
|
import {Identifiers, createIdentifier} from './identifiers';
|
||||||
|
@ -32,8 +32,8 @@ const CHANGES_FIELD_NAME = '_changes';
|
||||||
const CHANGED_FIELD_NAME = '_changed';
|
const CHANGED_FIELD_NAME = '_changed';
|
||||||
const EVENT_HANDLER_FIELD_NAME = '_eventHandler';
|
const EVENT_HANDLER_FIELD_NAME = '_eventHandler';
|
||||||
|
|
||||||
|
const CHANGE_VAR = o.variable('change');
|
||||||
const CURR_VALUE_VAR = o.variable('currValue');
|
const CURR_VALUE_VAR = o.variable('currValue');
|
||||||
const THROW_ON_CHANGE_VAR = o.variable('throwOnChange');
|
|
||||||
const FORCE_UPDATE_VAR = o.variable('forceUpdate');
|
const FORCE_UPDATE_VAR = o.variable('forceUpdate');
|
||||||
const VIEW_VAR = o.variable('view');
|
const VIEW_VAR = o.variable('view');
|
||||||
const COMPONENT_VIEW_VAR = o.variable('componentView');
|
const COMPONENT_VIEW_VAR = o.variable('componentView');
|
||||||
|
@ -130,8 +130,9 @@ class DirectiveWrapperBuilder implements ClassBuilder {
|
||||||
new o.ClassField(CONTEXT_FIELD_NAME, o.importType(this.dirMeta.type)),
|
new o.ClassField(CONTEXT_FIELD_NAME, o.importType(this.dirMeta.type)),
|
||||||
new o.ClassField(CHANGED_FIELD_NAME, o.BOOL_TYPE, [o.StmtModifier.Private]),
|
new o.ClassField(CHANGED_FIELD_NAME, o.BOOL_TYPE, [o.StmtModifier.Private]),
|
||||||
];
|
];
|
||||||
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 (this.genChanges) {
|
if (this.genChanges) {
|
||||||
fields.push(new o.ClassField(
|
fields.push(new o.ClassField(
|
||||||
CHANGES_FIELD_NAME, new o.MapType(o.DYNAMIC_TYPE), [o.StmtModifier.Private]));
|
CHANGES_FIELD_NAME, new o.MapType(o.DYNAMIC_TYPE), [o.StmtModifier.Private]));
|
||||||
|
@ -180,14 +181,14 @@ function addNgDoCheckMethod(builder: DirectiveWrapperBuilder) {
|
||||||
|
|
||||||
if (builder.ngOnInit) {
|
if (builder.ngOnInit) {
|
||||||
lifecycleStmts.push(new o.IfStmt(
|
lifecycleStmts.push(new o.IfStmt(
|
||||||
VIEW_VAR.prop('numberOfChecks').identical(new o.LiteralExpr(0)),
|
isFirstViewCheck(VIEW_VAR),
|
||||||
[o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).callMethod('ngOnInit', []).toStmt()]));
|
[o.THIS_EXPR.prop(CONTEXT_FIELD_NAME).callMethod('ngOnInit', []).toStmt()]));
|
||||||
}
|
}
|
||||||
if (builder.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) {
|
||||||
stmts.push(new o.IfStmt(o.not(THROW_ON_CHANGE_VAR), lifecycleStmts));
|
stmts.push(new o.IfStmt(o.not(VIEW_VAR.prop('throwOnChange')), lifecycleStmts));
|
||||||
}
|
}
|
||||||
stmts.push(new o.ReturnStatement(changedVar));
|
stmts.push(new o.ReturnStatement(changedVar));
|
||||||
|
|
||||||
|
@ -197,7 +198,6 @@ function addNgDoCheckMethod(builder: DirectiveWrapperBuilder) {
|
||||||
new o.FnParam(
|
new o.FnParam(
|
||||||
VIEW_VAR.name, o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
|
VIEW_VAR.name, o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
|
||||||
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),
|
|
||||||
],
|
],
|
||||||
stmts, o.BOOL_TYPE));
|
stmts, o.BOOL_TYPE));
|
||||||
}
|
}
|
||||||
|
@ -207,24 +207,35 @@ function addCheckInputMethod(input: string, builder: DirectiveWrapperBuilder) {
|
||||||
const onChangeStatements: o.Statement[] = [
|
const 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(),
|
||||||
|
field.expression.set(CURR_VALUE_VAR).toStmt()
|
||||||
];
|
];
|
||||||
|
let methodBody: o.Statement[];
|
||||||
if (builder.genChanges) {
|
if (builder.genChanges) {
|
||||||
onChangeStatements.push(o.THIS_EXPR.prop(CHANGES_FIELD_NAME)
|
onChangeStatements.push(
|
||||||
.key(o.literal(input))
|
o.THIS_EXPR.prop(CHANGES_FIELD_NAME).key(o.literal(input)).set(CHANGE_VAR).toStmt());
|
||||||
.set(o.importExpr(createIdentifier(Identifiers.SimpleChange))
|
methodBody = [
|
||||||
.instantiate([field.expression, CURR_VALUE_VAR]))
|
CHANGE_VAR
|
||||||
.toStmt());
|
.set(o.importExpr(createIdentifier(Identifiers.checkBindingChange)).callFn([
|
||||||
|
VIEW_VAR, field.expression, CURR_VALUE_VAR, FORCE_UPDATE_VAR
|
||||||
|
]))
|
||||||
|
.toDeclStmt(),
|
||||||
|
new o.IfStmt(CHANGE_VAR, onChangeStatements)
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
methodBody = [new o.IfStmt(
|
||||||
|
o.importExpr(createIdentifier(Identifiers.checkBinding)).callFn([
|
||||||
|
VIEW_VAR, field.expression, CURR_VALUE_VAR, FORCE_UPDATE_VAR
|
||||||
|
]),
|
||||||
|
onChangeStatements)];
|
||||||
}
|
}
|
||||||
|
|
||||||
const methodBody: o.Statement[] = createCheckBindingStmt(
|
|
||||||
{currValExpr: CURR_VALUE_VAR, forceUpdate: FORCE_UPDATE_VAR, stmts: []}, field.expression,
|
|
||||||
THROW_ON_CHANGE_VAR, onChangeStatements);
|
|
||||||
builder.methods.push(new o.ClassMethod(
|
builder.methods.push(new o.ClassMethod(
|
||||||
`check_${input}`,
|
`check_${input}`,
|
||||||
[
|
[
|
||||||
|
new o.FnParam(
|
||||||
|
VIEW_VAR.name, o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
|
||||||
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(FORCE_UPDATE_VAR.name, o.BOOL_TYPE)
|
||||||
new o.FnParam(FORCE_UPDATE_VAR.name, o.BOOL_TYPE),
|
|
||||||
],
|
],
|
||||||
methodBody));
|
methodBody));
|
||||||
}
|
}
|
||||||
|
@ -240,7 +251,6 @@ function addCheckHostMethod(
|
||||||
COMPONENT_VIEW_VAR.name,
|
COMPONENT_VIEW_VAR.name,
|
||||||
o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
|
o.importType(createIdentifier(Identifiers.AppView), [o.DYNAMIC_TYPE])),
|
||||||
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),
|
|
||||||
];
|
];
|
||||||
hostProps.forEach((hostProp, hostPropIdx) => {
|
hostProps.forEach((hostProp, hostPropIdx) => {
|
||||||
const field = createCheckBindingField(builder);
|
const field = createCheckBindingField(builder);
|
||||||
|
@ -255,23 +265,18 @@ function addCheckHostMethod(
|
||||||
methodParams.push(new o.FnParam(
|
methodParams.push(new o.FnParam(
|
||||||
securityContextExpr.name, o.importType(createIdentifier(Identifiers.SecurityContext))));
|
securityContextExpr.name, o.importType(createIdentifier(Identifiers.SecurityContext))));
|
||||||
}
|
}
|
||||||
let checkBindingStmts: o.Statement[];
|
|
||||||
if (hostProp.isAnimation) {
|
if (hostProp.isAnimation) {
|
||||||
const {updateStmts, detachStmts} = triggerAnimation(
|
const {checkUpdateStmts, checkDetachStmts} = createCheckAnimationBindingStmts(
|
||||||
VIEW_VAR, COMPONENT_VIEW_VAR, hostProp, hostEvents,
|
VIEW_VAR, COMPONENT_VIEW_VAR, hostProp, hostEvents,
|
||||||
o.THIS_EXPR.prop(EVENT_HANDLER_FIELD_NAME)
|
o.THIS_EXPR.prop(EVENT_HANDLER_FIELD_NAME)
|
||||||
.or(o.importExpr(createIdentifier(Identifiers.noop))),
|
.or(o.importExpr(createIdentifier(Identifiers.noop))),
|
||||||
RENDER_EL_VAR, evalResult.currValExpr, field.expression);
|
RENDER_EL_VAR, field.expression, evalResult);
|
||||||
checkBindingStmts = updateStmts;
|
builder.detachStmts.push(...checkDetachStmts);
|
||||||
builder.detachStmts.push(...detachStmts);
|
stmts.push(...checkUpdateStmts);
|
||||||
} else {
|
} else {
|
||||||
checkBindingStmts = writeToRenderer(
|
stmts.push(...createCheckRenderBindingStmt(
|
||||||
VIEW_VAR, hostProp, RENDER_EL_VAR, evalResult.currValExpr,
|
VIEW_VAR, RENDER_EL_VAR, hostProp, field.expression, evalResult, securityContextExpr));
|
||||||
builder.compilerConfig.logBindingUpdate, securityContextExpr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmts.push(...createCheckBindingStmt(
|
|
||||||
evalResult, field.expression, THROW_ON_CHANGE_VAR, checkBindingStmts));
|
|
||||||
});
|
});
|
||||||
builder.methods.push(new o.ClassMethod('checkHost', methodParams, stmts));
|
builder.methods.push(new o.ClassMethod('checkHost', methodParams, stmts));
|
||||||
}
|
}
|
||||||
|
@ -381,20 +386,19 @@ export class DirectiveWrapperExpressions {
|
||||||
return dirWrapper.prop(CONTEXT_FIELD_NAME);
|
return dirWrapper.prop(CONTEXT_FIELD_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ngDoCheck(
|
static ngDoCheck(dirWrapper: o.Expression, view: o.Expression, renderElement: o.Expression, ):
|
||||||
dirWrapper: o.Expression, view: o.Expression, renderElement: o.Expression,
|
o.Expression {
|
||||||
throwOnChange: o.Expression): o.Expression {
|
return dirWrapper.callMethod('ngDoCheck', [view, renderElement]);
|
||||||
return dirWrapper.callMethod('ngDoCheck', [view, renderElement, throwOnChange]);
|
|
||||||
}
|
}
|
||||||
static checkHost(
|
static checkHost(
|
||||||
hostProps: BoundElementPropertyAst[], dirWrapper: o.Expression, view: o.Expression,
|
hostProps: BoundElementPropertyAst[], dirWrapper: o.Expression, view: o.Expression,
|
||||||
componentView: o.Expression, renderElement: o.Expression, throwOnChange: o.Expression,
|
componentView: o.Expression, renderElement: o.Expression,
|
||||||
runtimeSecurityContexts: o.Expression[]): o.Statement[] {
|
runtimeSecurityContexts: o.Expression[]): o.Statement[] {
|
||||||
if (hostProps.length) {
|
if (hostProps.length) {
|
||||||
return [dirWrapper
|
return [dirWrapper
|
||||||
.callMethod(
|
.callMethod(
|
||||||
'checkHost', [view, componentView, renderElement, throwOnChange].concat(
|
'checkHost',
|
||||||
runtimeSecurityContexts))
|
[view, componentView, renderElement].concat(runtimeSecurityContexts))
|
||||||
.toStmt()];
|
.toStmt()];
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {ANALYZE_FOR_ENTRY_COMPONENTS, AnimationTransitionEvent, ChangeDetectionS
|
||||||
|
|
||||||
import {StaticSymbol} from './aot/static_symbol';
|
import {StaticSymbol} from './aot/static_symbol';
|
||||||
import {CompileIdentifierMetadata, CompileTokenMetadata, identifierModuleUrl, identifierName} from './compile_metadata';
|
import {CompileIdentifierMetadata, CompileTokenMetadata, identifierModuleUrl, identifierName} from './compile_metadata';
|
||||||
import {AnimationGroupPlayer, AnimationKeyframe, AnimationSequencePlayer, AnimationStyles, AnimationTransition, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, ComponentRef_, DebugAppView, DebugContext, NgModuleInjector, NoOpAnimationPlayer, StaticNodeDebugInfo, TemplateRef_, UNINITIALIZED, ValueUnwrapper, ViewContainer, ViewType, balanceAnimationKeyframes, clearStyles, collectAndResolveStyles, devModeEqual, prepareFinalAnimationStyles, reflector, registerModuleFactory, renderStyles, view_utils} from './private_import_core';
|
import {AnimationGroupPlayer, AnimationKeyframe, AnimationSequencePlayer, AnimationStyles, AnimationTransition, AppView, ChangeDetectorStatus, CodegenComponentFactoryResolver, ComponentRef_, DebugAppView, DebugContext, NgModuleInjector, NoOpAnimationPlayer, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewContainer, ViewType, balanceAnimationKeyframes, clearStyles, collectAndResolveStyles, devModeEqual, prepareFinalAnimationStyles, reflector, registerModuleFactory, renderStyles, view_utils} from './private_import_core';
|
||||||
|
|
||||||
const APP_VIEW_MODULE_URL = assetUrl('core', 'linker/view');
|
const APP_VIEW_MODULE_URL = assetUrl('core', 'linker/view');
|
||||||
const VIEW_UTILS_MODULE_URL = assetUrl('core', 'linker/view_utils');
|
const VIEW_UTILS_MODULE_URL = assetUrl('core', 'linker/view_utils');
|
||||||
|
@ -161,8 +161,6 @@ export class Identifiers {
|
||||||
};
|
};
|
||||||
static SimpleChange:
|
static SimpleChange:
|
||||||
IdentifierSpec = {name: 'SimpleChange', moduleUrl: CD_MODULE_URL, runtime: SimpleChange};
|
IdentifierSpec = {name: 'SimpleChange', moduleUrl: CD_MODULE_URL, runtime: SimpleChange};
|
||||||
static UNINITIALIZED:
|
|
||||||
IdentifierSpec = {name: 'UNINITIALIZED', moduleUrl: CD_MODULE_URL, runtime: UNINITIALIZED};
|
|
||||||
static ChangeDetectorStatus: IdentifierSpec = {
|
static ChangeDetectorStatus: IdentifierSpec = {
|
||||||
name: 'ChangeDetectorStatus',
|
name: 'ChangeDetectorStatus',
|
||||||
moduleUrl: CD_MODULE_URL,
|
moduleUrl: CD_MODULE_URL,
|
||||||
|
@ -173,6 +171,36 @@ export class Identifiers {
|
||||||
moduleUrl: VIEW_UTILS_MODULE_URL,
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
runtime: view_utils.checkBinding
|
runtime: view_utils.checkBinding
|
||||||
};
|
};
|
||||||
|
static checkBindingChange: IdentifierSpec = {
|
||||||
|
name: 'checkBindingChange',
|
||||||
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
|
runtime: view_utils.checkBindingChange
|
||||||
|
};
|
||||||
|
static checkRenderText: IdentifierSpec = {
|
||||||
|
name: 'checkRenderText',
|
||||||
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
|
runtime: view_utils.checkRenderText
|
||||||
|
};
|
||||||
|
static checkRenderProperty: IdentifierSpec = {
|
||||||
|
name: 'checkRenderProperty',
|
||||||
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
|
runtime: view_utils.checkRenderProperty
|
||||||
|
};
|
||||||
|
static checkRenderAttribute: IdentifierSpec = {
|
||||||
|
name: 'checkRenderAttribute',
|
||||||
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
|
runtime: view_utils.checkRenderAttribute
|
||||||
|
};
|
||||||
|
static checkRenderClass: IdentifierSpec = {
|
||||||
|
name: 'checkRenderClass',
|
||||||
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
|
runtime: view_utils.checkRenderClass
|
||||||
|
};
|
||||||
|
static checkRenderStyle: IdentifierSpec = {
|
||||||
|
name: 'checkRenderStyle',
|
||||||
|
moduleUrl: VIEW_UTILS_MODULE_URL,
|
||||||
|
runtime: view_utils.checkRenderStyle
|
||||||
|
};
|
||||||
static devModeEqual:
|
static devModeEqual:
|
||||||
IdentifierSpec = {name: 'devModeEqual', moduleUrl: CD_MODULE_URL, runtime: devModeEqual};
|
IdentifierSpec = {name: 'devModeEqual', moduleUrl: CD_MODULE_URL, runtime: devModeEqual};
|
||||||
static inlineInterpolate: IdentifierSpec = {
|
static inlineInterpolate: IdentifierSpec = {
|
||||||
|
|
|
@ -32,7 +32,6 @@ export const view_utils: typeof r.view_utils = r.view_utils;
|
||||||
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;
|
||||||
export const UNINITIALIZED: typeof r.UNINITIALIZED = r.UNINITIALIZED;
|
|
||||||
export const ValueUnwrapper: typeof r.ValueUnwrapper = r.ValueUnwrapper;
|
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;
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
import {AnimationEntryCompileResult} from '../animation/animation_compiler';
|
import {AnimationEntryCompileResult} from '../animation/animation_compiler';
|
||||||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeSummary, tokenName, viewClassName} from '../compile_metadata';
|
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeSummary, tokenName, viewClassName} from '../compile_metadata';
|
||||||
import {EventHandlerVars, NameResolver} from '../compiler_util/expression_converter';
|
import {EventHandlerVars, NameResolver} from '../compiler_util/expression_converter';
|
||||||
import {createPureProxy} from '../compiler_util/identifier_util';
|
|
||||||
import {CompilerConfig} from '../config';
|
import {CompilerConfig} from '../config';
|
||||||
import {isPresent} from '../facade/lang';
|
import {isPresent} from '../facade/lang';
|
||||||
import {Identifiers, createIdentifier} from '../identifiers';
|
import {Identifiers, createIdentifier} from '../identifiers';
|
||||||
|
|
|
@ -47,6 +47,7 @@ export class ViewConstructorVars {
|
||||||
export class ViewProperties {
|
export class ViewProperties {
|
||||||
static renderer = o.THIS_EXPR.prop('renderer');
|
static renderer = o.THIS_EXPR.prop('renderer');
|
||||||
static viewUtils = o.THIS_EXPR.prop('viewUtils');
|
static viewUtils = o.THIS_EXPR.prop('viewUtils');
|
||||||
|
static throwOnChange = o.THIS_EXPR.prop('throwOnChange');
|
||||||
}
|
}
|
||||||
|
|
||||||
export class InjectMethodVars {
|
export class InjectMethodVars {
|
||||||
|
@ -54,9 +55,3 @@ export class InjectMethodVars {
|
||||||
static requestNodeIndex = o.variable('requestNodeIndex');
|
static requestNodeIndex = o.variable('requestNodeIndex');
|
||||||
static notFoundResult = o.variable('notFoundResult');
|
static notFoundResult = o.variable('notFoundResult');
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DetectChangesVars {
|
|
||||||
static throwOnChange = o.variable(`throwOnChange`);
|
|
||||||
static changes = o.variable(`changes`);
|
|
||||||
static changed = o.variable(`changed`);
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {CompileDirectiveSummary, CompilePipeSummary} from '../compile_metadata';
|
import {CompileDirectiveSummary, CompilePipeSummary} from '../compile_metadata';
|
||||||
|
import {isFirstViewCheck} from '../compiler_util/binding_util';
|
||||||
import {DirectiveWrapperExpressions} from '../directive_wrapper_compiler';
|
import {DirectiveWrapperExpressions} from '../directive_wrapper_compiler';
|
||||||
import * as o from '../output/output_ast';
|
import * as o from '../output/output_ast';
|
||||||
import {LifecycleHooks} from '../private_import_core';
|
import {LifecycleHooks} from '../private_import_core';
|
||||||
|
@ -14,10 +15,6 @@ import {DirectiveAst, ProviderAst, ProviderAstType} from '../template_parser/tem
|
||||||
|
|
||||||
import {CompileElement} from './compile_element';
|
import {CompileElement} from './compile_element';
|
||||||
import {CompileView} from './compile_view';
|
import {CompileView} from './compile_view';
|
||||||
import {DetectChangesVars} from './constants';
|
|
||||||
|
|
||||||
const STATE_IS_NEVER_CHECKED = o.THIS_EXPR.prop('numberOfChecks').identical(new o.LiteralExpr(0));
|
|
||||||
const NOT_THROW_ON_CHANGES = o.not(DetectChangesVars.throwOnChange);
|
|
||||||
|
|
||||||
export function bindDirectiveAfterContentLifecycleCallbacks(
|
export function bindDirectiveAfterContentLifecycleCallbacks(
|
||||||
directiveMeta: CompileDirectiveSummary, directiveInstance: o.Expression,
|
directiveMeta: CompileDirectiveSummary, directiveInstance: o.Expression,
|
||||||
|
@ -29,7 +26,8 @@ export function bindDirectiveAfterContentLifecycleCallbacks(
|
||||||
compileElement.nodeIndex, compileElement.sourceAst);
|
compileElement.nodeIndex, compileElement.sourceAst);
|
||||||
if (lifecycleHooks.indexOf(LifecycleHooks.AfterContentInit) !== -1) {
|
if (lifecycleHooks.indexOf(LifecycleHooks.AfterContentInit) !== -1) {
|
||||||
afterContentLifecycleCallbacksMethod.addStmt(new o.IfStmt(
|
afterContentLifecycleCallbacksMethod.addStmt(new o.IfStmt(
|
||||||
STATE_IS_NEVER_CHECKED, [directiveInstance.callMethod('ngAfterContentInit', []).toStmt()]));
|
isFirstViewCheck(o.THIS_EXPR),
|
||||||
|
[directiveInstance.callMethod('ngAfterContentInit', []).toStmt()]));
|
||||||
}
|
}
|
||||||
if (lifecycleHooks.indexOf(LifecycleHooks.AfterContentChecked) !== -1) {
|
if (lifecycleHooks.indexOf(LifecycleHooks.AfterContentChecked) !== -1) {
|
||||||
afterContentLifecycleCallbacksMethod.addStmt(
|
afterContentLifecycleCallbacksMethod.addStmt(
|
||||||
|
@ -47,7 +45,8 @@ export function bindDirectiveAfterViewLifecycleCallbacks(
|
||||||
compileElement.nodeIndex, compileElement.sourceAst);
|
compileElement.nodeIndex, compileElement.sourceAst);
|
||||||
if (lifecycleHooks.indexOf(LifecycleHooks.AfterViewInit) !== -1) {
|
if (lifecycleHooks.indexOf(LifecycleHooks.AfterViewInit) !== -1) {
|
||||||
afterViewLifecycleCallbacksMethod.addStmt(new o.IfStmt(
|
afterViewLifecycleCallbacksMethod.addStmt(new o.IfStmt(
|
||||||
STATE_IS_NEVER_CHECKED, [directiveInstance.callMethod('ngAfterViewInit', []).toStmt()]));
|
isFirstViewCheck(o.THIS_EXPR),
|
||||||
|
[directiveInstance.callMethod('ngAfterViewInit', []).toStmt()]));
|
||||||
}
|
}
|
||||||
if (lifecycleHooks.indexOf(LifecycleHooks.AfterViewChecked) !== -1) {
|
if (lifecycleHooks.indexOf(LifecycleHooks.AfterViewChecked) !== -1) {
|
||||||
afterViewLifecycleCallbacksMethod.addStmt(
|
afterViewLifecycleCallbacksMethod.addStmt(
|
||||||
|
|
|
@ -8,19 +8,19 @@
|
||||||
|
|
||||||
import {SecurityContext} from '@angular/core';
|
import {SecurityContext} from '@angular/core';
|
||||||
|
|
||||||
import {createCheckBindingField, createCheckBindingStmt} from '../compiler_util/binding_util';
|
import {createCheckBindingField} from '../compiler_util/binding_util';
|
||||||
import {ConvertPropertyBindingResult, convertPropertyBinding} from '../compiler_util/expression_converter';
|
import {ConvertPropertyBindingResult, convertPropertyBinding} from '../compiler_util/expression_converter';
|
||||||
import {createEnumExpression} from '../compiler_util/identifier_util';
|
import {createEnumExpression} from '../compiler_util/identifier_util';
|
||||||
import {triggerAnimation, writeToRenderer} from '../compiler_util/render_util';
|
import {createCheckAnimationBindingStmts, createCheckRenderBindingStmt} from '../compiler_util/render_util';
|
||||||
import {DirectiveWrapperExpressions} from '../directive_wrapper_compiler';
|
import {DirectiveWrapperExpressions} from '../directive_wrapper_compiler';
|
||||||
import {Identifiers, createIdentifier} from '../identifiers';
|
import {Identifiers, createIdentifier} from '../identifiers';
|
||||||
import * as o from '../output/output_ast';
|
import * as o from '../output/output_ast';
|
||||||
import {isDefaultChangeDetectionStrategy} from '../private_import_core';
|
import {isDefaultChangeDetectionStrategy} from '../private_import_core';
|
||||||
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
|
import {ElementSchemaRegistry} from '../schema/element_schema_registry';
|
||||||
import {BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, PropertyBindingType} from '../template_parser/template_ast';
|
import {BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, PropertyBindingType} from '../template_parser/template_ast';
|
||||||
|
|
||||||
import {CompileElement, CompileNode} from './compile_element';
|
import {CompileElement, CompileNode} from './compile_element';
|
||||||
import {CompileView} from './compile_view';
|
import {CompileView} from './compile_view';
|
||||||
import {DetectChangesVars} from './constants';
|
|
||||||
import {getHandleEventMethodName} from './util';
|
import {getHandleEventMethodName} from './util';
|
||||||
|
|
||||||
export function bindRenderText(
|
export function bindRenderText(
|
||||||
|
@ -33,11 +33,15 @@ export function bindRenderText(
|
||||||
}
|
}
|
||||||
|
|
||||||
view.detectChangesRenderPropertiesMethod.resetDebugInfo(compileNode.nodeIndex, boundText);
|
view.detectChangesRenderPropertiesMethod.resetDebugInfo(compileNode.nodeIndex, boundText);
|
||||||
view.detectChangesRenderPropertiesMethod.addStmts(createCheckBindingStmt(
|
view.detectChangesRenderPropertiesMethod.addStmts(evalResult.stmts);
|
||||||
evalResult, valueField.expression, DetectChangesVars.throwOnChange,
|
view.detectChangesRenderPropertiesMethod.addStmt(
|
||||||
[o.THIS_EXPR.prop('renderer')
|
o.importExpr(createIdentifier(Identifiers.checkRenderText))
|
||||||
.callMethod('setText', [compileNode.renderNode, evalResult.currValExpr])
|
.callFn([
|
||||||
.toStmt()]));
|
o.THIS_EXPR, compileNode.renderNode, valueField.expression,
|
||||||
|
valueField.expression.set(evalResult.currValExpr),
|
||||||
|
evalResult.forceUpdate || o.literal(false)
|
||||||
|
])
|
||||||
|
.toStmt());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function bindRenderInputs(
|
export function bindRenderInputs(
|
||||||
|
@ -54,31 +58,27 @@ export function bindRenderInputs(
|
||||||
if (!evalResult) {
|
if (!evalResult) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const checkBindingStmts: o.Statement[] = [];
|
|
||||||
let compileMethod = view.detectChangesRenderPropertiesMethod;
|
let compileMethod = view.detectChangesRenderPropertiesMethod;
|
||||||
switch (boundProp.type) {
|
switch (boundProp.type) {
|
||||||
case PropertyBindingType.Property:
|
case PropertyBindingType.Property:
|
||||||
case PropertyBindingType.Attribute:
|
case PropertyBindingType.Attribute:
|
||||||
case PropertyBindingType.Class:
|
case PropertyBindingType.Class:
|
||||||
case PropertyBindingType.Style:
|
case PropertyBindingType.Style:
|
||||||
checkBindingStmts.push(...writeToRenderer(
|
compileMethod.addStmts(createCheckRenderBindingStmt(
|
||||||
o.THIS_EXPR, boundProp, renderNode, evalResult.currValExpr,
|
o.THIS_EXPR, renderNode, boundProp, bindingField.expression, evalResult));
|
||||||
view.genConfig.logBindingUpdate));
|
|
||||||
break;
|
break;
|
||||||
case PropertyBindingType.Animation:
|
case PropertyBindingType.Animation:
|
||||||
compileMethod = view.animationBindingsMethod;
|
compileMethod = view.animationBindingsMethod;
|
||||||
const {updateStmts, detachStmts} = triggerAnimation(
|
const {checkUpdateStmts, checkDetachStmts} = createCheckAnimationBindingStmts(
|
||||||
o.THIS_EXPR, o.THIS_EXPR, boundProp, boundOutputs,
|
o.THIS_EXPR, o.THIS_EXPR, boundProp, boundOutputs,
|
||||||
(hasEvents ? o.THIS_EXPR.prop(getHandleEventMethodName(compileElement.nodeIndex)) :
|
(hasEvents ? o.THIS_EXPR.prop(getHandleEventMethodName(compileElement.nodeIndex)) :
|
||||||
o.importExpr(createIdentifier(Identifiers.noop)))
|
o.importExpr(createIdentifier(Identifiers.noop)))
|
||||||
.callMethod(o.BuiltinMethod.Bind, [o.THIS_EXPR]),
|
.callMethod(o.BuiltinMethod.Bind, [o.THIS_EXPR]),
|
||||||
compileElement.renderNode, evalResult.currValExpr, bindingField.expression);
|
compileElement.renderNode, bindingField.expression, evalResult);
|
||||||
checkBindingStmts.push(...updateStmts);
|
view.detachMethod.addStmts(checkDetachStmts);
|
||||||
view.detachMethod.addStmts(detachStmts);
|
compileMethod.addStmts(checkUpdateStmts);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
compileMethod.addStmts(createCheckBindingStmt(
|
|
||||||
evalResult, bindingField.expression, DetectChangesVars.throwOnChange, checkBindingStmts));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ export function bindDirectiveHostProps(
|
||||||
DirectiveWrapperExpressions.checkHost(
|
DirectiveWrapperExpressions.checkHost(
|
||||||
directiveAst.hostProperties, directiveWrapperInstance, o.THIS_EXPR,
|
directiveAst.hostProperties, directiveWrapperInstance, o.THIS_EXPR,
|
||||||
compileElement.compViewExpr || o.THIS_EXPR, compileElement.renderNode,
|
compileElement.compViewExpr || o.THIS_EXPR, compileElement.renderNode,
|
||||||
DetectChangesVars.throwOnChange, runtimeSecurityCtxExprs));
|
runtimeSecurityCtxExprs));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function bindDirectiveInputs(
|
export function bindDirectiveInputs(
|
||||||
|
@ -132,17 +132,13 @@ export function bindDirectiveInputs(
|
||||||
directiveWrapperInstance
|
directiveWrapperInstance
|
||||||
.callMethod(
|
.callMethod(
|
||||||
`check_${input.directiveName}`,
|
`check_${input.directiveName}`,
|
||||||
[
|
[o.THIS_EXPR, evalResult.currValExpr, evalResult.forceUpdate || o.literal(false)])
|
||||||
evalResult.currValExpr, DetectChangesVars.throwOnChange,
|
|
||||||
evalResult.forceUpdate || o.literal(false)
|
|
||||||
])
|
|
||||||
.toStmt());
|
.toStmt());
|
||||||
});
|
});
|
||||||
const isOnPushComp = directiveAst.directive.isComponent &&
|
const isOnPushComp = directiveAst.directive.isComponent &&
|
||||||
!isDefaultChangeDetectionStrategy(directiveAst.directive.changeDetection);
|
!isDefaultChangeDetectionStrategy(directiveAst.directive.changeDetection);
|
||||||
const directiveDetectChangesExpr = DirectiveWrapperExpressions.ngDoCheck(
|
const directiveDetectChangesExpr = DirectiveWrapperExpressions.ngDoCheck(
|
||||||
directiveWrapperInstance, o.THIS_EXPR, compileElement.renderNode,
|
directiveWrapperInstance, o.THIS_EXPR, compileElement.renderNode);
|
||||||
DetectChangesVars.throwOnChange);
|
|
||||||
const directiveDetectChangesStmt = isOnPushComp ?
|
const directiveDetectChangesStmt = isOnPushComp ?
|
||||||
new o.IfStmt(
|
new o.IfStmt(
|
||||||
directiveDetectChangesExpr,
|
directiveDetectChangesExpr,
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventA
|
||||||
|
|
||||||
import {CompileElement, CompileNode} from './compile_element';
|
import {CompileElement, CompileNode} from './compile_element';
|
||||||
import {CompileView, CompileViewRootNode, CompileViewRootNodeType} from './compile_view';
|
import {CompileView, CompileViewRootNode, CompileViewRootNodeType} from './compile_view';
|
||||||
import {ChangeDetectorStatusEnum, DetectChangesVars, InjectMethodVars, ViewConstructorVars, ViewEncapsulationEnum, ViewProperties, ViewTypeEnum} from './constants';
|
import {ChangeDetectorStatusEnum, InjectMethodVars, ViewConstructorVars, ViewEncapsulationEnum, ViewProperties, ViewTypeEnum} from './constants';
|
||||||
import {ComponentFactoryDependency, ComponentViewDependency, DirectiveWrapperDependency} from './deps';
|
import {ComponentFactoryDependency, ComponentViewDependency, DirectiveWrapperDependency} from './deps';
|
||||||
|
|
||||||
const IMPLICIT_TEMPLATE_VAR = '\$implicit';
|
const IMPLICIT_TEMPLATE_VAR = '\$implicit';
|
||||||
|
@ -483,9 +483,7 @@ function createViewClass(
|
||||||
],
|
],
|
||||||
addReturnValuefNotEmpty(view.injectorGetMethod.finish(), InjectMethodVars.notFoundResult),
|
addReturnValuefNotEmpty(view.injectorGetMethod.finish(), InjectMethodVars.notFoundResult),
|
||||||
o.DYNAMIC_TYPE),
|
o.DYNAMIC_TYPE),
|
||||||
new o.ClassMethod(
|
new o.ClassMethod('detectChangesInternal', [], generateDetectChangesMethod(view)),
|
||||||
'detectChangesInternal', [new o.FnParam(DetectChangesVars.throwOnChange.name, o.BOOL_TYPE)],
|
|
||||||
generateDetectChangesMethod(view)),
|
|
||||||
new o.ClassMethod('dirtyParentQueriesInternal', [], view.dirtyParentQueriesMethod.finish()),
|
new o.ClassMethod('dirtyParentQueriesInternal', [], view.dirtyParentQueriesMethod.finish()),
|
||||||
new o.ClassMethod('destroyInternal', [], generateDestroyMethod(view)),
|
new o.ClassMethod('destroyInternal', [], generateDestroyMethod(view)),
|
||||||
new o.ClassMethod('detachInternal', [], view.detachMethod.finish()),
|
new o.ClassMethod('detachInternal', [], view.detachMethod.finish()),
|
||||||
|
@ -569,36 +567,26 @@ function generateDetectChangesMethod(view: CompileView): o.Statement[] {
|
||||||
stmts.push(...view.detectChangesInInputsMethod.finish());
|
stmts.push(...view.detectChangesInInputsMethod.finish());
|
||||||
view.viewContainers.forEach((viewContainer) => {
|
view.viewContainers.forEach((viewContainer) => {
|
||||||
stmts.push(
|
stmts.push(
|
||||||
viewContainer.callMethod('detectChangesInNestedViews', [DetectChangesVars.throwOnChange])
|
viewContainer.callMethod('detectChangesInNestedViews', [ViewProperties.throwOnChange])
|
||||||
.toStmt());
|
.toStmt());
|
||||||
});
|
});
|
||||||
const afterContentStmts = view.updateContentQueriesMethod.finish().concat(
|
const afterContentStmts = view.updateContentQueriesMethod.finish().concat(
|
||||||
view.afterContentLifecycleCallbacksMethod.finish());
|
view.afterContentLifecycleCallbacksMethod.finish());
|
||||||
if (afterContentStmts.length > 0) {
|
if (afterContentStmts.length > 0) {
|
||||||
stmts.push(new o.IfStmt(o.not(DetectChangesVars.throwOnChange), afterContentStmts));
|
stmts.push(new o.IfStmt(o.not(ViewProperties.throwOnChange), afterContentStmts));
|
||||||
}
|
}
|
||||||
stmts.push(...view.detectChangesRenderPropertiesMethod.finish());
|
stmts.push(...view.detectChangesRenderPropertiesMethod.finish());
|
||||||
view.viewChildren.forEach((viewChild) => {
|
view.viewChildren.forEach((viewChild) => {
|
||||||
stmts.push(
|
stmts.push(
|
||||||
viewChild.callMethod('internalDetectChanges', [DetectChangesVars.throwOnChange]).toStmt());
|
viewChild.callMethod('internalDetectChanges', [ViewProperties.throwOnChange]).toStmt());
|
||||||
});
|
});
|
||||||
const afterViewStmts =
|
const afterViewStmts =
|
||||||
view.updateViewQueriesMethod.finish().concat(view.afterViewLifecycleCallbacksMethod.finish());
|
view.updateViewQueriesMethod.finish().concat(view.afterViewLifecycleCallbacksMethod.finish());
|
||||||
if (afterViewStmts.length > 0) {
|
if (afterViewStmts.length > 0) {
|
||||||
stmts.push(new o.IfStmt(o.not(DetectChangesVars.throwOnChange), afterViewStmts));
|
stmts.push(new o.IfStmt(o.not(ViewProperties.throwOnChange), afterViewStmts));
|
||||||
}
|
}
|
||||||
|
|
||||||
const varStmts: any[] = [];
|
const varStmts = createSharedBindingVariablesIfNeeded(stmts);
|
||||||
const readVars = o.findReadVarNames(stmts);
|
|
||||||
if (readVars.has(DetectChangesVars.changed.name)) {
|
|
||||||
varStmts.push(DetectChangesVars.changed.set(o.literal(true)).toDeclStmt(o.BOOL_TYPE));
|
|
||||||
}
|
|
||||||
if (readVars.has(DetectChangesVars.changes.name)) {
|
|
||||||
varStmts.push(
|
|
||||||
DetectChangesVars.changes.set(o.NULL_EXPR)
|
|
||||||
.toDeclStmt(new o.MapType(o.importType(createIdentifier(Identifiers.SimpleChange)))));
|
|
||||||
}
|
|
||||||
varStmts.push(...createSharedBindingVariablesIfNeeded(stmts));
|
|
||||||
return varStmts.concat(stmts);
|
return varStmts.concat(stmts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {IterableDifferFactory, IterableDiffers} from './differs/iterable_differs
|
||||||
import {KeyValueDifferFactory, KeyValueDiffers} from './differs/keyvalue_differs';
|
import {KeyValueDifferFactory, KeyValueDiffers} from './differs/keyvalue_differs';
|
||||||
|
|
||||||
export {SimpleChanges} from '../metadata/lifecycle_hooks';
|
export {SimpleChanges} from '../metadata/lifecycle_hooks';
|
||||||
export {SimpleChange, UNINITIALIZED, ValueUnwrapper, WrappedValue, devModeEqual, looseIdentical} from './change_detection_util';
|
export {SimpleChange, ValueUnwrapper, WrappedValue, devModeEqual, looseIdentical} from './change_detection_util';
|
||||||
export {ChangeDetectorRef} from './change_detector_ref';
|
export {ChangeDetectorRef} from './change_detector_ref';
|
||||||
export {ChangeDetectionStrategy, ChangeDetectorStatus, isDefaultChangeDetectionStrategy} from './constants';
|
export {ChangeDetectionStrategy, ChangeDetectorStatus, isDefaultChangeDetectionStrategy} from './constants';
|
||||||
export {CollectionChangeRecord, DefaultIterableDifferFactory} from './differs/default_iterable_differ';
|
export {CollectionChangeRecord, DefaultIterableDifferFactory} from './differs/default_iterable_differ';
|
||||||
|
|
|
@ -11,10 +11,6 @@ import {isPrimitive, looseIdentical} from '../facade/lang';
|
||||||
|
|
||||||
export {looseIdentical} from '../facade/lang';
|
export {looseIdentical} from '../facade/lang';
|
||||||
|
|
||||||
export const UNINITIALIZED = {
|
|
||||||
toString: () => 'CD_INIT_VALUE'
|
|
||||||
};
|
|
||||||
|
|
||||||
export function devModeEqual(a: any, b: any): boolean {
|
export function devModeEqual(a: any, b: any): boolean {
|
||||||
if (isListLikeIterable(a) && isListLikeIterable(b)) {
|
if (isListLikeIterable(a) && isListLikeIterable(b)) {
|
||||||
return areIterablesEqual(a, b, devModeEqual);
|
return areIterablesEqual(a, b, devModeEqual);
|
||||||
|
@ -75,10 +71,15 @@ export class ValueUnwrapper {
|
||||||
* @stable
|
* @stable
|
||||||
*/
|
*/
|
||||||
export class SimpleChange {
|
export class SimpleChange {
|
||||||
constructor(public previousValue: any, public currentValue: any) {}
|
constructor(
|
||||||
|
public previousValue: any, public currentValue: any, _isFirstChange: boolean = false) {
|
||||||
|
// Store this in a non declared field
|
||||||
|
// to prevent a breaking change (users might have `implement`ed SimpleChange before)
|
||||||
|
(<any>this)._firstChange = _isFirstChange;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the new value is the first value assigned.
|
* Check whether the new value is the first value assigned.
|
||||||
*/
|
*/
|
||||||
isFirstChange(): boolean { return this.previousValue === UNINITIALIZED; }
|
isFirstChange(): boolean { return (<any>this)._firstChange; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,6 @@ export const __core_private__: {
|
||||||
StaticNodeDebugInfo: typeof debug_context.StaticNodeDebugInfo,
|
StaticNodeDebugInfo: typeof debug_context.StaticNodeDebugInfo,
|
||||||
_StaticNodeDebugInfo?: debug_context.StaticNodeDebugInfo,
|
_StaticNodeDebugInfo?: debug_context.StaticNodeDebugInfo,
|
||||||
devModeEqual: typeof change_detection_util.devModeEqual,
|
devModeEqual: typeof change_detection_util.devModeEqual,
|
||||||
UNINITIALIZED: typeof change_detection_util.UNINITIALIZED,
|
|
||||||
ValueUnwrapper: typeof change_detection_util.ValueUnwrapper,
|
ValueUnwrapper: typeof change_detection_util.ValueUnwrapper,
|
||||||
_ValueUnwrapper?: change_detection_util.ValueUnwrapper,
|
_ValueUnwrapper?: change_detection_util.ValueUnwrapper,
|
||||||
RenderDebugInfo: typeof api.RenderDebugInfo,
|
RenderDebugInfo: typeof api.RenderDebugInfo,
|
||||||
|
@ -130,7 +129,6 @@ export const __core_private__: {
|
||||||
DebugContext: debug_context.DebugContext,
|
DebugContext: debug_context.DebugContext,
|
||||||
StaticNodeDebugInfo: debug_context.StaticNodeDebugInfo,
|
StaticNodeDebugInfo: debug_context.StaticNodeDebugInfo,
|
||||||
devModeEqual: change_detection_util.devModeEqual,
|
devModeEqual: change_detection_util.devModeEqual,
|
||||||
UNINITIALIZED: change_detection_util.UNINITIALIZED,
|
|
||||||
ValueUnwrapper: change_detection_util.ValueUnwrapper,
|
ValueUnwrapper: change_detection_util.ValueUnwrapper,
|
||||||
RenderDebugInfo: api.RenderDebugInfo,
|
RenderDebugInfo: api.RenderDebugInfo,
|
||||||
TemplateRef_: template_ref.TemplateRef_,
|
TemplateRef_: template_ref.TemplateRef_,
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {UNINITIALIZED} from '../change_detection/change_detection_util';
|
|
||||||
import {BaseError, WrappedError} from '../facade/errors';
|
import {BaseError, WrappedError} from '../facade/errors';
|
||||||
|
|
||||||
import {DebugContext} from './debug_context';
|
import {DebugContext} from './debug_context';
|
||||||
|
@ -45,10 +44,10 @@ import {DebugContext} from './debug_context';
|
||||||
* @stable
|
* @stable
|
||||||
*/
|
*/
|
||||||
export class ExpressionChangedAfterItHasBeenCheckedError extends BaseError {
|
export class ExpressionChangedAfterItHasBeenCheckedError extends BaseError {
|
||||||
constructor(oldValue: any, currValue: any) {
|
constructor(oldValue: any, currValue: any, isFirstCheck: boolean) {
|
||||||
let msg =
|
let msg =
|
||||||
`Expression has changed after it was checked. Previous value: '${oldValue}'. Current value: '${currValue}'.`;
|
`Expression has changed after it was checked. Previous value: '${oldValue}'. Current value: '${currValue}'.`;
|
||||||
if (oldValue === UNINITIALIZED) {
|
if (isFirstCheck) {
|
||||||
msg +=
|
msg +=
|
||||||
` It seems like the view has been created after its parent and its children have been dirty checked.` +
|
` It seems like the view has been created after its parent and its children have been dirty checked.` +
|
||||||
` Has it been created in a change detection hook ?`;
|
` Has it been created in a change detection hook ?`;
|
||||||
|
|
|
@ -47,6 +47,7 @@ export abstract class AppView<T> {
|
||||||
appRef: ApplicationRef;
|
appRef: ApplicationRef;
|
||||||
|
|
||||||
numberOfChecks: number = 0;
|
numberOfChecks: number = 0;
|
||||||
|
throwOnChange: boolean = false;
|
||||||
|
|
||||||
renderer: Renderer;
|
renderer: Renderer;
|
||||||
|
|
||||||
|
@ -326,7 +327,8 @@ export abstract class AppView<T> {
|
||||||
if (this.cdMode === ChangeDetectorStatus.Destroyed) {
|
if (this.cdMode === ChangeDetectorStatus.Destroyed) {
|
||||||
this.throwDestroyedError('detectChanges');
|
this.throwDestroyedError('detectChanges');
|
||||||
}
|
}
|
||||||
this.detectChangesInternal(throwOnChange);
|
this.throwOnChange = throwOnChange;
|
||||||
|
this.detectChangesInternal();
|
||||||
if (this.cdMode === ChangeDetectorStatus.CheckOnce) this.cdMode = ChangeDetectorStatus.Checked;
|
if (this.cdMode === ChangeDetectorStatus.CheckOnce) this.cdMode = ChangeDetectorStatus.Checked;
|
||||||
|
|
||||||
this.numberOfChecks++;
|
this.numberOfChecks++;
|
||||||
|
@ -336,7 +338,7 @@ export abstract class AppView<T> {
|
||||||
/**
|
/**
|
||||||
* Overwritten by implementations
|
* Overwritten by implementations
|
||||||
*/
|
*/
|
||||||
detectChangesInternal(throwOnChange: boolean): void {}
|
detectChangesInternal(): void {}
|
||||||
|
|
||||||
markAsCheckOnce(): void { this.cdMode = ChangeDetectorStatus.CheckOnce; }
|
markAsCheckOnce(): void { this.cdMode = ChangeDetectorStatus.CheckOnce; }
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,11 @@
|
||||||
|
|
||||||
import {AnimationQueue} from '../animation/animation_queue';
|
import {AnimationQueue} from '../animation/animation_queue';
|
||||||
import {SimpleChange, devModeEqual} from '../change_detection/change_detection';
|
import {SimpleChange, devModeEqual} from '../change_detection/change_detection';
|
||||||
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, RenderDebugInfo, Renderer, RootRenderer} from '../render/api';
|
import {RenderComponentType, RenderDebugInfo, Renderer, RootRenderer} from '../render/api';
|
||||||
import {Sanitizer} from '../security';
|
import {Sanitizer, SecurityContext} from '../security';
|
||||||
import {Type} from '../type';
|
import {Type} from '../type';
|
||||||
import {VERSION} from '../version';
|
import {VERSION} from '../version';
|
||||||
import {NgZone} from '../zone/ng_zone';
|
import {NgZone} from '../zone/ng_zone';
|
||||||
|
@ -102,14 +101,77 @@ function _toStringWithNull(v: any): string {
|
||||||
return v != null ? v.toString() : '';
|
return v != null ? v.toString() : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkBinding(throwOnChange: boolean, oldValue: any, newValue: any): boolean {
|
export function checkBinding(
|
||||||
if (throwOnChange) {
|
view: AppView<any>, oldValue: any, newValue: any, forceUpdate: boolean): boolean {
|
||||||
if (!devModeEqual(oldValue, newValue)) {
|
const isFirstCheck = view.numberOfChecks === 0;
|
||||||
throw new ExpressionChangedAfterItHasBeenCheckedError(oldValue, newValue);
|
if (view.throwOnChange) {
|
||||||
|
if (isFirstCheck || !devModeEqual(oldValue, newValue)) {
|
||||||
|
throw new ExpressionChangedAfterItHasBeenCheckedError(oldValue, newValue, isFirstCheck);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return !looseIdentical(oldValue, newValue);
|
return isFirstCheck || forceUpdate || !looseIdentical(oldValue, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkBindingChange(
|
||||||
|
view: AppView<any>, oldValue: any, newValue: any, forceUpdate: boolean): SimpleChange {
|
||||||
|
if (checkBinding(view, oldValue, newValue, forceUpdate)) {
|
||||||
|
return new SimpleChange(oldValue, newValue, view.numberOfChecks === 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkRenderText(
|
||||||
|
view: AppView<any>, renderElement: any, oldValue: any, newValue: any, forceUpdate: boolean) {
|
||||||
|
if (checkBinding(view, oldValue, newValue, forceUpdate)) {
|
||||||
|
view.renderer.setText(renderElement, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkRenderProperty(
|
||||||
|
view: AppView<any>, renderElement: any, propName: string, oldValue: any, newValue: any,
|
||||||
|
forceUpdate: boolean, securityContext: SecurityContext) {
|
||||||
|
if (checkBinding(view, oldValue, newValue, forceUpdate)) {
|
||||||
|
let renderValue =
|
||||||
|
securityContext ? view.viewUtils.sanitizer.sanitize(securityContext, newValue) : newValue;
|
||||||
|
view.renderer.setElementProperty(renderElement, propName, renderValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkRenderAttribute(
|
||||||
|
view: AppView<any>, renderElement: any, attrName: string, oldValue: any, newValue: any,
|
||||||
|
forceUpdate: boolean, securityContext: SecurityContext) {
|
||||||
|
if (checkBinding(view, oldValue, newValue, forceUpdate)) {
|
||||||
|
let renderValue =
|
||||||
|
securityContext ? view.viewUtils.sanitizer.sanitize(securityContext, newValue) : newValue;
|
||||||
|
renderValue = renderValue != null ? renderValue.toString() : null;
|
||||||
|
view.renderer.setElementAttribute(renderElement, attrName, renderValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkRenderClass(
|
||||||
|
view: AppView<any>, renderElement: any, className: string, oldValue: any, newValue: any,
|
||||||
|
forceUpdate: boolean) {
|
||||||
|
if (checkBinding(view, oldValue, newValue, forceUpdate)) {
|
||||||
|
view.renderer.setElementClass(renderElement, className, newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function checkRenderStyle(
|
||||||
|
view: AppView<any>, renderElement: any, styleName: string, unit: string, oldValue: any,
|
||||||
|
newValue: any, forceUpdate: boolean, securityContext: SecurityContext) {
|
||||||
|
if (checkBinding(view, oldValue, newValue, forceUpdate)) {
|
||||||
|
let renderValue =
|
||||||
|
securityContext ? view.viewUtils.sanitizer.sanitize(securityContext, newValue) : newValue;
|
||||||
|
if (renderValue != null) {
|
||||||
|
renderValue = renderValue.toString();
|
||||||
|
if (unit != null) {
|
||||||
|
renderValue = renderValue + unit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
renderValue = null;
|
||||||
|
}
|
||||||
|
view.renderer.setElementStyle(renderElement, styleName, renderValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,11 +183,12 @@ export const EMPTY_ARRAY: any[] = [];
|
||||||
export const EMPTY_MAP = {};
|
export const EMPTY_MAP = {};
|
||||||
|
|
||||||
export function pureProxy1<P0, R>(fn: (p0: P0) => R): (p0: P0) => R {
|
export function pureProxy1<P0, R>(fn: (p0: P0) => R): (p0: P0) => R {
|
||||||
|
let numberOfChecks = 0;
|
||||||
let result: R;
|
let result: R;
|
||||||
let v0: any = UNINITIALIZED;
|
let v0: any;
|
||||||
|
|
||||||
return (p0) => {
|
return (p0) => {
|
||||||
if (!looseIdentical(v0, p0)) {
|
if (!numberOfChecks++ || !looseIdentical(v0, p0)) {
|
||||||
v0 = p0;
|
v0 = p0;
|
||||||
result = fn(p0);
|
result = fn(p0);
|
||||||
}
|
}
|
||||||
|
@ -134,12 +197,13 @@ export function pureProxy1<P0, R>(fn: (p0: P0) => R): (p0: P0) => R {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pureProxy2<P0, P1, R>(fn: (p0: P0, p1: P1) => R): (p0: P0, p1: P1) => R {
|
export function pureProxy2<P0, P1, R>(fn: (p0: P0, p1: P1) => R): (p0: P0, p1: P1) => R {
|
||||||
|
let numberOfChecks = 0;
|
||||||
let result: R;
|
let result: R;
|
||||||
let v0: any = UNINITIALIZED;
|
let v0: any;
|
||||||
let v1: any = UNINITIALIZED;
|
let v1: any;
|
||||||
|
|
||||||
return (p0, p1) => {
|
return (p0, p1) => {
|
||||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1)) {
|
if (!numberOfChecks++ || !looseIdentical(v0, p0) || !looseIdentical(v1, p1)) {
|
||||||
v0 = p0;
|
v0 = p0;
|
||||||
v1 = p1;
|
v1 = p1;
|
||||||
result = fn(p0, p1);
|
result = fn(p0, p1);
|
||||||
|
@ -150,13 +214,15 @@ export function pureProxy2<P0, P1, R>(fn: (p0: P0, p1: P1) => R): (p0: P0, p1: P
|
||||||
|
|
||||||
export function pureProxy3<P0, P1, P2, R>(fn: (p0: P0, p1: P1, p2: P2) => R): (
|
export function pureProxy3<P0, P1, P2, R>(fn: (p0: P0, p1: P1, p2: P2) => R): (
|
||||||
p0: P0, p1: P1, p2: P2) => R {
|
p0: P0, p1: P1, p2: P2) => R {
|
||||||
|
let numberOfChecks = 0;
|
||||||
let result: R;
|
let result: R;
|
||||||
let v0: any = UNINITIALIZED;
|
let v0: any;
|
||||||
let v1: any = UNINITIALIZED;
|
let v1: any;
|
||||||
let v2: any = UNINITIALIZED;
|
let v2: any;
|
||||||
|
|
||||||
return (p0, p1, p2) => {
|
return (p0, p1, p2) => {
|
||||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2)) {
|
if (!numberOfChecks++ || !looseIdentical(v0, p0) || !looseIdentical(v1, p1) ||
|
||||||
|
!looseIdentical(v2, p2)) {
|
||||||
v0 = p0;
|
v0 = p0;
|
||||||
v1 = p1;
|
v1 = p1;
|
||||||
v2 = p2;
|
v2 = p2;
|
||||||
|
@ -168,12 +234,13 @@ export function pureProxy3<P0, P1, P2, R>(fn: (p0: P0, p1: P1, p2: P2) => R): (
|
||||||
|
|
||||||
export function pureProxy4<P0, P1, P2, P3, R>(fn: (p0: P0, p1: P1, p2: P2, p3: P3) => R): (
|
export function pureProxy4<P0, P1, P2, P3, R>(fn: (p0: P0, p1: P1, p2: P2, p3: P3) => R): (
|
||||||
p0: P0, p1: P1, p2: P2, p3: P3) => R {
|
p0: P0, p1: P1, p2: P2, p3: P3) => R {
|
||||||
|
let numberOfChecks = 0;
|
||||||
let result: R;
|
let result: R;
|
||||||
let v0: any, v1: any, v2: any, v3: any;
|
let v0: any, v1: any, v2: any, v3: any;
|
||||||
v0 = v1 = v2 = v3 = UNINITIALIZED;
|
v0 = v1 = v2 = v3;
|
||||||
return (p0, p1, p2, p3) => {
|
return (p0, p1, p2, p3) => {
|
||||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
if (!numberOfChecks++ || !looseIdentical(v0, p0) || !looseIdentical(v1, p1) ||
|
||||||
!looseIdentical(v3, p3)) {
|
!looseIdentical(v2, p2) || !looseIdentical(v3, p3)) {
|
||||||
v0 = p0;
|
v0 = p0;
|
||||||
v1 = p1;
|
v1 = p1;
|
||||||
v2 = p2;
|
v2 = p2;
|
||||||
|
@ -187,12 +254,13 @@ export function pureProxy4<P0, P1, P2, P3, R>(fn: (p0: P0, p1: P1, p2: P2, p3: P
|
||||||
export function pureProxy5<P0, P1, P2, P3, P4, R>(
|
export function pureProxy5<P0, P1, P2, P3, P4, R>(
|
||||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) => R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) =>
|
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) => R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) =>
|
||||||
R {
|
R {
|
||||||
|
let numberOfChecks = 0;
|
||||||
let result: R;
|
let result: R;
|
||||||
let v0: any, v1: any, v2: any, v3: any, v4: any;
|
let v0: any, v1: any, v2: any, v3: any, v4: any;
|
||||||
v0 = v1 = v2 = v3 = v4 = UNINITIALIZED;
|
v0 = v1 = v2 = v3 = v4;
|
||||||
return (p0, p1, p2, p3, p4) => {
|
return (p0, p1, p2, p3, p4) => {
|
||||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
if (!numberOfChecks++ || !looseIdentical(v0, p0) || !looseIdentical(v1, p1) ||
|
||||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4)) {
|
!looseIdentical(v2, p2) || !looseIdentical(v3, p3) || !looseIdentical(v4, p4)) {
|
||||||
v0 = p0;
|
v0 = p0;
|
||||||
v1 = p1;
|
v1 = p1;
|
||||||
v2 = p2;
|
v2 = p2;
|
||||||
|
@ -208,12 +276,14 @@ export function pureProxy5<P0, P1, P2, P3, P4, R>(
|
||||||
export function pureProxy6<P0, P1, P2, P3, P4, P5, R>(
|
export function pureProxy6<P0, P1, P2, P3, P4, P5, R>(
|
||||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) =>
|
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) =>
|
||||||
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) => R {
|
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) => R {
|
||||||
|
let numberOfChecks = 0;
|
||||||
let result: R;
|
let result: R;
|
||||||
let v0: any, v1: any, v2: any, v3: any, v4: any, v5: any;
|
let v0: any, v1: any, v2: any, v3: any, v4: any, v5: any;
|
||||||
v0 = v1 = v2 = v3 = v4 = v5 = UNINITIALIZED;
|
v0 = v1 = v2 = v3 = v4 = v5;
|
||||||
return (p0, p1, p2, p3, p4, p5) => {
|
return (p0, p1, p2, p3, p4, p5) => {
|
||||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
if (!numberOfChecks++ || !looseIdentical(v0, p0) || !looseIdentical(v1, p1) ||
|
||||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4) || !looseIdentical(v5, p5)) {
|
!looseIdentical(v2, p2) || !looseIdentical(v3, p3) || !looseIdentical(v4, p4) ||
|
||||||
|
!looseIdentical(v5, p5)) {
|
||||||
v0 = p0;
|
v0 = p0;
|
||||||
v1 = p1;
|
v1 = p1;
|
||||||
v2 = p2;
|
v2 = p2;
|
||||||
|
@ -229,13 +299,14 @@ export function pureProxy6<P0, P1, P2, P3, P4, P5, R>(
|
||||||
export function pureProxy7<P0, P1, P2, P3, P4, P5, P6, R>(
|
export function pureProxy7<P0, P1, P2, P3, P4, P5, P6, R>(
|
||||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) =>
|
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) =>
|
||||||
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) => R {
|
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) => R {
|
||||||
|
let numberOfChecks = 0;
|
||||||
let result: R;
|
let result: R;
|
||||||
let v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any;
|
let v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any;
|
||||||
v0 = v1 = v2 = v3 = v4 = v5 = v6 = UNINITIALIZED;
|
v0 = v1 = v2 = v3 = v4 = v5 = v6;
|
||||||
return (p0, p1, p2, p3, p4, p5, p6) => {
|
return (p0, p1, p2, p3, p4, p5, p6) => {
|
||||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
if (!numberOfChecks++ || !looseIdentical(v0, p0) || !looseIdentical(v1, p1) ||
|
||||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4) || !looseIdentical(v5, p5) ||
|
!looseIdentical(v2, p2) || !looseIdentical(v3, p3) || !looseIdentical(v4, p4) ||
|
||||||
!looseIdentical(v6, p6)) {
|
!looseIdentical(v5, p5) || !looseIdentical(v6, p6)) {
|
||||||
v0 = p0;
|
v0 = p0;
|
||||||
v1 = p1;
|
v1 = p1;
|
||||||
v2 = p2;
|
v2 = p2;
|
||||||
|
@ -252,13 +323,14 @@ export function pureProxy7<P0, P1, P2, P3, P4, P5, P6, R>(
|
||||||
export function pureProxy8<P0, P1, P2, P3, P4, P5, P6, P7, R>(
|
export function pureProxy8<P0, P1, P2, P3, P4, P5, P6, P7, R>(
|
||||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) =>
|
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) =>
|
||||||
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) => R {
|
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) => R {
|
||||||
|
let numberOfChecks = 0;
|
||||||
let result: R;
|
let result: R;
|
||||||
let v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any;
|
let v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any;
|
||||||
v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = UNINITIALIZED;
|
v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7;
|
||||||
return (p0, p1, p2, p3, p4, p5, p6, p7) => {
|
return (p0, p1, p2, p3, p4, p5, p6, p7) => {
|
||||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
if (!numberOfChecks++ || !looseIdentical(v0, p0) || !looseIdentical(v1, p1) ||
|
||||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4) || !looseIdentical(v5, p5) ||
|
!looseIdentical(v2, p2) || !looseIdentical(v3, p3) || !looseIdentical(v4, p4) ||
|
||||||
!looseIdentical(v6, p6) || !looseIdentical(v7, p7)) {
|
!looseIdentical(v5, p5) || !looseIdentical(v6, p6) || !looseIdentical(v7, p7)) {
|
||||||
v0 = p0;
|
v0 = p0;
|
||||||
v1 = p1;
|
v1 = p1;
|
||||||
v2 = p2;
|
v2 = p2;
|
||||||
|
@ -276,13 +348,15 @@ export function pureProxy8<P0, P1, P2, P3, P4, P5, P6, P7, R>(
|
||||||
export function pureProxy9<P0, P1, P2, P3, P4, P5, P6, P7, P8, R>(
|
export function pureProxy9<P0, P1, P2, P3, P4, P5, P6, P7, P8, R>(
|
||||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) =>
|
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) =>
|
||||||
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) => R {
|
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) => R {
|
||||||
|
let numberOfChecks = 0;
|
||||||
let result: R;
|
let result: R;
|
||||||
let v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any, v8: any;
|
let v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any, v8: any;
|
||||||
v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = UNINITIALIZED;
|
v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8;
|
||||||
return (p0, p1, p2, p3, p4, p5, p6, p7, p8) => {
|
return (p0, p1, p2, p3, p4, p5, p6, p7, p8) => {
|
||||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
if (!numberOfChecks++ || !looseIdentical(v0, p0) || !looseIdentical(v1, p1) ||
|
||||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4) || !looseIdentical(v5, p5) ||
|
!looseIdentical(v2, p2) || !looseIdentical(v3, p3) || !looseIdentical(v4, p4) ||
|
||||||
!looseIdentical(v6, p6) || !looseIdentical(v7, p7) || !looseIdentical(v8, p8)) {
|
!looseIdentical(v5, p5) || !looseIdentical(v6, p6) || !looseIdentical(v7, p7) ||
|
||||||
|
!looseIdentical(v8, p8)) {
|
||||||
v0 = p0;
|
v0 = p0;
|
||||||
v1 = p1;
|
v1 = p1;
|
||||||
v2 = p2;
|
v2 = p2;
|
||||||
|
@ -301,14 +375,15 @@ export function pureProxy9<P0, P1, P2, P3, P4, P5, P6, P7, P8, R>(
|
||||||
export function pureProxy10<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, R>(
|
export function pureProxy10<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, R>(
|
||||||
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9) =>
|
fn: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9) =>
|
||||||
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9) => R {
|
R): (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9) => R {
|
||||||
|
let numberOfChecks = 0;
|
||||||
let result: R;
|
let result: R;
|
||||||
let v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any, v8: any, v9: any;
|
let v0: any, v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any, v8: any, v9: any;
|
||||||
v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = UNINITIALIZED;
|
v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9;
|
||||||
return (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) => {
|
return (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9) => {
|
||||||
if (!looseIdentical(v0, p0) || !looseIdentical(v1, p1) || !looseIdentical(v2, p2) ||
|
if (!numberOfChecks++ || !looseIdentical(v0, p0) || !looseIdentical(v1, p1) ||
|
||||||
!looseIdentical(v3, p3) || !looseIdentical(v4, p4) || !looseIdentical(v5, p5) ||
|
!looseIdentical(v2, p2) || !looseIdentical(v3, p3) || !looseIdentical(v4, p4) ||
|
||||||
!looseIdentical(v6, p6) || !looseIdentical(v7, p7) || !looseIdentical(v8, p8) ||
|
!looseIdentical(v5, p5) || !looseIdentical(v6, p6) || !looseIdentical(v7, p7) ||
|
||||||
!looseIdentical(v9, p9)) {
|
!looseIdentical(v8, p8) || !looseIdentical(v9, p9)) {
|
||||||
v0 = p0;
|
v0 = p0;
|
||||||
v1 = p1;
|
v1 = p1;
|
||||||
v2 = p2;
|
v2 = p2;
|
||||||
|
|
|
@ -286,7 +286,7 @@ export function main() {
|
||||||
const formValidator = (c: any /** TODO #9100 */) => ({'custom': true});
|
const formValidator = (c: any /** TODO #9100 */) => ({'custom': true});
|
||||||
const f = new FormGroupDirective([formValidator], []);
|
const f = new FormGroupDirective([formValidator], []);
|
||||||
f.form = formModel;
|
f.form = formModel;
|
||||||
f.ngOnChanges({'form': new SimpleChange(null, null)});
|
f.ngOnChanges({'form': new SimpleChange(null, null, false)});
|
||||||
|
|
||||||
expect(formModel.errors).toEqual({'custom': true});
|
expect(formModel.errors).toEqual({'custom': true});
|
||||||
});
|
});
|
||||||
|
@ -294,7 +294,7 @@ export function main() {
|
||||||
it('should set up an async validator', fakeAsync(() => {
|
it('should set up an async validator', fakeAsync(() => {
|
||||||
const f = new FormGroupDirective([], [asyncValidator('expected')]);
|
const f = new FormGroupDirective([], [asyncValidator('expected')]);
|
||||||
f.form = formModel;
|
f.form = formModel;
|
||||||
f.ngOnChanges({'form': new SimpleChange(null, null)});
|
f.ngOnChanges({'form': new SimpleChange(null, null, false)});
|
||||||
|
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
|
@ -514,7 +514,7 @@ export function main() {
|
||||||
it('should reexport new control properties', () => {
|
it('should reexport new control properties', () => {
|
||||||
const newControl = new FormControl(null);
|
const newControl = new FormControl(null);
|
||||||
controlDir.form = newControl;
|
controlDir.form = newControl;
|
||||||
controlDir.ngOnChanges({'form': new SimpleChange(control, newControl)});
|
controlDir.ngOnChanges({'form': new SimpleChange(control, newControl, false)});
|
||||||
|
|
||||||
checkProperties(newControl);
|
checkProperties(newControl);
|
||||||
});
|
});
|
||||||
|
@ -523,7 +523,7 @@ export function main() {
|
||||||
expect(control.valid).toBe(true);
|
expect(control.valid).toBe(true);
|
||||||
|
|
||||||
// this will add the required validator and recalculate the validity
|
// this will add the required validator and recalculate the validity
|
||||||
controlDir.ngOnChanges({'form': new SimpleChange(null, control)});
|
controlDir.ngOnChanges({'form': new SimpleChange(null, control, false)});
|
||||||
|
|
||||||
expect(control.valid).toBe(false);
|
expect(control.valid).toBe(false);
|
||||||
});
|
});
|
||||||
|
@ -596,39 +596,39 @@ export function main() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should mark as disabled properly', fakeAsync(() => {
|
it('should mark as disabled properly', fakeAsync(() => {
|
||||||
ngModel.ngOnChanges({isDisabled: new SimpleChange('', undefined)});
|
ngModel.ngOnChanges({isDisabled: new SimpleChange('', undefined, false)});
|
||||||
tick();
|
tick();
|
||||||
expect(ngModel.control.disabled).toEqual(false);
|
expect(ngModel.control.disabled).toEqual(false);
|
||||||
|
|
||||||
ngModel.ngOnChanges({isDisabled: new SimpleChange('', null)});
|
ngModel.ngOnChanges({isDisabled: new SimpleChange('', null, false)});
|
||||||
tick();
|
tick();
|
||||||
expect(ngModel.control.disabled).toEqual(false);
|
expect(ngModel.control.disabled).toEqual(false);
|
||||||
|
|
||||||
ngModel.ngOnChanges({isDisabled: new SimpleChange('', false)});
|
ngModel.ngOnChanges({isDisabled: new SimpleChange('', false, false)});
|
||||||
tick();
|
tick();
|
||||||
expect(ngModel.control.disabled).toEqual(false);
|
expect(ngModel.control.disabled).toEqual(false);
|
||||||
|
|
||||||
ngModel.ngOnChanges({isDisabled: new SimpleChange('', 'false')});
|
ngModel.ngOnChanges({isDisabled: new SimpleChange('', 'false', false)});
|
||||||
tick();
|
tick();
|
||||||
expect(ngModel.control.disabled).toEqual(false);
|
expect(ngModel.control.disabled).toEqual(false);
|
||||||
|
|
||||||
ngModel.ngOnChanges({isDisabled: new SimpleChange('', 0)});
|
ngModel.ngOnChanges({isDisabled: new SimpleChange('', 0, false)});
|
||||||
tick();
|
tick();
|
||||||
expect(ngModel.control.disabled).toEqual(false);
|
expect(ngModel.control.disabled).toEqual(false);
|
||||||
|
|
||||||
ngModel.ngOnChanges({isDisabled: new SimpleChange(null, '')});
|
ngModel.ngOnChanges({isDisabled: new SimpleChange(null, '', false)});
|
||||||
tick();
|
tick();
|
||||||
expect(ngModel.control.disabled).toEqual(true);
|
expect(ngModel.control.disabled).toEqual(true);
|
||||||
|
|
||||||
ngModel.ngOnChanges({isDisabled: new SimpleChange(null, 'true')});
|
ngModel.ngOnChanges({isDisabled: new SimpleChange(null, 'true', false)});
|
||||||
tick();
|
tick();
|
||||||
expect(ngModel.control.disabled).toEqual(true);
|
expect(ngModel.control.disabled).toEqual(true);
|
||||||
|
|
||||||
ngModel.ngOnChanges({isDisabled: new SimpleChange(null, true)});
|
ngModel.ngOnChanges({isDisabled: new SimpleChange(null, true, false)});
|
||||||
tick();
|
tick();
|
||||||
expect(ngModel.control.disabled).toEqual(true);
|
expect(ngModel.control.disabled).toEqual(true);
|
||||||
|
|
||||||
ngModel.ngOnChanges({isDisabled: new SimpleChange(null, 'anything else')});
|
ngModel.ngOnChanges({isDisabled: new SimpleChange(null, 'anything else', false)});
|
||||||
tick();
|
tick();
|
||||||
expect(ngModel.control.disabled).toEqual(true);
|
expect(ngModel.control.disabled).toEqual(true);
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,9 @@ export class DowngradeComponentAdapter {
|
||||||
return (value: any /** TODO #9100 */) => {
|
return (value: any /** TODO #9100 */) => {
|
||||||
if (this.inputChanges !== null) {
|
if (this.inputChanges !== null) {
|
||||||
this.inputChangeCount++;
|
this.inputChangeCount++;
|
||||||
this.inputChanges[prop] =
|
this.inputChanges[prop] = new SimpleChange(
|
||||||
new Ng1Change(value, prevValue === INITIAL_VALUE ? value : prevValue);
|
value, prevValue === INITIAL_VALUE ? value : prevValue,
|
||||||
|
prevValue === INITIAL_VALUE);
|
||||||
prevValue = value;
|
prevValue = value;
|
||||||
}
|
}
|
||||||
this.component[prop] = value;
|
this.component[prop] = value;
|
||||||
|
@ -82,11 +83,11 @@ export class DowngradeComponentAdapter {
|
||||||
}
|
}
|
||||||
if (expr != null) {
|
if (expr != null) {
|
||||||
const watchFn =
|
const watchFn =
|
||||||
((prop: any /** TODO #9100 */) =>
|
((prop: any /** TODO #9100 */) => (
|
||||||
(value: any /** TODO #9100 */, prevValue: any /** TODO #9100 */) => {
|
value: any /** TODO #9100 */, prevValue: any /** TODO #9100 */) => {
|
||||||
if (this.inputChanges != null) {
|
if (this.inputChanges != null) {
|
||||||
this.inputChangeCount++;
|
this.inputChangeCount++;
|
||||||
this.inputChanges[prop] = new Ng1Change(prevValue, value);
|
this.inputChanges[prop] = new SimpleChange(prevValue, value, prevValue === value);
|
||||||
}
|
}
|
||||||
this.component[prop] = value;
|
this.component[prop] = value;
|
||||||
})(input.prop);
|
})(input.prop);
|
||||||
|
@ -172,9 +173,3 @@ export class DowngradeComponentAdapter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Ng1Change implements SimpleChange {
|
|
||||||
constructor(public previousValue: any, public currentValue: any) {}
|
|
||||||
|
|
||||||
isFirstChange(): boolean { return this.previousValue === this.currentValue; }
|
|
||||||
}
|
|
||||||
|
|
|
@ -54,8 +54,9 @@ export class DowngradeNg2ComponentAdapter {
|
||||||
return (value: any /** TODO #9100 */) => {
|
return (value: any /** TODO #9100 */) => {
|
||||||
if (this.inputChanges !== null) {
|
if (this.inputChanges !== null) {
|
||||||
this.inputChangeCount++;
|
this.inputChangeCount++;
|
||||||
this.inputChanges[prop] =
|
this.inputChanges[prop] = new SimpleChange(
|
||||||
new Ng1Change(value, prevValue === INITIAL_VALUE ? value : prevValue);
|
value, prevValue === INITIAL_VALUE ? value : prevValue,
|
||||||
|
prevValue === INITIAL_VALUE);
|
||||||
prevValue = value;
|
prevValue = value;
|
||||||
}
|
}
|
||||||
this.component[prop] = value;
|
this.component[prop] = value;
|
||||||
|
@ -73,11 +74,11 @@ export class DowngradeNg2ComponentAdapter {
|
||||||
}
|
}
|
||||||
if (expr != null) {
|
if (expr != null) {
|
||||||
const watchFn =
|
const watchFn =
|
||||||
((prop: any /** TODO #9100 */) =>
|
((prop: any /** TODO #9100 */) => (
|
||||||
(value: any /** TODO #9100 */, prevValue: any /** TODO #9100 */) => {
|
value: any /** TODO #9100 */, prevValue: any /** TODO #9100 */) => {
|
||||||
if (this.inputChanges != null) {
|
if (this.inputChanges != null) {
|
||||||
this.inputChangeCount++;
|
this.inputChangeCount++;
|
||||||
this.inputChanges[prop] = new Ng1Change(prevValue, value);
|
this.inputChanges[prop] = new SimpleChange(prevValue, value, prevValue === value);
|
||||||
}
|
}
|
||||||
this.component[prop] = value;
|
this.component[prop] = value;
|
||||||
})(input.prop);
|
})(input.prop);
|
||||||
|
@ -152,9 +153,3 @@ export class DowngradeNg2ComponentAdapter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Ng1Change implements SimpleChange {
|
|
||||||
constructor(public previousValue: any, public currentValue: any) {}
|
|
||||||
|
|
||||||
isFirstChange(): boolean { return this.previousValue === this.currentValue; }
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ export function init(moduleRef: NgModuleRef<AppModule>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function detectChanges() {
|
function detectChanges() {
|
||||||
for (var i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
appRef.tick();
|
appRef.tick();
|
||||||
}
|
}
|
||||||
detectChangesRuns += 10;
|
detectChangesRuns += 10;
|
||||||
|
|
|
@ -41,8 +41,8 @@ class _View_TreeComponent_Host0 extends import1.AppView<any> {
|
||||||
this.init([].concat([this._el_0]), [this._el_0], []);
|
this.init([].concat([this._el_0]), [this._el_0], []);
|
||||||
return new import9.ComponentRef_(0, this, this._el_0, this._TreeComponent_0_4.context);
|
return new import9.ComponentRef_(0, this, this._el_0, this._TreeComponent_0_4.context);
|
||||||
}
|
}
|
||||||
detectChangesInternal(throwOnChange: boolean): void {
|
detectChangesInternal(): void {
|
||||||
this._TreeComponent_0_4.detectChangesInternal(throwOnChange);
|
this._TreeComponent_0_4.detectChangesInternal(this.throwOnChange);
|
||||||
}
|
}
|
||||||
destroyInternal(): void { this._TreeComponent_0_4.destroyInternal(); }
|
destroyInternal(): void { this._TreeComponent_0_4.destroyInternal(); }
|
||||||
injectorGetInternal(token: any, requestNodeIndex: number, notFoundResult: any): any {
|
injectorGetInternal(token: any, requestNodeIndex: number, notFoundResult: any): any {
|
||||||
|
|
|
@ -49,8 +49,8 @@ class _View_TreeRootComponent_Host0 extends import1.AppView<any> {
|
||||||
this.init([].concat([this._el_0]), [this._el_0], []);
|
this.init([].concat([this._el_0]), [this._el_0], []);
|
||||||
return new import9.ComponentRef_(0, this, this._el_0, this._TreeRootComponent_0_4);
|
return new import9.ComponentRef_(0, this, this._el_0, this._TreeRootComponent_0_4);
|
||||||
}
|
}
|
||||||
detectChangesInternal(throwOnChange: boolean): void {
|
detectChangesInternal(): void {
|
||||||
this._TreeRootComponent_0_4_View.detectChangesInternal(throwOnChange);
|
this._TreeRootComponent_0_4_View.detectChangesInternal(this.throwOnChange);
|
||||||
}
|
}
|
||||||
destroyInternal(): void { this._TreeRootComponent_0_4_View.destroyInternal(); }
|
destroyInternal(): void { this._TreeRootComponent_0_4_View.destroyInternal(); }
|
||||||
injectorGetInternal(token: any, requestNodeIndex: number, notFoundResult: any): any {
|
injectorGetInternal(token: any, requestNodeIndex: number, notFoundResult: any): any {
|
||||||
|
@ -106,13 +106,13 @@ class _View_TreeRootComponent0 extends import1.AppView<import3.TreeRootComponent
|
||||||
}
|
}
|
||||||
return notFoundResult;
|
return notFoundResult;
|
||||||
}
|
}
|
||||||
detectChangesInternal(throwOnChange: boolean): void {
|
detectChangesInternal(): void {
|
||||||
const currVal_0: any = (this.context.data.left != (null as any));
|
const currVal_0: any = (this.context.data.left != (null as any));
|
||||||
if (checkBinding(throwOnChange, this._expr_0, currVal_0)) {
|
if (checkBinding(this.throwOnChange, this._expr_0, currVal_0)) {
|
||||||
this._NgIf_0_6.ngIf = currVal_0;
|
this._NgIf_0_6.ngIf = currVal_0;
|
||||||
this._expr_0 = currVal_0;
|
this._expr_0 = currVal_0;
|
||||||
}
|
}
|
||||||
this._appEl_0.detectChangesInNestedViews(throwOnChange);
|
this._appEl_0.detectChangesInNestedViews(this.throwOnChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class _View_TreeRootComponent1 extends import1.AppView<any> {
|
class _View_TreeRootComponent1 extends import1.AppView<any> {
|
||||||
|
@ -133,9 +133,9 @@ class _View_TreeRootComponent1 extends import1.AppView<any> {
|
||||||
return (null as any);
|
return (null as any);
|
||||||
}
|
}
|
||||||
destroyInternal() { this._TreeComponent0_0_4View.destroyInternal(); }
|
destroyInternal() { this._TreeComponent0_0_4View.destroyInternal(); }
|
||||||
detectChangesInternal(throwOnChange: boolean): void {
|
detectChangesInternal(): void {
|
||||||
this._TreeComponent0_0_4View.updateData(this.parentView.context.data);
|
this._TreeComponent0_0_4View.updateData(this.parentView.context.data);
|
||||||
this._TreeComponent0_0_4View.detectChangesInternal(throwOnChange);
|
this._TreeComponent0_0_4View.detectChangesInternal(this.throwOnChange);
|
||||||
}
|
}
|
||||||
visitRootNodesInternal(cb: any, context: any) { cb(this._el_0, context); }
|
visitRootNodesInternal(cb: any, context: any) { cb(this._el_0, context); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -843,7 +843,7 @@ export declare function setTestabilityGetter(getter: GetTestability): void;
|
||||||
export declare class SimpleChange {
|
export declare class SimpleChange {
|
||||||
currentValue: any;
|
currentValue: any;
|
||||||
previousValue: any;
|
previousValue: any;
|
||||||
constructor(previousValue: any, currentValue: any);
|
constructor(previousValue: any, currentValue: any, _isFirstChange?: boolean);
|
||||||
isFirstChange(): boolean;
|
isFirstChange(): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue