refactor(core): misc refactoring to support upcoming changes to improve synthetic host bindings (#35884)

This commit performs a few updates to internal functions that would be required in upcoming changes to support synthetic host bindings in Directives.

* the `elementPropertyInternal` function was refactored to accept renderer as an argument (prior to that, there was a function that loads the renderer in some specific way for animation bindings)
* `elementPropertyInternal`, `elementAttributeInternal` and `listenerInternal` functions were updated to have a fixed set of arguments (for better performance)
* `elementPropertyInternal` and `elementAttributeInternal` functions were updated to take `tNode` as an argument instead of passing node index (that was used to retrieve `tNode` internally), in some cases we already have `tNode` available or we can retrieve it from the state

The refactoring was triggered by the need to pass different renderers to the `elementPropertyInternal` to support synthetic host bindings in Directives (see this comment for additional context: https://github.com/angular/angular/pull/35568/files#r388034584).

PR Close #35884
This commit is contained in:
Andrew Kushnir 2020-03-05 14:14:59 -08:00
parent e552591768
commit 168a393589
10 changed files with 123 additions and 117 deletions

View File

@ -800,7 +800,8 @@ function readCreateOpCodes(
const attrValue = createOpCodes[++i] as string; const attrValue = createOpCodes[++i] as string;
// This code is used for ICU expressions only, since we don't support // This code is used for ICU expressions only, since we don't support
// directives/components in ICUs, we don't need to worry about inputs here // directives/components in ICUs, we don't need to worry about inputs here
elementAttributeInternal(elementNodeIndex, attrName, attrValue, tView, lView); elementAttributeInternal(
getTNode(tView, elementNodeIndex), lView, attrName, attrValue, null, null);
break; break;
default: default:
throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`); throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`);
@ -877,7 +878,9 @@ function readUpdateOpCodes(
case I18nUpdateOpCode.Attr: case I18nUpdateOpCode.Attr:
const propName = updateOpCodes[++j] as string; const propName = updateOpCodes[++j] as string;
const sanitizeFn = updateOpCodes[++j] as SanitizerFn | null; const sanitizeFn = updateOpCodes[++j] as SanitizerFn | null;
elementPropertyInternal(tView, lView, nodeIndex, propName, value, sanitizeFn); elementPropertyInternal(
tView, getTNode(tView, nodeIndex), lView, propName, value, lView[RENDERER],
sanitizeFn, false);
break; break;
case I18nUpdateOpCode.Text: case I18nUpdateOpCode.Text:
textBindingInternal(lView, nodeIndex, value); textBindingInternal(lView, nodeIndex, value);
@ -1042,7 +1045,7 @@ function i18nAttributesFirstPass(lView: LView, tView: TView, index: number, valu
// Set attributes for Elements only, for other types (like ElementContainer), // Set attributes for Elements only, for other types (like ElementContainer),
// only set inputs below // only set inputs below
if (tNode.type === TNodeType.Element) { if (tNode.type === TNodeType.Element) {
elementAttributeInternal(previousElementIndex, attrName, value, tView, lView); elementAttributeInternal(tNode, lView, attrName, value, null, null);
} }
// Check if that attribute is a directive input // Check if that attribute is a directive input
const dataValue = tNode.inputs !== null && tNode.inputs[attrName]; const dataValue = tNode.inputs !== null && tNode.inputs[attrName];

View File

@ -7,7 +7,7 @@
*/ */
import {bindingUpdated} from '../bindings'; import {bindingUpdated} from '../bindings';
import {SanitizerFn} from '../interfaces/sanitization'; import {SanitizerFn} from '../interfaces/sanitization';
import {getLView, getSelectedIndex, getTView, nextBindingIndex} from '../state'; import {getLView, getSelectedIndex, getSelectedTNode, getTView, nextBindingIndex} from '../state';
import {elementAttributeInternal, storePropertyBindingMetadata} from './shared'; import {elementAttributeInternal, storePropertyBindingMetadata} from './shared';
@ -31,10 +31,10 @@ export function ɵɵattribute(
const lView = getLView(); const lView = getLView();
const bindingIndex = nextBindingIndex(); const bindingIndex = nextBindingIndex();
if (bindingUpdated(lView, bindingIndex, value)) { if (bindingUpdated(lView, bindingIndex, value)) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementAttributeInternal(nodeIndex, name, value, tView, lView, sanitizer, namespace); const tNode = getSelectedTNode();
ngDevMode && storePropertyBindingMetadata(tView.data, nodeIndex, 'attr.' + name, bindingIndex); elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata(tView.data, tNode, 'attr.' + name, bindingIndex);
} }
return ɵɵattribute; return ɵɵattribute;
} }

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {SanitizerFn} from '../interfaces/sanitization'; import {SanitizerFn} from '../interfaces/sanitization';
import {getBindingIndex, getLView, getSelectedIndex, getTView} from '../state'; import {getBindingIndex, getLView, getSelectedTNode, getTView} from '../state';
import {NO_CHANGE} from '../tokens'; import {NO_CHANGE} from '../tokens';
import {interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV} from './interpolation'; import {interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV} from './interpolation';
import {elementAttributeInternal, storePropertyBindingMetadata} from './shared'; import {elementAttributeInternal, storePropertyBindingMetadata} from './shared';
@ -43,13 +43,11 @@ export function ɵɵattributeInterpolate1(
const lView = getLView(); const lView = getLView();
const interpolatedValue = interpolation1(lView, prefix, v0, suffix); const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex(); const tNode = getSelectedTNode();
const tView = getTView(); elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && ngDevMode &&
storePropertyBindingMetadata( storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 1, prefix, suffix); getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 1, prefix, suffix);
} }
return ɵɵattributeInterpolate1; return ɵɵattributeInterpolate1;
} }
@ -86,13 +84,11 @@ export function ɵɵattributeInterpolate2(
const lView = getLView(); const lView = getLView();
const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix); const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex(); const tNode = getSelectedTNode();
const tView = getTView(); elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && ngDevMode &&
storePropertyBindingMetadata( storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 2, prefix, i0, suffix); getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 2, prefix, i0, suffix);
} }
return ɵɵattributeInterpolate2; return ɵɵattributeInterpolate2;
} }
@ -132,12 +128,10 @@ export function ɵɵattributeInterpolate3(
const lView = getLView(); const lView = getLView();
const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix); const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex(); const tNode = getSelectedTNode();
const tView = getTView(); elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata( ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 3, prefix, i0, getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 3, prefix, i0,
i1, suffix); i1, suffix);
} }
return ɵɵattributeInterpolate3; return ɵɵattributeInterpolate3;
@ -181,12 +175,10 @@ export function ɵɵattributeInterpolate4(
const lView = getLView(); const lView = getLView();
const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix); const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex(); const tNode = getSelectedTNode();
const tView = getTView(); elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata( ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 4, prefix, i0, getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 4, prefix, i0,
i1, i2, suffix); i1, i2, suffix);
} }
return ɵɵattributeInterpolate4; return ɵɵattributeInterpolate4;
@ -233,12 +225,10 @@ export function ɵɵattributeInterpolate5(
const interpolatedValue = const interpolatedValue =
interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix); interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex(); const tNode = getSelectedTNode();
const tView = getTView(); elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata( ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 5, prefix, i0, getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 5, prefix, i0,
i1, i2, i3, suffix); i1, i2, i3, suffix);
} }
return ɵɵattributeInterpolate5; return ɵɵattributeInterpolate5;
@ -287,12 +277,10 @@ export function ɵɵattributeInterpolate6(
const interpolatedValue = const interpolatedValue =
interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix); interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex(); const tNode = getSelectedTNode();
const tView = getTView(); elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata( ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 6, prefix, i0, getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 6, prefix, i0,
i1, i2, i3, i4, suffix); i1, i2, i3, i4, suffix);
} }
return ɵɵattributeInterpolate6; return ɵɵattributeInterpolate6;
@ -343,12 +331,10 @@ export function ɵɵattributeInterpolate7(
const interpolatedValue = const interpolatedValue =
interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix); interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex(); const tNode = getSelectedTNode();
const tView = getTView(); elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata( ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 7, prefix, i0, getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 7, prefix, i0,
i1, i2, i3, i4, i5, suffix); i1, i2, i3, i4, i5, suffix);
} }
return ɵɵattributeInterpolate7; return ɵɵattributeInterpolate7;
@ -401,12 +387,10 @@ export function ɵɵattributeInterpolate8(
const interpolatedValue = interpolation8( const interpolatedValue = interpolation8(
lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix); lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex(); const tNode = getSelectedTNode();
const tView = getTView(); elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
elementAttributeInternal(
nodeIndex, attrName, interpolatedValue, tView, lView, sanitizer, namespace);
ngDevMode && storePropertyBindingMetadata( ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getBindingIndex() - 8, prefix, i0, getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 8, prefix, i0,
i1, i2, i3, i4, i5, i6, suffix); i1, i2, i3, i4, i5, i6, suffix);
} }
return ɵɵattributeInterpolate8; return ɵɵattributeInterpolate8;
@ -444,16 +428,15 @@ export function ɵɵattributeInterpolateV(
const lView = getLView(); const lView = getLView();
const interpolated = interpolationV(lView, values); const interpolated = interpolationV(lView, values);
if (interpolated !== NO_CHANGE) { if (interpolated !== NO_CHANGE) {
const tView = getTView(); const tNode = getSelectedTNode();
const nodeIndex = getSelectedIndex(); elementAttributeInternal(tNode, lView, attrName, interpolated, sanitizer, namespace);
elementAttributeInternal(nodeIndex, attrName, interpolated, tView, lView, sanitizer, namespace);
if (ngDevMode) { if (ngDevMode) {
const interpolationInBetween = [values[0]]; // prefix const interpolationInBetween = [values[0]]; // prefix
for (let i = 2; i < values.length; i += 2) { for (let i = 2; i < values.length; i += 2) {
interpolationInBetween.push(values[i]); interpolationInBetween.push(values[i]);
} }
storePropertyBindingMetadata( storePropertyBindingMetadata(
tView.data, nodeIndex, 'attr.' + attrName, getTView().data, tNode, 'attr.' + attrName,
getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween); getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
} }
} }

View File

@ -7,8 +7,10 @@
*/ */
import {bindingUpdated} from '../bindings'; import {bindingUpdated} from '../bindings';
import {SanitizerFn} from '../interfaces/sanitization'; import {SanitizerFn} from '../interfaces/sanitization';
import {getLView, getSelectedIndex, getTView, nextBindingIndex} from '../state'; import {RENDERER} from '../interfaces/view';
import {getLView, getSelectedTNode, getTView, nextBindingIndex} from '../state';
import {NO_CHANGE} from '../tokens'; import {NO_CHANGE} from '../tokens';
import {elementPropertyInternal, loadComponentRenderer, storePropertyBindingMetadata} from './shared'; import {elementPropertyInternal, loadComponentRenderer, storePropertyBindingMetadata} from './shared';
/** /**
@ -30,10 +32,10 @@ export function ɵɵhostProperty<T>(
const lView = getLView(); const lView = getLView();
const bindingIndex = nextBindingIndex(); const bindingIndex = nextBindingIndex();
if (bindingUpdated(lView, bindingIndex, value)) { if (bindingUpdated(lView, bindingIndex, value)) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, value, sanitizer, true); const tNode = getSelectedTNode();
ngDevMode && storePropertyBindingMetadata(tView.data, nodeIndex, propName, bindingIndex); elementPropertyInternal(tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, true);
ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
} }
return ɵɵhostProperty; return ɵɵhostProperty;
} }
@ -66,11 +68,11 @@ export function ɵɵupdateSyntheticHostBinding<T>(
const lView = getLView(); const lView = getLView();
const bindingIndex = nextBindingIndex(); const bindingIndex = nextBindingIndex();
if (bindingUpdated(lView, bindingIndex, value)) { if (bindingUpdated(lView, bindingIndex, value)) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal( const tNode = getSelectedTNode();
tView, lView, nodeIndex, propName, value, sanitizer, true, loadComponentRenderer); const renderer = loadComponentRenderer(tNode, lView);
ngDevMode && storePropertyBindingMetadata(tView.data, nodeIndex, propName, bindingIndex); elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, true);
ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
} }
return ɵɵupdateSyntheticHostBinding; return ɵɵupdateSyntheticHostBinding;
} }

View File

@ -8,8 +8,9 @@
import {bindingUpdated} from '../bindings'; import {bindingUpdated} from '../bindings';
import {TNode} from '../interfaces/node'; import {TNode} from '../interfaces/node';
import {SanitizerFn} from '../interfaces/sanitization'; import {SanitizerFn} from '../interfaces/sanitization';
import {LView, TView} from '../interfaces/view'; import {LView, RENDERER, TView} from '../interfaces/view';
import {getLView, getSelectedIndex, getTView, nextBindingIndex} from '../state'; import {getLView, getSelectedTNode, getTView, nextBindingIndex} from '../state';
import {elementPropertyInternal, setInputsForProperty, storePropertyBindingMetadata} from './shared'; import {elementPropertyInternal, setInputsForProperty, storePropertyBindingMetadata} from './shared';
@ -36,10 +37,11 @@ export function ɵɵproperty<T>(
const lView = getLView(); const lView = getLView();
const bindingIndex = nextBindingIndex(); const bindingIndex = nextBindingIndex();
if (bindingUpdated(lView, bindingIndex, value)) { if (bindingUpdated(lView, bindingIndex, value)) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, value, sanitizer); const tNode = getSelectedTNode();
ngDevMode && storePropertyBindingMetadata(tView.data, nodeIndex, propName, bindingIndex); elementPropertyInternal(
tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, false);
ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
} }
return ɵɵproperty; return ɵɵproperty;
} }

View File

@ -6,8 +6,10 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {SanitizerFn} from '../interfaces/sanitization'; import {SanitizerFn} from '../interfaces/sanitization';
import {getBindingIndex, getLView, getSelectedIndex, getTView} from '../state'; import {RENDERER} from '../interfaces/view';
import {getBindingIndex, getLView, getSelectedTNode, getTView} from '../state';
import {NO_CHANGE} from '../tokens'; import {NO_CHANGE} from '../tokens';
import {interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV} from './interpolation'; import {interpolation1, interpolation2, interpolation3, interpolation4, interpolation5, interpolation6, interpolation7, interpolation8, interpolationV} from './interpolation';
import {elementPropertyInternal, storePropertyBindingMetadata} from './shared'; import {elementPropertyInternal, storePropertyBindingMetadata} from './shared';
@ -82,11 +84,12 @@ export function ɵɵpropertyInterpolate1(
const lView = getLView(); const lView = getLView();
const interpolatedValue = interpolation1(lView, prefix, v0, suffix); const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer); const tNode = getSelectedTNode();
elementPropertyInternal(
tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
ngDevMode && storePropertyBindingMetadata( ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, propName, getBindingIndex() - 1, prefix, suffix); tView.data, tNode, propName, getBindingIndex() - 1, prefix, suffix);
} }
return ɵɵpropertyInterpolate1; return ɵɵpropertyInterpolate1;
} }
@ -127,11 +130,12 @@ export function ɵɵpropertyInterpolate2(
const lView = getLView(); const lView = getLView();
const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix); const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer); const tNode = getSelectedTNode();
elementPropertyInternal(
tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
ngDevMode && storePropertyBindingMetadata( ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, propName, getBindingIndex() - 2, prefix, i0, suffix); tView.data, tNode, propName, getBindingIndex() - 2, prefix, i0, suffix);
} }
return ɵɵpropertyInterpolate2; return ɵɵpropertyInterpolate2;
} }
@ -175,12 +179,12 @@ export function ɵɵpropertyInterpolate3(
const lView = getLView(); const lView = getLView();
const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix); const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer); const tNode = getSelectedTNode();
ngDevMode && elementPropertyInternal(
storePropertyBindingMetadata( tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
tView.data, nodeIndex, propName, getBindingIndex() - 3, prefix, i0, i1, suffix); ngDevMode && storePropertyBindingMetadata(
tView.data, tNode, propName, getBindingIndex() - 3, prefix, i0, i1, suffix);
} }
return ɵɵpropertyInterpolate3; return ɵɵpropertyInterpolate3;
} }
@ -226,12 +230,13 @@ export function ɵɵpropertyInterpolate4(
const lView = getLView(); const lView = getLView();
const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix); const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer); const tNode = getSelectedTNode();
elementPropertyInternal(
tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
ngDevMode && ngDevMode &&
storePropertyBindingMetadata( storePropertyBindingMetadata(
tView.data, nodeIndex, propName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix); tView.data, tNode, propName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix);
} }
return ɵɵpropertyInterpolate4; return ɵɵpropertyInterpolate4;
} }
@ -281,12 +286,13 @@ export function ɵɵpropertyInterpolate5(
const interpolatedValue = const interpolatedValue =
interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix); interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer); const tNode = getSelectedTNode();
elementPropertyInternal(
tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
ngDevMode && ngDevMode &&
storePropertyBindingMetadata( storePropertyBindingMetadata(
tView.data, nodeIndex, propName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix); tView.data, tNode, propName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix);
} }
return ɵɵpropertyInterpolate5; return ɵɵpropertyInterpolate5;
} }
@ -338,12 +344,13 @@ export function ɵɵpropertyInterpolate6(
const interpolatedValue = const interpolatedValue =
interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix); interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer); const tNode = getSelectedTNode();
ngDevMode && storePropertyBindingMetadata( elementPropertyInternal(
tView.data, nodeIndex, propName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
i4, suffix); ngDevMode &&
storePropertyBindingMetadata(
tView.data, tNode, propName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix);
} }
return ɵɵpropertyInterpolate6; return ɵɵpropertyInterpolate6;
} }
@ -397,12 +404,13 @@ export function ɵɵpropertyInterpolate7(
const interpolatedValue = const interpolatedValue =
interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix); interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer); const tNode = getSelectedTNode();
elementPropertyInternal(
tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
ngDevMode && storePropertyBindingMetadata( ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, propName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, tView.data, tNode, propName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4,
i4, i5, suffix); i5, suffix);
} }
return ɵɵpropertyInterpolate7; return ɵɵpropertyInterpolate7;
} }
@ -458,12 +466,13 @@ export function ɵɵpropertyInterpolate8(
const interpolatedValue = interpolation8( const interpolatedValue = interpolation8(
lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix); lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer); const tNode = getSelectedTNode();
elementPropertyInternal(
tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
ngDevMode && storePropertyBindingMetadata( ngDevMode && storePropertyBindingMetadata(
tView.data, nodeIndex, propName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, tView.data, tNode, propName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4,
i4, i5, i6, suffix); i5, i6, suffix);
} }
return ɵɵpropertyInterpolate8; return ɵɵpropertyInterpolate8;
} }
@ -503,16 +512,17 @@ export function ɵɵpropertyInterpolateV(
const lView = getLView(); const lView = getLView();
const interpolatedValue = interpolationV(lView, values); const interpolatedValue = interpolationV(lView, values);
if (interpolatedValue !== NO_CHANGE) { if (interpolatedValue !== NO_CHANGE) {
const nodeIndex = getSelectedIndex();
const tView = getTView(); const tView = getTView();
elementPropertyInternal(tView, lView, nodeIndex, propName, interpolatedValue, sanitizer); const tNode = getSelectedTNode();
elementPropertyInternal(
tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
if (ngDevMode) { if (ngDevMode) {
const interpolationInBetween = [values[0]]; // prefix const interpolationInBetween = [values[0]]; // prefix
for (let i = 2; i < values.length; i += 2) { for (let i = 2; i < values.length; i += 2) {
interpolationInBetween.push(values[i]); interpolationInBetween.push(values[i]);
} }
storePropertyBindingMetadata( storePropertyBindingMetadata(
tView.data, nodeIndex, propName, getBindingIndex() - interpolationInBetween.length + 1, tView.data, tNode, propName, getBindingIndex() - interpolationInBetween.length + 1,
...interpolationInBetween); ...interpolationInBetween);
} }
} }

View File

@ -941,17 +941,15 @@ function mapPropName(name: string): string {
} }
export function elementPropertyInternal<T>( export function elementPropertyInternal<T>(
tView: TView, lView: LView, index: number, propName: string, value: T, tView: TView, tNode: TNode, lView: LView, propName: string, value: T, renderer: Renderer3,
sanitizer?: SanitizerFn | null, nativeOnly?: boolean, sanitizer: SanitizerFn | null | undefined, nativeOnly: boolean): void {
loadRendererFn?: ((tNode: TNode, lView: LView) => Renderer3) | null): void {
ngDevMode && assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.'); ngDevMode && assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.');
const element = getNativeByIndex(index, lView) as RElement | RComment; const element = getNativeByTNode(tNode, lView) as RElement | RComment;
const tNode = getTNode(tView, index);
let inputData = tNode.inputs; let inputData = tNode.inputs;
let dataValue: PropertyAliasValue|undefined; let dataValue: PropertyAliasValue|undefined;
if (!nativeOnly && inputData != null && (dataValue = inputData[propName])) { if (!nativeOnly && inputData != null && (dataValue = inputData[propName])) {
setInputsForProperty(tView, lView, dataValue, propName, value); setInputsForProperty(tView, lView, dataValue, propName, value);
if (isComponentHost(tNode)) markDirtyIfOnPush(lView, index + HEADER_OFFSET); if (isComponentHost(tNode)) markDirtyIfOnPush(lView, tNode.index);
if (ngDevMode) { if (ngDevMode) {
setNgReflectProperties(lView, element, tNode.type, dataValue, value); setNgReflectProperties(lView, element, tNode.type, dataValue, value);
} }
@ -968,7 +966,6 @@ export function elementPropertyInternal<T>(
ngDevMode.rendererSetProperty++; ngDevMode.rendererSetProperty++;
} }
const renderer = loadRendererFn ? loadRendererFn(tNode, lView) : lView[RENDERER];
// It is assumed that the sanitizer is only added when the compiler determines that the // It is assumed that the sanitizer is only added when the compiler determines that the
// property is risky, so sanitization can be done without further checks. // property is risky, so sanitization can be done without further checks.
value = sanitizer != null ? (sanitizer(value, tNode.tagName || '', propName) as any) : value; value = sanitizer != null ? (sanitizer(value, tNode.tagName || '', propName) as any) : value;
@ -1438,11 +1435,11 @@ function addComponentLogic<T>(lView: LView, hostTNode: TElementNode, def: Compon
} }
export function elementAttributeInternal( export function elementAttributeInternal(
index: number, name: string, value: any, tView: TView, lView: LView, tNode: TNode, lView: LView, name: string, value: any, sanitizer: SanitizerFn | null | undefined,
sanitizer?: SanitizerFn | null, namespace?: string) { namespace: string | null | undefined) {
ngDevMode && assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.'); ngDevMode && assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.');
ngDevMode && validateAgainstEventAttributes(name); ngDevMode && validateAgainstEventAttributes(name);
const element = getNativeByIndex(index, lView) as RElement; const element = getNativeByTNode(tNode, lView) as RElement;
const renderer = lView[RENDERER]; const renderer = lView[RENDERER];
if (value == null) { if (value == null) {
ngDevMode && ngDevMode.rendererRemoveAttribute++; ngDevMode && ngDevMode.rendererRemoveAttribute++;
@ -1450,7 +1447,6 @@ export function elementAttributeInternal(
element.removeAttribute(name); element.removeAttribute(name);
} else { } else {
ngDevMode && ngDevMode.rendererSetAttribute++; ngDevMode && ngDevMode.rendererSetAttribute++;
const tNode = getTNode(tView, index);
const strValue = const strValue =
sanitizer == null ? renderStringify(value) : sanitizer(value, tNode.tagName || '', name); sanitizer == null ? renderStringify(value) : sanitizer(value, tNode.tagName || '', name);
@ -1892,19 +1888,18 @@ function executeViewQueryFn<T>(
* interpolated properties. * interpolated properties.
* *
* @param tData `TData` where meta-data will be saved; * @param tData `TData` where meta-data will be saved;
* @param nodeIndex index of a `TNode` that is a target of the binding; * @param tNode `TNode` that is a target of the binding;
* @param propertyName bound property name; * @param propertyName bound property name;
* @param bindingIndex binding index in `LView` * @param bindingIndex binding index in `LView`
* @param interpolationParts static interpolation parts (for property interpolations) * @param interpolationParts static interpolation parts (for property interpolations)
*/ */
export function storePropertyBindingMetadata( export function storePropertyBindingMetadata(
tData: TData, nodeIndex: number, propertyName: string, bindingIndex: number, tData: TData, tNode: TNode, propertyName: string, bindingIndex: number,
...interpolationParts: string[]) { ...interpolationParts: string[]) {
// Binding meta-data are stored only the first time a given property instruction is processed. // Binding meta-data are stored only the first time a given property instruction is processed.
// Since we don't have a concept of the "first update pass" we need to check for presence of the // Since we don't have a concept of the "first update pass" we need to check for presence of the
// binding meta-data to decide if one should be stored (or if was stored already). // binding meta-data to decide if one should be stored (or if was stored already).
if (tData[bindingIndex] === null) { if (tData[bindingIndex] === null) {
const tNode = tData[nodeIndex + HEADER_OFFSET] as TNode;
if (tNode.inputs == null || !tNode.inputs[propertyName]) { if (tNode.inputs == null || !tNode.inputs[propertyName]) {
const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []); const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []);
propBindingIdxs.push(bindingIndex); propBindingIdxs.push(bindingIndex);

View File

@ -12,6 +12,7 @@ import {assertLViewOrUndefined} from './assert';
import {TNode} from './interfaces/node'; import {TNode} from './interfaces/node';
import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState, TVIEW, TView} from './interfaces/view'; import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState, TVIEW, TView} from './interfaces/view';
import {MATH_ML_NAMESPACE, SVG_NAMESPACE} from './namespaces'; import {MATH_ML_NAMESPACE, SVG_NAMESPACE} from './namespaces';
import {getTNode} from './util/view_utils';
/** /**
@ -532,6 +533,13 @@ export function setSelectedIndex(index: number) {
instructionState.lFrame.selectedIndex = index; instructionState.lFrame.selectedIndex = index;
} }
/**
* Gets the `tNode` that represents currently selected element.
*/
export function getSelectedTNode() {
const lFrame = instructionState.lFrame;
return getTNode(lFrame.tView, lFrame.selectedIndex);
}
/** /**
* Sets the namespace used to create elements to `'http://www.w3.org/2000/svg'` in global state. * Sets the namespace used to create elements to `'http://www.w3.org/2000/svg'` in global state.

View File

@ -191,6 +191,9 @@
{ {
"name": "newArray" "name": "newArray"
}, },
{
"name": "noSideEffects"
},
{ {
"name": "providerToFactory" "name": "providerToFactory"
}, },
@ -223,8 +226,5 @@
}, },
{ {
"name": "ɵɵinject" "name": "ɵɵinject"
},
{
"name": "noSideEffects"
} }
] ]

View File

@ -707,6 +707,9 @@
{ {
"name": "getSelectedIndex" "name": "getSelectedIndex"
}, },
{
"name": "getSelectedTNode"
},
{ {
"name": "getSymbolIterator" "name": "getSymbolIterator"
}, },