2016-06-23 09:47:54 -07:00
|
|
|
/**
|
|
|
|
* @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
|
|
|
|
*/
|
|
|
|
|
2016-08-02 15:53:34 -07:00
|
|
|
import {SecurityContext} from '@angular/core';
|
|
|
|
|
2016-01-06 14:13:44 -08:00
|
|
|
import * as cdAst from '../expression_parser/ast';
|
2016-06-08 16:38:52 -07:00
|
|
|
import {isBlank, isPresent} from '../facade/lang';
|
2016-08-24 17:39:49 -07:00
|
|
|
import {Identifiers, resolveIdentifier} from '../identifiers';
|
2016-06-08 16:38:52 -07:00
|
|
|
import * as o from '../output/output_ast';
|
2016-08-30 18:07:40 -07:00
|
|
|
import {EMPTY_STATE as EMPTY_ANIMATION_STATE, LifecycleHooks, isDefaultChangeDetectionStrategy} from '../private_import_core';
|
2016-08-02 15:53:34 -07:00
|
|
|
import {BoundElementPropertyAst, BoundTextAst, DirectiveAst, PropertyBindingType} from '../template_parser/template_ast';
|
|
|
|
import {camelCaseToDashCase} from '../util';
|
|
|
|
|
|
|
|
import {CompileBinding} from './compile_binding';
|
2016-01-06 14:13:44 -08:00
|
|
|
import {CompileElement, CompileNode} from './compile_element';
|
|
|
|
import {CompileMethod} from './compile_method';
|
2016-08-02 15:53:34 -07:00
|
|
|
import {CompileView} from './compile_view';
|
|
|
|
import {DetectChangesVars, ViewProperties} from './constants';
|
2016-08-11 21:20:54 -07:00
|
|
|
import {convertCdExpressionToIr, temporaryDeclaration} from './expression_converter';
|
2016-04-28 17:50:03 -07:00
|
|
|
|
2016-01-06 14:13:44 -08:00
|
|
|
function createBindFieldExpr(exprIndex: number): o.ReadPropExpr {
|
|
|
|
return o.THIS_EXPR.prop(`_expr_${exprIndex}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
function createCurrValueExpr(exprIndex: number): o.ReadVarExpr {
|
feat: security implementation in Angular 2.
Summary:
This adds basic security hooks to Angular 2.
* `SecurityContext` is a private API between core, compiler, and
platform-browser. `SecurityContext` communicates what context a value is used
in across template parser, compiler, and sanitization at runtime.
* `SanitizationService` is the bare bones interface to sanitize values for a
particular context.
* `SchemaElementRegistry.securityContext(tagName, attributeOrPropertyName)`
determines the security context for an attribute or property (it turns out
attributes and properties match for the purposes of sanitization).
Based on these hooks:
* `DomSchemaElementRegistry` decides what sanitization applies in a particular
context.
* `DomSanitizationService` implements `SanitizationService` and adds *Safe
Value*s, i.e. the ability to mark a value as safe and not requiring further
sanitization.
* `url_sanitizer` and `style_sanitizer` sanitize URLs and Styles, respectively
(surprise!).
`DomSanitizationService` is the default implementation bound for browser
applications, in the three contexts (browser rendering, web worker rendering,
server side rendering).
BREAKING CHANGES:
*** SECURITY WARNING ***
Angular 2 Release Candidates do not implement proper contextual escaping yet.
Make sure to correctly escape all values that go into the DOM.
*** SECURITY WARNING ***
Reviewers: IgorMinar
Differential Revision: https://reviews.angular.io/D103
2016-04-29 16:04:08 -07:00
|
|
|
return o.variable(`currVal_${exprIndex}`); // fix syntax highlighting: `
|
2016-01-06 14:13:44 -08:00
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
function bind(
|
|
|
|
view: CompileView, currValExpr: o.ReadVarExpr, fieldExpr: o.ReadPropExpr,
|
|
|
|
parsedExpression: cdAst.AST, context: o.Expression, actions: o.Statement[],
|
2016-08-11 21:20:54 -07:00
|
|
|
method: CompileMethod, bindingIndex: number) {
|
|
|
|
var checkExpression = convertCdExpressionToIr(
|
|
|
|
view, context, parsedExpression, DetectChangesVars.valUnwrapper, bindingIndex);
|
2016-01-06 14:13:44 -08:00
|
|
|
if (isBlank(checkExpression.expression)) {
|
|
|
|
// e.g. an empty expression was given
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-11 21:20:54 -07:00
|
|
|
if (checkExpression.temporaryCount) {
|
|
|
|
for (let i = 0; i < checkExpression.temporaryCount; i++) {
|
|
|
|
method.addStmt(temporaryDeclaration(bindingIndex, i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-30 16:13:03 -07:00
|
|
|
// private is fine here as no child view will reference the cached value...
|
2016-01-06 14:13:44 -08:00
|
|
|
view.fields.push(new o.ClassField(fieldExpr.name, null, [o.StmtModifier.Private]));
|
2016-08-24 17:39:49 -07:00
|
|
|
view.createMethod.addStmt(o.THIS_EXPR.prop(fieldExpr.name)
|
|
|
|
.set(o.importExpr(resolveIdentifier(Identifiers.UNINITIALIZED)))
|
|
|
|
.toStmt());
|
2016-01-06 14:13:44 -08:00
|
|
|
|
|
|
|
if (checkExpression.needsValueUnwrapper) {
|
|
|
|
var initValueUnwrapperStmt = DetectChangesVars.valUnwrapper.callMethod('reset', []).toStmt();
|
|
|
|
method.addStmt(initValueUnwrapperStmt);
|
|
|
|
}
|
|
|
|
method.addStmt(
|
|
|
|
currValExpr.set(checkExpression.expression).toDeclStmt(null, [o.StmtModifier.Final]));
|
|
|
|
|
2016-08-24 17:39:49 -07:00
|
|
|
var condition: o.Expression = o.importExpr(resolveIdentifier(Identifiers.checkBinding)).callFn([
|
2016-06-08 16:38:52 -07:00
|
|
|
DetectChangesVars.throwOnChange, fieldExpr, currValExpr
|
|
|
|
]);
|
2016-01-06 14:13:44 -08:00
|
|
|
if (checkExpression.needsValueUnwrapper) {
|
|
|
|
condition = DetectChangesVars.valUnwrapper.prop('hasWrappedValue').or(condition);
|
|
|
|
}
|
|
|
|
method.addStmt(new o.IfStmt(
|
|
|
|
condition,
|
|
|
|
actions.concat([<o.Statement>o.THIS_EXPR.prop(fieldExpr.name).set(currValExpr).toStmt()])));
|
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
export function bindRenderText(
|
|
|
|
boundText: BoundTextAst, compileNode: CompileNode, view: CompileView) {
|
2016-01-06 14:13:44 -08:00
|
|
|
var bindingIndex = view.bindings.length;
|
|
|
|
view.bindings.push(new CompileBinding(compileNode, boundText));
|
|
|
|
var currValExpr = createCurrValueExpr(bindingIndex);
|
|
|
|
var valueField = createBindFieldExpr(bindingIndex);
|
2016-04-20 18:10:19 -07:00
|
|
|
view.detectChangesRenderPropertiesMethod.resetDebugInfo(compileNode.nodeIndex, boundText);
|
2016-01-06 14:13:44 -08:00
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
bind(
|
|
|
|
view, currValExpr, valueField, boundText.value, view.componentContext,
|
|
|
|
[o.THIS_EXPR.prop('renderer')
|
|
|
|
.callMethod('setText', [compileNode.renderNode, currValExpr])
|
|
|
|
.toStmt()],
|
2016-08-11 21:20:54 -07:00
|
|
|
view.detectChangesRenderPropertiesMethod, bindingIndex);
|
2016-01-06 14:13:44 -08:00
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
function bindAndWriteToRenderer(
|
2016-07-08 17:11:12 -07:00
|
|
|
boundProps: BoundElementPropertyAst[], context: o.Expression, compileElement: CompileElement,
|
|
|
|
isHostProp: boolean) {
|
2016-01-06 14:13:44 -08:00
|
|
|
var view = compileElement.view;
|
|
|
|
var renderNode = compileElement.renderNode;
|
|
|
|
boundProps.forEach((boundProp) => {
|
|
|
|
var bindingIndex = view.bindings.length;
|
|
|
|
view.bindings.push(new CompileBinding(compileElement, boundProp));
|
2016-04-20 18:10:19 -07:00
|
|
|
view.detectChangesRenderPropertiesMethod.resetDebugInfo(compileElement.nodeIndex, boundProp);
|
2016-01-06 14:13:44 -08:00
|
|
|
var fieldExpr = createBindFieldExpr(bindingIndex);
|
|
|
|
var currValExpr = createCurrValueExpr(bindingIndex);
|
|
|
|
var renderMethod: string;
|
2016-05-25 12:46:22 -07:00
|
|
|
var oldRenderValue: o.Expression = sanitizedValue(boundProp, fieldExpr);
|
feat: security implementation in Angular 2.
Summary:
This adds basic security hooks to Angular 2.
* `SecurityContext` is a private API between core, compiler, and
platform-browser. `SecurityContext` communicates what context a value is used
in across template parser, compiler, and sanitization at runtime.
* `SanitizationService` is the bare bones interface to sanitize values for a
particular context.
* `SchemaElementRegistry.securityContext(tagName, attributeOrPropertyName)`
determines the security context for an attribute or property (it turns out
attributes and properties match for the purposes of sanitization).
Based on these hooks:
* `DomSchemaElementRegistry` decides what sanitization applies in a particular
context.
* `DomSanitizationService` implements `SanitizationService` and adds *Safe
Value*s, i.e. the ability to mark a value as safe and not requiring further
sanitization.
* `url_sanitizer` and `style_sanitizer` sanitize URLs and Styles, respectively
(surprise!).
`DomSanitizationService` is the default implementation bound for browser
applications, in the three contexts (browser rendering, web worker rendering,
server side rendering).
BREAKING CHANGES:
*** SECURITY WARNING ***
Angular 2 Release Candidates do not implement proper contextual escaping yet.
Make sure to correctly escape all values that go into the DOM.
*** SECURITY WARNING ***
Reviewers: IgorMinar
Differential Revision: https://reviews.angular.io/D103
2016-04-29 16:04:08 -07:00
|
|
|
var renderValue: o.Expression = sanitizedValue(boundProp, currValExpr);
|
2016-06-08 15:45:15 -07:00
|
|
|
var updateStmts: any[] /** TODO #9100 */ = [];
|
2016-09-01 23:24:26 +03:00
|
|
|
var compileMethod = view.detectChangesRenderPropertiesMethod;
|
2016-01-06 14:13:44 -08:00
|
|
|
switch (boundProp.type) {
|
|
|
|
case PropertyBindingType.Property:
|
|
|
|
if (view.genConfig.logBindingUpdate) {
|
2016-05-25 12:46:22 -07:00
|
|
|
updateStmts.push(logBindingUpdateStmt(renderNode, boundProp.name, renderValue));
|
2016-01-06 14:13:44 -08:00
|
|
|
}
|
2016-05-25 12:46:22 -07:00
|
|
|
updateStmts.push(
|
|
|
|
o.THIS_EXPR.prop('renderer')
|
2016-06-08 16:38:52 -07:00
|
|
|
.callMethod(
|
|
|
|
'setElementProperty', [renderNode, o.literal(boundProp.name), renderValue])
|
|
|
|
.toStmt());
|
2016-01-06 14:13:44 -08:00
|
|
|
break;
|
|
|
|
case PropertyBindingType.Attribute:
|
2016-06-08 16:38:52 -07:00
|
|
|
renderValue =
|
|
|
|
renderValue.isBlank().conditional(o.NULL_EXPR, renderValue.callMethod('toString', []));
|
2016-05-25 12:46:22 -07:00
|
|
|
updateStmts.push(
|
|
|
|
o.THIS_EXPR.prop('renderer')
|
2016-06-08 16:38:52 -07:00
|
|
|
.callMethod(
|
|
|
|
'setElementAttribute', [renderNode, o.literal(boundProp.name), renderValue])
|
|
|
|
.toStmt());
|
2016-01-06 14:13:44 -08:00
|
|
|
break;
|
|
|
|
case PropertyBindingType.Class:
|
2016-05-25 12:46:22 -07:00
|
|
|
updateStmts.push(
|
|
|
|
o.THIS_EXPR.prop('renderer')
|
|
|
|
.callMethod('setElementClass', [renderNode, o.literal(boundProp.name), renderValue])
|
2016-06-08 16:38:52 -07:00
|
|
|
.toStmt());
|
2016-01-06 14:13:44 -08:00
|
|
|
break;
|
|
|
|
case PropertyBindingType.Style:
|
|
|
|
var strValue: o.Expression = renderValue.callMethod('toString', []);
|
|
|
|
if (isPresent(boundProp.unit)) {
|
|
|
|
strValue = strValue.plus(o.literal(boundProp.unit));
|
|
|
|
}
|
2016-07-08 17:11:12 -07:00
|
|
|
|
2016-01-06 14:13:44 -08:00
|
|
|
renderValue = renderValue.isBlank().conditional(o.NULL_EXPR, strValue);
|
2016-05-25 12:46:22 -07:00
|
|
|
updateStmts.push(
|
|
|
|
o.THIS_EXPR.prop('renderer')
|
|
|
|
.callMethod('setElementStyle', [renderNode, o.literal(boundProp.name), renderValue])
|
2016-06-08 16:38:52 -07:00
|
|
|
.toStmt());
|
2016-05-25 12:46:22 -07:00
|
|
|
break;
|
|
|
|
case PropertyBindingType.Animation:
|
|
|
|
var animationName = boundProp.name;
|
2016-07-08 17:11:12 -07:00
|
|
|
var targetViewExpr: o.Expression = o.THIS_EXPR;
|
|
|
|
if (isHostProp) {
|
|
|
|
targetViewExpr = compileElement.appElement.prop('componentView');
|
|
|
|
}
|
|
|
|
|
2016-09-01 23:24:26 +03:00
|
|
|
compileMethod = view.animationBindingsMethod;
|
|
|
|
|
2016-07-08 17:11:12 -07:00
|
|
|
var animationFnExpr =
|
|
|
|
targetViewExpr.prop('componentType').prop('animations').key(o.literal(animationName));
|
2016-05-25 12:46:22 -07:00
|
|
|
|
|
|
|
// it's important to normalize the void value as `void` explicitly
|
|
|
|
// so that the styles data can be obtained from the stringmap
|
|
|
|
var emptyStateValue = o.literal(EMPTY_ANIMATION_STATE);
|
|
|
|
|
|
|
|
// void => ...
|
|
|
|
var oldRenderVar = o.variable('oldRenderVar');
|
|
|
|
updateStmts.push(oldRenderVar.set(oldRenderValue).toDeclStmt());
|
2016-06-08 16:38:52 -07:00
|
|
|
updateStmts.push(new o.IfStmt(
|
2016-08-24 17:39:49 -07:00
|
|
|
oldRenderVar.equals(o.importExpr(resolveIdentifier(Identifiers.UNINITIALIZED))),
|
2016-06-08 16:38:52 -07:00
|
|
|
[oldRenderVar.set(emptyStateValue).toStmt()]));
|
2016-05-25 12:46:22 -07:00
|
|
|
|
|
|
|
// ... => void
|
|
|
|
var newRenderVar = o.variable('newRenderVar');
|
|
|
|
updateStmts.push(newRenderVar.set(renderValue).toDeclStmt());
|
2016-06-08 16:38:52 -07:00
|
|
|
updateStmts.push(new o.IfStmt(
|
2016-08-24 17:39:49 -07:00
|
|
|
newRenderVar.equals(o.importExpr(resolveIdentifier(Identifiers.UNINITIALIZED))),
|
2016-06-08 16:38:52 -07:00
|
|
|
[newRenderVar.set(emptyStateValue).toStmt()]));
|
2016-05-25 12:46:22 -07:00
|
|
|
|
|
|
|
updateStmts.push(
|
2016-07-08 17:11:12 -07:00
|
|
|
animationFnExpr.callFn([o.THIS_EXPR, renderNode, oldRenderVar, newRenderVar]).toStmt());
|
2016-05-25 12:46:22 -07:00
|
|
|
|
|
|
|
view.detachMethod.addStmt(
|
2016-07-08 17:11:12 -07:00
|
|
|
animationFnExpr.callFn([o.THIS_EXPR, renderNode, oldRenderValue, emptyStateValue])
|
2016-06-08 16:38:52 -07:00
|
|
|
.toStmt());
|
2016-05-25 12:46:22 -07:00
|
|
|
|
2016-01-06 14:13:44 -08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
bind(
|
2016-09-01 23:24:26 +03:00
|
|
|
view, currValExpr, fieldExpr, boundProp.value, context, updateStmts, compileMethod,
|
|
|
|
view.bindings.length);
|
2016-01-06 14:13:44 -08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
function sanitizedValue(
|
|
|
|
boundProp: BoundElementPropertyAst, renderValue: o.Expression): o.Expression {
|
feat: security implementation in Angular 2.
Summary:
This adds basic security hooks to Angular 2.
* `SecurityContext` is a private API between core, compiler, and
platform-browser. `SecurityContext` communicates what context a value is used
in across template parser, compiler, and sanitization at runtime.
* `SanitizationService` is the bare bones interface to sanitize values for a
particular context.
* `SchemaElementRegistry.securityContext(tagName, attributeOrPropertyName)`
determines the security context for an attribute or property (it turns out
attributes and properties match for the purposes of sanitization).
Based on these hooks:
* `DomSchemaElementRegistry` decides what sanitization applies in a particular
context.
* `DomSanitizationService` implements `SanitizationService` and adds *Safe
Value*s, i.e. the ability to mark a value as safe and not requiring further
sanitization.
* `url_sanitizer` and `style_sanitizer` sanitize URLs and Styles, respectively
(surprise!).
`DomSanitizationService` is the default implementation bound for browser
applications, in the three contexts (browser rendering, web worker rendering,
server side rendering).
BREAKING CHANGES:
*** SECURITY WARNING ***
Angular 2 Release Candidates do not implement proper contextual escaping yet.
Make sure to correctly escape all values that go into the DOM.
*** SECURITY WARNING ***
Reviewers: IgorMinar
Differential Revision: https://reviews.angular.io/D103
2016-04-29 16:04:08 -07:00
|
|
|
let enumValue: string;
|
|
|
|
switch (boundProp.securityContext) {
|
|
|
|
case SecurityContext.NONE:
|
|
|
|
return renderValue; // No sanitization needed.
|
|
|
|
case SecurityContext.HTML:
|
|
|
|
enumValue = 'HTML';
|
|
|
|
break;
|
|
|
|
case SecurityContext.STYLE:
|
|
|
|
enumValue = 'STYLE';
|
|
|
|
break;
|
|
|
|
case SecurityContext.SCRIPT:
|
|
|
|
enumValue = 'SCRIPT';
|
|
|
|
break;
|
|
|
|
case SecurityContext.URL:
|
|
|
|
enumValue = 'URL';
|
|
|
|
break;
|
|
|
|
case SecurityContext.RESOURCE_URL:
|
|
|
|
enumValue = 'RESOURCE_URL';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new Error(`internal error, unexpected SecurityContext ${boundProp.securityContext}.`);
|
|
|
|
}
|
|
|
|
let ctx = ViewProperties.viewUtils.prop('sanitizer');
|
2016-08-24 17:39:49 -07:00
|
|
|
let args =
|
|
|
|
[o.importExpr(resolveIdentifier(Identifiers.SecurityContext)).prop(enumValue), renderValue];
|
feat: security implementation in Angular 2.
Summary:
This adds basic security hooks to Angular 2.
* `SecurityContext` is a private API between core, compiler, and
platform-browser. `SecurityContext` communicates what context a value is used
in across template parser, compiler, and sanitization at runtime.
* `SanitizationService` is the bare bones interface to sanitize values for a
particular context.
* `SchemaElementRegistry.securityContext(tagName, attributeOrPropertyName)`
determines the security context for an attribute or property (it turns out
attributes and properties match for the purposes of sanitization).
Based on these hooks:
* `DomSchemaElementRegistry` decides what sanitization applies in a particular
context.
* `DomSanitizationService` implements `SanitizationService` and adds *Safe
Value*s, i.e. the ability to mark a value as safe and not requiring further
sanitization.
* `url_sanitizer` and `style_sanitizer` sanitize URLs and Styles, respectively
(surprise!).
`DomSanitizationService` is the default implementation bound for browser
applications, in the three contexts (browser rendering, web worker rendering,
server side rendering).
BREAKING CHANGES:
*** SECURITY WARNING ***
Angular 2 Release Candidates do not implement proper contextual escaping yet.
Make sure to correctly escape all values that go into the DOM.
*** SECURITY WARNING ***
Reviewers: IgorMinar
Differential Revision: https://reviews.angular.io/D103
2016-04-29 16:04:08 -07:00
|
|
|
return ctx.callMethod('sanitize', args);
|
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
export function bindRenderInputs(
|
|
|
|
boundProps: BoundElementPropertyAst[], compileElement: CompileElement): void {
|
2016-07-08 17:11:12 -07:00
|
|
|
bindAndWriteToRenderer(boundProps, compileElement.view.componentContext, compileElement, false);
|
2016-01-06 14:13:44 -08:00
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
export function bindDirectiveHostProps(
|
|
|
|
directiveAst: DirectiveAst, directiveInstance: o.Expression,
|
|
|
|
compileElement: CompileElement): void {
|
2016-07-08 17:11:12 -07:00
|
|
|
bindAndWriteToRenderer(directiveAst.hostProperties, directiveInstance, compileElement, true);
|
2016-01-06 14:13:44 -08:00
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
export function bindDirectiveInputs(
|
|
|
|
directiveAst: DirectiveAst, directiveInstance: o.Expression, compileElement: CompileElement) {
|
2016-01-06 14:13:44 -08:00
|
|
|
if (directiveAst.inputs.length === 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var view = compileElement.view;
|
|
|
|
var detectChangesInInputsMethod = view.detectChangesInInputsMethod;
|
|
|
|
detectChangesInInputsMethod.resetDebugInfo(compileElement.nodeIndex, compileElement.sourceAst);
|
|
|
|
|
2016-08-02 01:12:24 -07:00
|
|
|
var lifecycleHooks = directiveAst.directive.type.lifecycleHooks;
|
2016-01-06 14:13:44 -08:00
|
|
|
var calcChangesMap = lifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1;
|
|
|
|
var isOnPushComp = directiveAst.directive.isComponent &&
|
2016-06-08 16:38:52 -07:00
|
|
|
!isDefaultChangeDetectionStrategy(directiveAst.directive.changeDetection);
|
2016-01-06 14:13:44 -08:00
|
|
|
if (calcChangesMap) {
|
|
|
|
detectChangesInInputsMethod.addStmt(DetectChangesVars.changes.set(o.NULL_EXPR).toStmt());
|
|
|
|
}
|
|
|
|
if (isOnPushComp) {
|
|
|
|
detectChangesInInputsMethod.addStmt(DetectChangesVars.changed.set(o.literal(false)).toStmt());
|
|
|
|
}
|
|
|
|
directiveAst.inputs.forEach((input) => {
|
|
|
|
var bindingIndex = view.bindings.length;
|
|
|
|
view.bindings.push(new CompileBinding(compileElement, input));
|
|
|
|
detectChangesInInputsMethod.resetDebugInfo(compileElement.nodeIndex, input);
|
|
|
|
var fieldExpr = createBindFieldExpr(bindingIndex);
|
|
|
|
var currValExpr = createCurrValueExpr(bindingIndex);
|
|
|
|
var statements: o.Statement[] =
|
|
|
|
[directiveInstance.prop(input.directiveName).set(currValExpr).toStmt()];
|
|
|
|
if (calcChangesMap) {
|
2016-06-08 16:38:52 -07:00
|
|
|
statements.push(new o.IfStmt(
|
|
|
|
DetectChangesVars.changes.identical(o.NULL_EXPR),
|
|
|
|
[DetectChangesVars.changes
|
2016-08-24 17:39:49 -07:00
|
|
|
.set(o.literalMap(
|
|
|
|
[], new o.MapType(o.importType(resolveIdentifier(Identifiers.SimpleChange)))))
|
2016-06-08 16:38:52 -07:00
|
|
|
.toStmt()]));
|
2016-08-24 17:39:49 -07:00
|
|
|
statements.push(DetectChangesVars.changes.key(o.literal(input.directiveName))
|
|
|
|
.set(o.importExpr(resolveIdentifier(Identifiers.SimpleChange))
|
|
|
|
.instantiate([fieldExpr, currValExpr]))
|
|
|
|
.toStmt());
|
2016-01-06 14:13:44 -08:00
|
|
|
}
|
|
|
|
if (isOnPushComp) {
|
|
|
|
statements.push(DetectChangesVars.changed.set(o.literal(true)).toStmt());
|
|
|
|
}
|
|
|
|
if (view.genConfig.logBindingUpdate) {
|
|
|
|
statements.push(
|
|
|
|
logBindingUpdateStmt(compileElement.renderNode, input.directiveName, currValExpr));
|
|
|
|
}
|
2016-06-08 16:38:52 -07:00
|
|
|
bind(
|
|
|
|
view, currValExpr, fieldExpr, input.value, view.componentContext, statements,
|
2016-08-11 21:20:54 -07:00
|
|
|
detectChangesInInputsMethod, bindingIndex);
|
2016-01-06 14:13:44 -08:00
|
|
|
});
|
|
|
|
if (isOnPushComp) {
|
|
|
|
detectChangesInInputsMethod.addStmt(new o.IfStmt(DetectChangesVars.changed, [
|
2016-06-08 16:38:52 -07:00
|
|
|
compileElement.appElement.prop('componentView').callMethod('markAsCheckOnce', []).toStmt()
|
2016-01-06 14:13:44 -08:00
|
|
|
]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
function logBindingUpdateStmt(
|
|
|
|
renderNode: o.Expression, propName: string, value: o.Expression): o.Statement {
|
2016-07-12 10:26:54 -07:00
|
|
|
const tryStmt =
|
|
|
|
o.THIS_EXPR.prop('renderer')
|
|
|
|
.callMethod(
|
|
|
|
'setBindingDebugInfo',
|
|
|
|
[
|
|
|
|
renderNode, o.literal(`ng-reflect-${camelCaseToDashCase(propName)}`),
|
|
|
|
value.isBlank().conditional(o.NULL_EXPR, value.callMethod('toString', []))
|
|
|
|
])
|
|
|
|
.toStmt();
|
|
|
|
|
|
|
|
const catchStmt = o.THIS_EXPR.prop('renderer')
|
|
|
|
.callMethod(
|
|
|
|
'setBindingDebugInfo',
|
|
|
|
[
|
|
|
|
renderNode, o.literal(`ng-reflect-${camelCaseToDashCase(propName)}`),
|
|
|
|
o.literal('[ERROR] Exception while trying to serialize the value')
|
|
|
|
])
|
|
|
|
.toStmt();
|
|
|
|
|
|
|
|
return new o.TryCatchStmt([tryStmt], [catchStmt]);
|
2016-01-06 14:13:44 -08:00
|
|
|
}
|