refactor(ivy): move `bindingIndex` from `LView` to `LFrame` (#33235)
`bindingIndex` stores the current location of the bindings in the template function. Because it used to be stored in `LView` that `LView` was not reentrant. This could happen if a binding was a getter and had a side-effect of calling `detectChanges()`. By moving the `bindingIndex` to `LFrame` where all of the global state is kept in reentrant way we correct the issue. PR Close #33235
This commit is contained in:
parent
c61f413477
commit
e16f75db56
|
@ -12,7 +12,7 @@
|
||||||
"master": {
|
"master": {
|
||||||
"uncompressed": {
|
"uncompressed": {
|
||||||
"runtime-es2015": 1485,
|
"runtime-es2015": 1485,
|
||||||
"main-es2015": 14678,
|
"main-es2015": 14861,
|
||||||
"polyfills-es2015": 36808
|
"polyfills-es2015": 36808
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,4 +64,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,9 @@ import {TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjecti
|
||||||
import {RComment, RElement, RText} from './interfaces/renderer';
|
import {RComment, RElement, RText} from './interfaces/renderer';
|
||||||
import {SanitizerFn} from './interfaces/sanitization';
|
import {SanitizerFn} from './interfaces/sanitization';
|
||||||
import {isLContainer} from './interfaces/type_checks';
|
import {isLContainer} from './interfaces/type_checks';
|
||||||
import {BINDING_INDEX, HEADER_OFFSET, LView, RENDERER, TVIEW, TView, T_HOST} from './interfaces/view';
|
import {HEADER_OFFSET, LView, RENDERER, TVIEW, TView, T_HOST} from './interfaces/view';
|
||||||
import {appendChild, applyProjection, createTextNode, nativeRemoveNode} from './node_manipulation';
|
import {appendChild, applyProjection, createTextNode, nativeRemoveNode} from './node_manipulation';
|
||||||
import {getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from './state';
|
import {getBindingIndex, getIsParent, getLView, getPreviousOrParentTNode, nextBindingIndex, setIsNotParent, setPreviousOrParentTNode} from './state';
|
||||||
import {renderStringify} from './util/misc_utils';
|
import {renderStringify} from './util/misc_utils';
|
||||||
import {getNativeByIndex, getNativeByTNode, getTNode, load} from './util/view_utils';
|
import {getNativeByIndex, getNativeByTNode, getTNode, load} from './util/view_utils';
|
||||||
|
|
||||||
|
@ -669,7 +669,7 @@ export function ɵɵi18nEnd(): void {
|
||||||
*/
|
*/
|
||||||
function i18nEndFirstPass(lView: LView, tView: TView) {
|
function i18nEndFirstPass(lView: LView, tView: TView) {
|
||||||
ngDevMode && assertEqual(
|
ngDevMode && assertEqual(
|
||||||
lView[BINDING_INDEX], tView.bindingStartIndex,
|
getBindingIndex(), tView.bindingStartIndex,
|
||||||
'i18nEnd should be called before any binding');
|
'i18nEnd should be called before any binding');
|
||||||
|
|
||||||
const rootIndex = i18nIndexStack[i18nIndexStackPointer--];
|
const rootIndex = i18nIndexStack[i18nIndexStackPointer--];
|
||||||
|
@ -1036,7 +1036,7 @@ let shiftsCounter = 0;
|
||||||
*/
|
*/
|
||||||
export function ɵɵi18nExp<T>(value: T): TsickleIssue1009 {
|
export function ɵɵi18nExp<T>(value: T): TsickleIssue1009 {
|
||||||
const lView = getLView();
|
const lView = getLView();
|
||||||
if (bindingUpdated(lView, lView[BINDING_INDEX]++, value)) {
|
if (bindingUpdated(lView, nextBindingIndex(), value)) {
|
||||||
changeMask = changeMask | (1 << shiftsCounter);
|
changeMask = changeMask | (1 << shiftsCounter);
|
||||||
}
|
}
|
||||||
shiftsCounter++;
|
shiftsCounter++;
|
||||||
|
@ -1065,7 +1065,7 @@ export function ɵɵi18nApply(index: number) {
|
||||||
updateOpCodes = (tI18n as TI18n).update;
|
updateOpCodes = (tI18n as TI18n).update;
|
||||||
icus = (tI18n as TI18n).icus;
|
icus = (tI18n as TI18n).icus;
|
||||||
}
|
}
|
||||||
const bindingsStartIndex = lView[BINDING_INDEX] - shiftsCounter - 1;
|
const bindingsStartIndex = getBindingIndex() - shiftsCounter - 1;
|
||||||
readUpdateOpCodes(updateOpCodes, icus, bindingsStartIndex, changeMask, lView);
|
readUpdateOpCodes(updateOpCodes, icus, bindingsStartIndex, changeMask, lView);
|
||||||
|
|
||||||
// Reset changeMask & maskBit to default for the next update cycle
|
// Reset changeMask & maskBit to default for the next update cycle
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
*/
|
*/
|
||||||
import {bindingUpdated} from '../bindings';
|
import {bindingUpdated} from '../bindings';
|
||||||
import {SanitizerFn} from '../interfaces/sanitization';
|
import {SanitizerFn} from '../interfaces/sanitization';
|
||||||
import {BINDING_INDEX} from '../interfaces/view';
|
import {getLView, getSelectedIndex, nextBindingIndex} from '../state';
|
||||||
import {getLView, getSelectedIndex} from '../state';
|
|
||||||
|
|
||||||
import {TsickleIssue1009, elementAttributeInternal} from './shared';
|
import {TsickleIssue1009, elementAttributeInternal} from './shared';
|
||||||
|
|
||||||
|
@ -31,7 +30,7 @@ export function ɵɵattribute(
|
||||||
name: string, value: any, sanitizer?: SanitizerFn | null,
|
name: string, value: any, sanitizer?: SanitizerFn | null,
|
||||||
namespace?: string): TsickleIssue1009 {
|
namespace?: string): TsickleIssue1009 {
|
||||||
const lView = getLView();
|
const lView = getLView();
|
||||||
if (bindingUpdated(lView, lView[BINDING_INDEX]++, value)) {
|
if (bindingUpdated(lView, nextBindingIndex(), value)) {
|
||||||
elementAttributeInternal(getSelectedIndex(), name, value, lView, sanitizer, namespace);
|
elementAttributeInternal(getSelectedIndex(), name, value, lView, sanitizer, namespace);
|
||||||
}
|
}
|
||||||
return ɵɵattribute;
|
return ɵɵattribute;
|
||||||
|
|
|
@ -11,12 +11,12 @@ import {attachPatchData} from '../context_discovery';
|
||||||
import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags, registerPostOrderHooks} from '../hooks';
|
import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags, registerPostOrderHooks} from '../hooks';
|
||||||
import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container';
|
import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container';
|
||||||
import {ComponentTemplate} from '../interfaces/definition';
|
import {ComponentTemplate} from '../interfaces/definition';
|
||||||
import {LocalRefExtractor, TAttributes, TContainerNode, TNode, TNodeFlags, TNodeType, TViewNode} from '../interfaces/node';
|
import {LocalRefExtractor, TAttributes, TContainerNode, TNode, TNodeType, TViewNode} from '../interfaces/node';
|
||||||
import {isDirectiveHost} from '../interfaces/type_checks';
|
import {isDirectiveHost} from '../interfaces/type_checks';
|
||||||
import {BINDING_INDEX, FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
|
import {FLAGS, HEADER_OFFSET, InitPhaseState, LView, LViewFlags, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
|
||||||
import {assertNodeType} from '../node_assert';
|
import {assertNodeType} from '../node_assert';
|
||||||
import {appendChild, removeView} from '../node_manipulation';
|
import {appendChild, removeView} from '../node_manipulation';
|
||||||
import {getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
|
import {getBindingIndex, getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
|
||||||
import {getNativeByTNode, load} from '../util/view_utils';
|
import {getNativeByTNode, load} from '../util/view_utils';
|
||||||
|
|
||||||
import {addToViewTree, createDirectivesInstances, createLContainer, createTNode, createTView, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';
|
import {addToViewTree, createDirectivesInstances, createLContainer, createTNode, createTView, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';
|
||||||
|
@ -172,7 +172,7 @@ function containerInternal(
|
||||||
lView: LView, nodeIndex: number, tagName: string | null,
|
lView: LView, nodeIndex: number, tagName: string | null,
|
||||||
attrs: TAttributes | null): TContainerNode {
|
attrs: TAttributes | null): TContainerNode {
|
||||||
ngDevMode && assertEqual(
|
ngDevMode && assertEqual(
|
||||||
lView[BINDING_INDEX], lView[TVIEW].bindingStartIndex,
|
getBindingIndex(), lView[TVIEW].bindingStartIndex,
|
||||||
'container nodes should be created before any bindings');
|
'container nodes should be created before any bindings');
|
||||||
|
|
||||||
const adjustedIndex = nodeIndex + HEADER_OFFSET;
|
const adjustedIndex = nodeIndex + HEADER_OFFSET;
|
||||||
|
|
|
@ -14,10 +14,10 @@ import {TAttributes, TNodeFlags, TNodeType} from '../interfaces/node';
|
||||||
import {RElement} from '../interfaces/renderer';
|
import {RElement} from '../interfaces/renderer';
|
||||||
import {StylingMapArray, TStylingContext} from '../interfaces/styling';
|
import {StylingMapArray, TStylingContext} from '../interfaces/styling';
|
||||||
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
|
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
|
||||||
import {BINDING_INDEX, HEADER_OFFSET, LView, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
|
import {HEADER_OFFSET, LView, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
|
||||||
import {assertNodeType} from '../node_assert';
|
import {assertNodeType} from '../node_assert';
|
||||||
import {appendChild} from '../node_manipulation';
|
import {appendChild} from '../node_manipulation';
|
||||||
import {decreaseElementDepthCount, getElementDepthCount, getIsParent, getLView, getNamespace, getPreviousOrParentTNode, getSelectedIndex, increaseElementDepthCount, setIsNotParent, setPreviousOrParentTNode} from '../state';
|
import {decreaseElementDepthCount, getBindingIndex, getElementDepthCount, getIsParent, getLView, getNamespace, getPreviousOrParentTNode, getSelectedIndex, increaseElementDepthCount, setIsNotParent, setPreviousOrParentTNode} from '../state';
|
||||||
import {setUpAttributes} from '../util/attrs_utils';
|
import {setUpAttributes} from '../util/attrs_utils';
|
||||||
import {getInitialStylingValue, hasClassInput, hasStyleInput, selectClassBasedInputName} from '../util/styling_utils';
|
import {getInitialStylingValue, hasClassInput, hasStyleInput, selectClassBasedInputName} from '../util/styling_utils';
|
||||||
import {getNativeByTNode, getTNode} from '../util/view_utils';
|
import {getNativeByTNode, getTNode} from '../util/view_utils';
|
||||||
|
@ -48,7 +48,7 @@ export function ɵɵelementStart(
|
||||||
const tViewConsts = tView.consts;
|
const tViewConsts = tView.consts;
|
||||||
const consts = tViewConsts === null || constsIndex == null ? null : tViewConsts[constsIndex];
|
const consts = tViewConsts === null || constsIndex == null ? null : tViewConsts[constsIndex];
|
||||||
ngDevMode && assertEqual(
|
ngDevMode && assertEqual(
|
||||||
lView[BINDING_INDEX], tView.bindingStartIndex,
|
getBindingIndex(), tView.bindingStartIndex,
|
||||||
'elements should be created before any bindings');
|
'elements should be created before any bindings');
|
||||||
|
|
||||||
ngDevMode && ngDevMode.rendererCreateElement++;
|
ngDevMode && ngDevMode.rendererCreateElement++;
|
||||||
|
|
|
@ -11,10 +11,10 @@ import {attachPatchData} from '../context_discovery';
|
||||||
import {registerPostOrderHooks} from '../hooks';
|
import {registerPostOrderHooks} from '../hooks';
|
||||||
import {TAttributes, TNodeType} from '../interfaces/node';
|
import {TAttributes, TNodeType} from '../interfaces/node';
|
||||||
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
|
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
|
||||||
import {BINDING_INDEX, HEADER_OFFSET, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
|
import {HEADER_OFFSET, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
|
||||||
import {assertNodeType} from '../node_assert';
|
import {assertNodeType} from '../node_assert';
|
||||||
import {appendChild} from '../node_manipulation';
|
import {appendChild} from '../node_manipulation';
|
||||||
import {getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
|
import {getBindingIndex, getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
|
||||||
|
|
||||||
import {createDirectivesInstances, executeContentQueries, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';
|
import {createDirectivesInstances, executeContentQueries, getOrCreateTNode, resolveDirectives, saveResolvedLocalsInData} from './shared';
|
||||||
import {registerInitialStylingOnTNode} from './styling';
|
import {registerInitialStylingOnTNode} from './styling';
|
||||||
|
@ -44,7 +44,7 @@ export function ɵɵelementContainerStart(
|
||||||
const tViewConsts = tView.consts;
|
const tViewConsts = tView.consts;
|
||||||
const consts = tViewConsts === null || constsIndex == null ? null : tViewConsts[constsIndex];
|
const consts = tViewConsts === null || constsIndex == null ? null : tViewConsts[constsIndex];
|
||||||
ngDevMode && assertEqual(
|
ngDevMode && assertEqual(
|
||||||
lView[BINDING_INDEX], tView.bindingStartIndex,
|
getBindingIndex(), tView.bindingStartIndex,
|
||||||
'element containers should be created before any bindings');
|
'element containers should be created before any bindings');
|
||||||
|
|
||||||
ngDevMode && ngDevMode.rendererCreateComment++;
|
ngDevMode && ngDevMode.rendererCreateComment++;
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
*/
|
*/
|
||||||
import {bindingUpdated} from '../bindings';
|
import {bindingUpdated} from '../bindings';
|
||||||
import {SanitizerFn} from '../interfaces/sanitization';
|
import {SanitizerFn} from '../interfaces/sanitization';
|
||||||
import {BINDING_INDEX, TVIEW} from '../interfaces/view';
|
import {TVIEW} from '../interfaces/view';
|
||||||
import {getLView, getSelectedIndex} from '../state';
|
import {getLView, getSelectedIndex, nextBindingIndex} from '../state';
|
||||||
import {NO_CHANGE} from '../tokens';
|
import {NO_CHANGE} from '../tokens';
|
||||||
|
|
||||||
import {TsickleIssue1009, elementPropertyInternal, loadComponentRenderer, storePropertyBindingMetadata} from './shared';
|
import {TsickleIssue1009, elementPropertyInternal, loadComponentRenderer, storePropertyBindingMetadata} from './shared';
|
||||||
|
@ -30,7 +30,7 @@ import {TsickleIssue1009, elementPropertyInternal, loadComponentRenderer, storeP
|
||||||
export function ɵɵhostProperty<T>(
|
export function ɵɵhostProperty<T>(
|
||||||
propName: string, value: T, sanitizer?: SanitizerFn | null): TsickleIssue1009 {
|
propName: string, value: T, sanitizer?: SanitizerFn | null): TsickleIssue1009 {
|
||||||
const lView = getLView();
|
const lView = getLView();
|
||||||
const bindingIndex = lView[BINDING_INDEX]++;
|
const bindingIndex = nextBindingIndex();
|
||||||
if (bindingUpdated(lView, bindingIndex, value)) {
|
if (bindingUpdated(lView, bindingIndex, value)) {
|
||||||
const nodeIndex = getSelectedIndex();
|
const nodeIndex = getSelectedIndex();
|
||||||
elementPropertyInternal(lView, nodeIndex, propName, value, sanitizer, true);
|
elementPropertyInternal(lView, nodeIndex, propName, value, sanitizer, true);
|
||||||
|
@ -64,7 +64,7 @@ export function ɵɵhostProperty<T>(
|
||||||
export function ɵɵupdateSyntheticHostBinding<T>(
|
export function ɵɵupdateSyntheticHostBinding<T>(
|
||||||
propName: string, value: T | NO_CHANGE, sanitizer?: SanitizerFn | null): TsickleIssue1009 {
|
propName: string, value: T | NO_CHANGE, sanitizer?: SanitizerFn | null): TsickleIssue1009 {
|
||||||
const lView = getLView();
|
const lView = getLView();
|
||||||
const bindingIndex = lView[BINDING_INDEX]++;
|
const bindingIndex = nextBindingIndex();
|
||||||
if (bindingUpdated(lView, bindingIndex, value)) {
|
if (bindingUpdated(lView, bindingIndex, value)) {
|
||||||
const nodeIndex = getSelectedIndex();
|
const nodeIndex = getSelectedIndex();
|
||||||
elementPropertyInternal(
|
elementPropertyInternal(
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
|
|
||||||
import {assertEqual, assertLessThan} from '../../util/assert';
|
import {assertEqual, assertLessThan} from '../../util/assert';
|
||||||
import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4} from '../bindings';
|
import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4} from '../bindings';
|
||||||
import {BINDING_INDEX, LView} from '../interfaces/view';
|
import {LView} from '../interfaces/view';
|
||||||
|
import {getBindingIndex, incrementBindingIndex, nextBindingIndex, setBindingIndex} from '../state';
|
||||||
import {NO_CHANGE} from '../tokens';
|
import {NO_CHANGE} from '../tokens';
|
||||||
import {renderStringify} from '../util/misc_utils';
|
import {renderStringify} from '../util/misc_utils';
|
||||||
|
|
||||||
|
@ -30,13 +31,13 @@ export function interpolationV(lView: LView, values: any[]): string|NO_CHANGE {
|
||||||
ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');
|
ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');
|
||||||
ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values');
|
ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values');
|
||||||
let isBindingUpdated = false;
|
let isBindingUpdated = false;
|
||||||
let bindingIndex = lView[BINDING_INDEX];
|
let bindingIndex = getBindingIndex();
|
||||||
|
|
||||||
for (let i = 1; i < values.length; i += 2) {
|
for (let i = 1; i < values.length; i += 2) {
|
||||||
// Check if bindings (odd indexes) have changed
|
// Check if bindings (odd indexes) have changed
|
||||||
isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated;
|
isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated;
|
||||||
}
|
}
|
||||||
lView[BINDING_INDEX] = bindingIndex;
|
setBindingIndex(bindingIndex);
|
||||||
|
|
||||||
if (!isBindingUpdated) {
|
if (!isBindingUpdated) {
|
||||||
return NO_CHANGE;
|
return NO_CHANGE;
|
||||||
|
@ -60,7 +61,7 @@ export function interpolationV(lView: LView, values: any[]): string|NO_CHANGE {
|
||||||
*/
|
*/
|
||||||
export function interpolation1(lView: LView, prefix: string, v0: any, suffix: string): string|
|
export function interpolation1(lView: LView, prefix: string, v0: any, suffix: string): string|
|
||||||
NO_CHANGE {
|
NO_CHANGE {
|
||||||
const different = bindingUpdated(lView, lView[BINDING_INDEX]++, v0);
|
const different = bindingUpdated(lView, nextBindingIndex(), v0);
|
||||||
return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE;
|
return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,9 +70,9 @@ export function interpolation1(lView: LView, prefix: string, v0: any, suffix: st
|
||||||
*/
|
*/
|
||||||
export function interpolation2(
|
export function interpolation2(
|
||||||
lView: LView, prefix: string, v0: any, i0: string, v1: any, suffix: string): string|NO_CHANGE {
|
lView: LView, prefix: string, v0: any, i0: string, v1: any, suffix: string): string|NO_CHANGE {
|
||||||
const bindingIndex = lView[BINDING_INDEX];
|
const bindingIndex = getBindingIndex();
|
||||||
const different = bindingUpdated2(lView, bindingIndex, v0, v1);
|
const different = bindingUpdated2(lView, bindingIndex, v0, v1);
|
||||||
lView[BINDING_INDEX] += 2;
|
incrementBindingIndex(2);
|
||||||
|
|
||||||
return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE;
|
return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE;
|
||||||
}
|
}
|
||||||
|
@ -82,9 +83,9 @@ export function interpolation2(
|
||||||
export function interpolation3(
|
export function interpolation3(
|
||||||
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any,
|
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any,
|
||||||
suffix: string): string|NO_CHANGE {
|
suffix: string): string|NO_CHANGE {
|
||||||
const bindingIndex = lView[BINDING_INDEX];
|
const bindingIndex = getBindingIndex();
|
||||||
const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2);
|
const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2);
|
||||||
lView[BINDING_INDEX] += 3;
|
incrementBindingIndex(3);
|
||||||
|
|
||||||
return different ?
|
return different ?
|
||||||
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix :
|
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix :
|
||||||
|
@ -97,9 +98,9 @@ export function interpolation3(
|
||||||
export function interpolation4(
|
export function interpolation4(
|
||||||
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
||||||
v3: any, suffix: string): string|NO_CHANGE {
|
v3: any, suffix: string): string|NO_CHANGE {
|
||||||
const bindingIndex = lView[BINDING_INDEX];
|
const bindingIndex = getBindingIndex();
|
||||||
const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
|
const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
|
||||||
lView[BINDING_INDEX] += 4;
|
incrementBindingIndex(4);
|
||||||
|
|
||||||
return different ?
|
return different ?
|
||||||
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
|
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
|
||||||
|
@ -113,10 +114,10 @@ export function interpolation4(
|
||||||
export function interpolation5(
|
export function interpolation5(
|
||||||
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
||||||
v3: any, i3: string, v4: any, suffix: string): string|NO_CHANGE {
|
v3: any, i3: string, v4: any, suffix: string): string|NO_CHANGE {
|
||||||
const bindingIndex = lView[BINDING_INDEX];
|
const bindingIndex = getBindingIndex();
|
||||||
let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
|
let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
|
||||||
different = bindingUpdated(lView, bindingIndex + 4, v4) || different;
|
different = bindingUpdated(lView, bindingIndex + 4, v4) || different;
|
||||||
lView[BINDING_INDEX] += 5;
|
incrementBindingIndex(5);
|
||||||
|
|
||||||
return different ?
|
return different ?
|
||||||
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
|
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
|
||||||
|
@ -130,10 +131,10 @@ export function interpolation5(
|
||||||
export function interpolation6(
|
export function interpolation6(
|
||||||
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
||||||
v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string): string|NO_CHANGE {
|
v3: any, i3: string, v4: any, i4: string, v5: any, suffix: string): string|NO_CHANGE {
|
||||||
const bindingIndex = lView[BINDING_INDEX];
|
const bindingIndex = getBindingIndex();
|
||||||
let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
|
let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
|
||||||
different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different;
|
different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different;
|
||||||
lView[BINDING_INDEX] += 6;
|
incrementBindingIndex(6);
|
||||||
|
|
||||||
return different ?
|
return different ?
|
||||||
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
|
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
|
||||||
|
@ -148,10 +149,10 @@ export function interpolation7(
|
||||||
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
||||||
v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string): string|
|
v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, suffix: string): string|
|
||||||
NO_CHANGE {
|
NO_CHANGE {
|
||||||
const bindingIndex = lView[BINDING_INDEX];
|
const bindingIndex = getBindingIndex();
|
||||||
let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
|
let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
|
||||||
different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different;
|
different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different;
|
||||||
lView[BINDING_INDEX] += 7;
|
incrementBindingIndex(7);
|
||||||
|
|
||||||
return different ?
|
return different ?
|
||||||
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
|
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
|
||||||
|
@ -167,10 +168,10 @@ export function interpolation8(
|
||||||
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
lView: LView, prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string,
|
||||||
v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any,
|
v3: any, i3: string, v4: any, i4: string, v5: any, i5: string, v6: any, i6: string, v7: any,
|
||||||
suffix: string): string|NO_CHANGE {
|
suffix: string): string|NO_CHANGE {
|
||||||
const bindingIndex = lView[BINDING_INDEX];
|
const bindingIndex = getBindingIndex();
|
||||||
let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
|
let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
|
||||||
different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different;
|
different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different;
|
||||||
lView[BINDING_INDEX] += 8;
|
incrementBindingIndex(8);
|
||||||
|
|
||||||
return different ?
|
return different ?
|
||||||
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
|
prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {SelectorFlags} from '../interfaces/projection';
|
||||||
import {TQueries} from '../interfaces/query';
|
import {TQueries} from '../interfaces/query';
|
||||||
import {RComment, RElement, RNode} from '../interfaces/renderer';
|
import {RComment, RElement, RNode} from '../interfaces/renderer';
|
||||||
import {TStylingContext} from '../interfaces/styling';
|
import {TStylingContext} from '../interfaces/styling';
|
||||||
import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, HookData, INJECTOR, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, SANITIZER, TData, TVIEW, TView as ITView, TView, T_HOST} from '../interfaces/view';
|
import {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, HookData, INJECTOR, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, RENDERER_FACTORY, SANITIZER, TData, TVIEW, TView as ITView, TView, T_HOST} from '../interfaces/view';
|
||||||
import {DebugNodeStyling, NodeStylingDebug} from '../styling/styling_debug';
|
import {DebugNodeStyling, NodeStylingDebug} from '../styling/styling_debug';
|
||||||
import {attachDebugObject} from '../util/debug_utils';
|
import {attachDebugObject} from '../util/debug_utils';
|
||||||
import {isStylingContext} from '../util/styling_utils';
|
import {isStylingContext} from '../util/styling_utils';
|
||||||
|
@ -325,7 +325,6 @@ export class LViewDebug {
|
||||||
get declarationView() { return toDebug(this._raw_lView[DECLARATION_VIEW]); }
|
get declarationView() { return toDebug(this._raw_lView[DECLARATION_VIEW]); }
|
||||||
get queries() { return this._raw_lView[QUERIES]; }
|
get queries() { return this._raw_lView[QUERIES]; }
|
||||||
get tHost() { return this._raw_lView[T_HOST]; }
|
get tHost() { return this._raw_lView[T_HOST]; }
|
||||||
get bindingIndex() { return this._raw_lView[BINDING_INDEX]; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalized view of child views (and containers) attached at this location.
|
* Normalized view of child views (and containers) attached at this location.
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
*/
|
*/
|
||||||
import {bindingUpdated} from '../bindings';
|
import {bindingUpdated} from '../bindings';
|
||||||
import {SanitizerFn} from '../interfaces/sanitization';
|
import {SanitizerFn} from '../interfaces/sanitization';
|
||||||
import {BINDING_INDEX, TVIEW} from '../interfaces/view';
|
import {TVIEW} from '../interfaces/view';
|
||||||
import {getLView, getSelectedIndex} from '../state';
|
import {getLView, getSelectedIndex, nextBindingIndex} from '../state';
|
||||||
|
|
||||||
import {TsickleIssue1009, elementPropertyInternal, storePropertyBindingMetadata} from './shared';
|
import {TsickleIssue1009, elementPropertyInternal, storePropertyBindingMetadata} from './shared';
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ import {TsickleIssue1009, elementPropertyInternal, storePropertyBindingMetadata}
|
||||||
export function ɵɵproperty<T>(
|
export function ɵɵproperty<T>(
|
||||||
propName: string, value: T, sanitizer?: SanitizerFn | null): TsickleIssue1009 {
|
propName: string, value: T, sanitizer?: SanitizerFn | null): TsickleIssue1009 {
|
||||||
const lView = getLView();
|
const lView = getLView();
|
||||||
const bindingIndex = lView[BINDING_INDEX]++;
|
const bindingIndex = nextBindingIndex();
|
||||||
if (bindingUpdated(lView, bindingIndex, value)) {
|
if (bindingUpdated(lView, bindingIndex, value)) {
|
||||||
const nodeIndex = getSelectedIndex();
|
const nodeIndex = getSelectedIndex();
|
||||||
elementPropertyInternal(lView, nodeIndex, propName, value, sanitizer);
|
elementPropertyInternal(lView, nodeIndex, propName, value, sanitizer);
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
* 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 {BINDING_INDEX, TVIEW} from '../interfaces/view';
|
import {TVIEW} from '../interfaces/view';
|
||||||
import {getLView, getSelectedIndex} from '../state';
|
import {getBindingIndex, getLView, getSelectedIndex} 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';
|
||||||
|
@ -86,9 +86,9 @@ export function ɵɵpropertyInterpolate1(
|
||||||
const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
|
const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
|
||||||
if (interpolatedValue !== NO_CHANGE) {
|
if (interpolatedValue !== NO_CHANGE) {
|
||||||
elementPropertyInternal(lView, getSelectedIndex(), propName, interpolatedValue, sanitizer);
|
elementPropertyInternal(lView, getSelectedIndex(), propName, interpolatedValue, sanitizer);
|
||||||
ngDevMode && storePropertyBindingMetadata(
|
ngDevMode &&
|
||||||
lView[TVIEW].data, getSelectedIndex(), propName, lView[BINDING_INDEX] - 1,
|
storePropertyBindingMetadata(
|
||||||
prefix, suffix);
|
lView[TVIEW].data, getSelectedIndex(), propName, getBindingIndex() - 1, prefix, suffix);
|
||||||
}
|
}
|
||||||
return ɵɵpropertyInterpolate1;
|
return ɵɵpropertyInterpolate1;
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ export function ɵɵpropertyInterpolate2(
|
||||||
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
||||||
ngDevMode &&
|
ngDevMode &&
|
||||||
storePropertyBindingMetadata(
|
storePropertyBindingMetadata(
|
||||||
lView[TVIEW].data, nodeIndex, propName, lView[BINDING_INDEX] - 2, prefix, i0, suffix);
|
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 2, prefix, i0, suffix);
|
||||||
}
|
}
|
||||||
return ɵɵpropertyInterpolate2;
|
return ɵɵpropertyInterpolate2;
|
||||||
}
|
}
|
||||||
|
@ -179,9 +179,9 @@ export function ɵɵpropertyInterpolate3(
|
||||||
if (interpolatedValue !== NO_CHANGE) {
|
if (interpolatedValue !== NO_CHANGE) {
|
||||||
const nodeIndex = getSelectedIndex();
|
const nodeIndex = getSelectedIndex();
|
||||||
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
||||||
ngDevMode && storePropertyBindingMetadata(
|
ngDevMode &&
|
||||||
lView[TVIEW].data, nodeIndex, propName, lView[BINDING_INDEX] - 3, prefix, i0,
|
storePropertyBindingMetadata(
|
||||||
i1, suffix);
|
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 3, prefix, i0, i1, suffix);
|
||||||
}
|
}
|
||||||
return ɵɵpropertyInterpolate3;
|
return ɵɵpropertyInterpolate3;
|
||||||
}
|
}
|
||||||
|
@ -230,8 +230,8 @@ export function ɵɵpropertyInterpolate4(
|
||||||
const nodeIndex = getSelectedIndex();
|
const nodeIndex = getSelectedIndex();
|
||||||
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
||||||
ngDevMode && storePropertyBindingMetadata(
|
ngDevMode && storePropertyBindingMetadata(
|
||||||
lView[TVIEW].data, nodeIndex, propName, lView[BINDING_INDEX] - 4, prefix, i0,
|
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 4, prefix, i0, i1,
|
||||||
i1, i2, suffix);
|
i2, suffix);
|
||||||
}
|
}
|
||||||
return ɵɵpropertyInterpolate4;
|
return ɵɵpropertyInterpolate4;
|
||||||
}
|
}
|
||||||
|
@ -283,8 +283,8 @@ export function ɵɵpropertyInterpolate5(
|
||||||
const nodeIndex = getSelectedIndex();
|
const nodeIndex = getSelectedIndex();
|
||||||
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
||||||
ngDevMode && storePropertyBindingMetadata(
|
ngDevMode && storePropertyBindingMetadata(
|
||||||
lView[TVIEW].data, nodeIndex, propName, lView[BINDING_INDEX] - 5, prefix, i0,
|
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 5, prefix, i0, i1,
|
||||||
i1, i2, i3, suffix);
|
i2, i3, suffix);
|
||||||
}
|
}
|
||||||
return ɵɵpropertyInterpolate5;
|
return ɵɵpropertyInterpolate5;
|
||||||
}
|
}
|
||||||
|
@ -339,8 +339,8 @@ export function ɵɵpropertyInterpolate6(
|
||||||
const nodeIndex = getSelectedIndex();
|
const nodeIndex = getSelectedIndex();
|
||||||
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
||||||
ngDevMode && storePropertyBindingMetadata(
|
ngDevMode && storePropertyBindingMetadata(
|
||||||
lView[TVIEW].data, nodeIndex, propName, lView[BINDING_INDEX] - 6, prefix, i0,
|
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 6, prefix, i0, i1,
|
||||||
i1, i2, i3, i4, suffix);
|
i2, i3, i4, suffix);
|
||||||
}
|
}
|
||||||
return ɵɵpropertyInterpolate6;
|
return ɵɵpropertyInterpolate6;
|
||||||
}
|
}
|
||||||
|
@ -397,8 +397,8 @@ export function ɵɵpropertyInterpolate7(
|
||||||
const nodeIndex = getSelectedIndex();
|
const nodeIndex = getSelectedIndex();
|
||||||
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
||||||
ngDevMode && storePropertyBindingMetadata(
|
ngDevMode && storePropertyBindingMetadata(
|
||||||
lView[TVIEW].data, nodeIndex, propName, lView[BINDING_INDEX] - 7, prefix, i0,
|
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 7, prefix, i0, i1,
|
||||||
i1, i2, i3, i4, i5, suffix);
|
i2, i3, i4, i5, suffix);
|
||||||
}
|
}
|
||||||
return ɵɵpropertyInterpolate7;
|
return ɵɵpropertyInterpolate7;
|
||||||
}
|
}
|
||||||
|
@ -457,8 +457,8 @@ export function ɵɵpropertyInterpolate8(
|
||||||
const nodeIndex = getSelectedIndex();
|
const nodeIndex = getSelectedIndex();
|
||||||
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
elementPropertyInternal(lView, nodeIndex, propName, interpolatedValue, sanitizer);
|
||||||
ngDevMode && storePropertyBindingMetadata(
|
ngDevMode && storePropertyBindingMetadata(
|
||||||
lView[TVIEW].data, nodeIndex, propName, lView[BINDING_INDEX] - 8, prefix, i0,
|
lView[TVIEW].data, nodeIndex, propName, getBindingIndex() - 8, prefix, i0, i1,
|
||||||
i1, i2, i3, i4, i5, i6, suffix);
|
i2, i3, i4, i5, i6, suffix);
|
||||||
}
|
}
|
||||||
return ɵɵpropertyInterpolate8;
|
return ɵɵpropertyInterpolate8;
|
||||||
}
|
}
|
||||||
|
@ -507,7 +507,7 @@ export function ɵɵpropertyInterpolateV(
|
||||||
}
|
}
|
||||||
storePropertyBindingMetadata(
|
storePropertyBindingMetadata(
|
||||||
lView[TVIEW].data, nodeIndex, propName,
|
lView[TVIEW].data, nodeIndex, propName,
|
||||||
lView[BINDING_INDEX] - interpolationInBetween.length + 1, ...interpolationInBetween);
|
getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ɵɵpropertyInterpolateV;
|
return ɵɵpropertyInterpolateV;
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {ErrorHandler} from '../../error_handler';
|
||||||
import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata} from '../../metadata/schema';
|
import {CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA, SchemaMetadata} from '../../metadata/schema';
|
||||||
import {validateAgainstEventAttributes, validateAgainstEventProperties} from '../../sanitization/sanitization';
|
import {validateAgainstEventAttributes, validateAgainstEventProperties} from '../../sanitization/sanitization';
|
||||||
import {Sanitizer} from '../../sanitization/sanitizer';
|
import {Sanitizer} from '../../sanitization/sanitizer';
|
||||||
import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertNotEqual, assertNotSame} from '../../util/assert';
|
import {assertDataInRange, assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertLessThanOrEqual, assertNotEqual, assertNotSame} from '../../util/assert';
|
||||||
import {createNamedArrayType} from '../../util/named_array_type';
|
import {createNamedArrayType} from '../../util/named_array_type';
|
||||||
import {initNgDevMode} from '../../util/ng_dev_mode';
|
import {initNgDevMode} from '../../util/ng_dev_mode';
|
||||||
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
|
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
|
||||||
|
@ -27,10 +27,10 @@ import {AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, Pro
|
||||||
import {RComment, RElement, RText, Renderer3, RendererFactory3, isProceduralRenderer} from '../interfaces/renderer';
|
import {RComment, RElement, RText, Renderer3, RendererFactory3, isProceduralRenderer} from '../interfaces/renderer';
|
||||||
import {SanitizerFn} from '../interfaces/sanitization';
|
import {SanitizerFn} from '../interfaces/sanitization';
|
||||||
import {isComponentDef, isComponentHost, isContentQueryHost, isLContainer, isRootView} from '../interfaces/type_checks';
|
import {isComponentDef, isComponentHost, isContentQueryHost, isLContainer, isRootView} from '../interfaces/type_checks';
|
||||||
import {BINDING_INDEX, CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TVIEW, TView, T_HOST} from '../interfaces/view';
|
import {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_VIEW, ExpandoInstructions, FLAGS, HEADER_OFFSET, HOST, INJECTOR, InitPhaseState, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TVIEW, TView, T_HOST} from '../interfaces/view';
|
||||||
import {assertNodeOfPossibleTypes} from '../node_assert';
|
import {assertNodeOfPossibleTypes} from '../node_assert';
|
||||||
import {isNodeMatchingSelectorList} from '../node_selector_matcher';
|
import {isNodeMatchingSelectorList} from '../node_selector_matcher';
|
||||||
import {ActiveElementFlags, enterView, executeElementExitFn, getBindingsEnabled, getCheckNoChangesMode, getIsParent, getPreviousOrParentTNode, getSelectedIndex, hasActiveElementFlag, incrementActiveDirectiveId, leaveView, leaveViewProcessExit, setActiveHostElement, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setCurrentQueryIndex, setPreviousOrParentTNode, setSelectedIndex} from '../state';
|
import {ActiveElementFlags, enterView, executeElementExitFn, getBindingIndex, getBindingsEnabled, getCheckNoChangesMode, getIsParent, getPreviousOrParentTNode, getSelectedIndex, hasActiveElementFlag, incrementActiveDirectiveId, leaveView, leaveViewProcessExit, setActiveHostElement, setBindingIndex, setBindingRoot, setCheckNoChangesMode, setCurrentDirectiveDef, setCurrentQueryIndex, setPreviousOrParentTNode, setSelectedIndex} from '../state';
|
||||||
import {renderStylingMap, writeStylingValueDirectly} from '../styling/bindings';
|
import {renderStylingMap, writeStylingValueDirectly} from '../styling/bindings';
|
||||||
import {NO_CHANGE} from '../tokens';
|
import {NO_CHANGE} from '../tokens';
|
||||||
import {isAnimationProp} from '../util/attrs_utils';
|
import {isAnimationProp} from '../util/attrs_utils';
|
||||||
|
@ -51,11 +51,11 @@ import {LCleanup, LViewBlueprint, MatchesArray, TCleanup, TNodeConstructor, TNod
|
||||||
const _CLEAN_PROMISE = (() => Promise.resolve(null))();
|
const _CLEAN_PROMISE = (() => Promise.resolve(null))();
|
||||||
|
|
||||||
/** Sets the host bindings for the current view. */
|
/** Sets the host bindings for the current view. */
|
||||||
export function setHostBindings(tView: TView, viewData: LView): void {
|
export function setHostBindings(tView: TView, lView: LView): void {
|
||||||
const selectedIndex = getSelectedIndex();
|
const selectedIndex = getSelectedIndex();
|
||||||
try {
|
try {
|
||||||
if (tView.expandoInstructions !== null) {
|
if (tView.expandoInstructions !== null) {
|
||||||
let bindingRootIndex = viewData[BINDING_INDEX] = tView.expandoStartIndex;
|
let bindingRootIndex = setBindingIndex(tView.expandoStartIndex);
|
||||||
setBindingRoot(bindingRootIndex);
|
setBindingRoot(bindingRootIndex);
|
||||||
let currentDirectiveIndex = -1;
|
let currentDirectiveIndex = -1;
|
||||||
let currentElementIndex = -1;
|
let currentElementIndex = -1;
|
||||||
|
@ -92,8 +92,8 @@ export function setHostBindings(tView: TView, viewData: LView): void {
|
||||||
// are run because this way the first directive ID value is not zero.
|
// are run because this way the first directive ID value is not zero.
|
||||||
incrementActiveDirectiveId();
|
incrementActiveDirectiveId();
|
||||||
|
|
||||||
viewData[BINDING_INDEX] = bindingRootIndex;
|
setBindingIndex(bindingRootIndex);
|
||||||
const hostCtx = unwrapRNode(viewData[currentDirectiveIndex]);
|
const hostCtx = unwrapRNode(lView[currentDirectiveIndex]);
|
||||||
instruction(RenderFlags.Update, hostCtx, currentElementIndex);
|
instruction(RenderFlags.Update, hostCtx, currentElementIndex);
|
||||||
}
|
}
|
||||||
currentDirectiveIndex++;
|
currentDirectiveIndex++;
|
||||||
|
@ -378,7 +378,7 @@ export function refreshView<T>(
|
||||||
try {
|
try {
|
||||||
resetPreOrderHookFlags(lView);
|
resetPreOrderHookFlags(lView);
|
||||||
|
|
||||||
setBindingRoot(lView[BINDING_INDEX] = tView.bindingStartIndex);
|
setBindingIndex(tView.bindingStartIndex);
|
||||||
if (templateFn !== null) {
|
if (templateFn !== null) {
|
||||||
executeTemplate(lView, templateFn, RenderFlags.Update, context);
|
executeTemplate(lView, templateFn, RenderFlags.Update, context);
|
||||||
}
|
}
|
||||||
|
@ -666,7 +666,6 @@ function createViewBlueprint(bindingStartIndex: number, initialViewLength: numbe
|
||||||
for (let i = 0; i < initialViewLength; i++) {
|
for (let i = 0; i < initialViewLength; i++) {
|
||||||
blueprint.push(i < bindingStartIndex ? null : NO_CHANGE);
|
blueprint.push(i < bindingStartIndex ? null : NO_CHANGE);
|
||||||
}
|
}
|
||||||
blueprint[BINDING_INDEX] = bindingStartIndex;
|
|
||||||
|
|
||||||
return blueprint as LView;
|
return blueprint as LView;
|
||||||
}
|
}
|
||||||
|
@ -1191,8 +1190,8 @@ function postProcessDirective<T>(
|
||||||
* A lighter version of postProcessDirective() that is used for the root component.
|
* A lighter version of postProcessDirective() that is used for the root component.
|
||||||
*/
|
*/
|
||||||
function postProcessBaseDirective<T>(lView: LView, hostTNode: TNode, directive: T): void {
|
function postProcessBaseDirective<T>(lView: LView, hostTNode: TNode, directive: T): void {
|
||||||
ngDevMode && assertEqual(
|
ngDevMode && assertLessThanOrEqual(
|
||||||
lView[BINDING_INDEX], lView[TVIEW].bindingStartIndex,
|
getBindingIndex(), lView[TVIEW].bindingStartIndex,
|
||||||
'directives should be created before any bindings');
|
'directives should be created before any bindings');
|
||||||
attachPatchData(directive, lView);
|
attachPatchData(directive, lView);
|
||||||
const native = getNativeByTNode(hostTNode, lView);
|
const native = getNativeByTNode(hostTNode, lView);
|
||||||
|
|
|
@ -13,8 +13,8 @@ import {AttributeMarker, TAttributes, TNode, TNodeFlags, TNodeType} from '../int
|
||||||
import {RElement} from '../interfaces/renderer';
|
import {RElement} from '../interfaces/renderer';
|
||||||
import {StylingMapArray, StylingMapArrayIndex, TStylingConfig, TStylingContext} from '../interfaces/styling';
|
import {StylingMapArray, StylingMapArrayIndex, TStylingConfig, TStylingContext} from '../interfaces/styling';
|
||||||
import {isDirectiveHost} from '../interfaces/type_checks';
|
import {isDirectiveHost} from '../interfaces/type_checks';
|
||||||
import {BINDING_INDEX, LView, RENDERER} from '../interfaces/view';
|
import {LView, RENDERER} from '../interfaces/view';
|
||||||
import {getActiveDirectiveId, getCheckNoChangesMode, getCurrentStyleSanitizer, getLView, getSelectedIndex, resetCurrentStyleSanitizer, setCurrentStyleSanitizer, setElementExitFn} from '../state';
|
import {getActiveDirectiveId, getCheckNoChangesMode, getCurrentStyleSanitizer, getLView, getSelectedIndex, incrementBindingIndex, nextBindingIndex, resetCurrentStyleSanitizer, setCurrentStyleSanitizer, setElementExitFn} from '../state';
|
||||||
import {applyStylingMapDirectly, applyStylingValueDirectly, flushStyling, setClass, setStyle, updateClassViaContext, updateStyleViaContext} from '../styling/bindings';
|
import {applyStylingMapDirectly, applyStylingValueDirectly, flushStyling, setClass, setStyle, updateClassViaContext, updateStyleViaContext} from '../styling/bindings';
|
||||||
import {activateStylingMapFeature} from '../styling/map_based_bindings';
|
import {activateStylingMapFeature} from '../styling/map_based_bindings';
|
||||||
import {attachStylingDebugObject} from '../styling/styling_debug';
|
import {attachStylingDebugObject} from '../styling/styling_debug';
|
||||||
|
@ -90,13 +90,11 @@ export function ɵɵstyleProp(
|
||||||
export function stylePropInternal(
|
export function stylePropInternal(
|
||||||
elementIndex: number, prop: string, value: string | number | SafeValue | null,
|
elementIndex: number, prop: string, value: string | number | SafeValue | null,
|
||||||
suffix?: string | null | undefined): void {
|
suffix?: string | null | undefined): void {
|
||||||
const lView = getLView();
|
|
||||||
|
|
||||||
// if a value is interpolated then it may render a `NO_CHANGE` value.
|
// if a value is interpolated then it may render a `NO_CHANGE` value.
|
||||||
// in this case we do not need to do anything, but the binding index
|
// in this case we do not need to do anything, but the binding index
|
||||||
// still needs to be incremented because all styling binding values
|
// still needs to be incremented because all styling binding values
|
||||||
// are stored inside of the lView.
|
// are stored inside of the lView.
|
||||||
const bindingIndex = getAndIncrementBindingIndex(lView, false);
|
const bindingIndex = nextBindingIndex();
|
||||||
|
|
||||||
const updated =
|
const updated =
|
||||||
stylingProp(elementIndex, bindingIndex, prop, resolveStylePropValue(value, suffix), false);
|
stylingProp(elementIndex, bindingIndex, prop, resolveStylePropValue(value, suffix), false);
|
||||||
|
@ -124,13 +122,11 @@ export function stylePropInternal(
|
||||||
* @codeGenApi
|
* @codeGenApi
|
||||||
*/
|
*/
|
||||||
export function ɵɵclassProp(className: string, value: boolean | null): void {
|
export function ɵɵclassProp(className: string, value: boolean | null): void {
|
||||||
const lView = getLView();
|
|
||||||
|
|
||||||
// if a value is interpolated then it may render a `NO_CHANGE` value.
|
// if a value is interpolated then it may render a `NO_CHANGE` value.
|
||||||
// in this case we do not need to do anything, but the binding index
|
// in this case we do not need to do anything, but the binding index
|
||||||
// still needs to be incremented because all styling binding values
|
// still needs to be incremented because all styling binding values
|
||||||
// are stored inside of the lView.
|
// are stored inside of the lView.
|
||||||
const bindingIndex = getAndIncrementBindingIndex(lView, false);
|
const bindingIndex = nextBindingIndex();
|
||||||
|
|
||||||
const updated = stylingProp(getSelectedIndex(), bindingIndex, className, value, true);
|
const updated = stylingProp(getSelectedIndex(), bindingIndex, className, value, true);
|
||||||
if (ngDevMode) {
|
if (ngDevMode) {
|
||||||
|
@ -248,7 +244,7 @@ export function ɵɵstyleMap(styles: {[styleName: string]: any} | NO_CHANGE | nu
|
||||||
// in this case we do not need to do anything, but the binding index
|
// in this case we do not need to do anything, but the binding index
|
||||||
// still needs to be incremented because all styling binding values
|
// still needs to be incremented because all styling binding values
|
||||||
// are stored inside of the lView.
|
// are stored inside of the lView.
|
||||||
const bindingIndex = getAndIncrementBindingIndex(lView, true);
|
const bindingIndex = incrementBindingIndex(2);
|
||||||
|
|
||||||
// inputs are only evaluated from a template binding into a directive, therefore,
|
// inputs are only evaluated from a template binding into a directive, therefore,
|
||||||
// there should not be a situation where a directive host bindings function
|
// there should not be a situation where a directive host bindings function
|
||||||
|
@ -300,7 +296,7 @@ export function classMapInternal(
|
||||||
// in this case we do not need to do anything, but the binding index
|
// in this case we do not need to do anything, but the binding index
|
||||||
// still needs to be incremented because all styling binding values
|
// still needs to be incremented because all styling binding values
|
||||||
// are stored inside of the lView.
|
// are stored inside of the lView.
|
||||||
const bindingIndex = getAndIncrementBindingIndex(lView, true);
|
const bindingIndex = incrementBindingIndex(2);
|
||||||
|
|
||||||
// inputs are only evaluated from a template binding into a directive, therefore,
|
// inputs are only evaluated from a template binding into a directive, therefore,
|
||||||
// there should not be a situation where a directive host bindings function
|
// there should not be a situation where a directive host bindings function
|
||||||
|
@ -582,11 +578,3 @@ function resolveStylePropValue(
|
||||||
function isHostStyling(): boolean {
|
function isHostStyling(): boolean {
|
||||||
return isHostStylingActive(getActiveDirectiveId());
|
return isHostStylingActive(getActiveDirectiveId());
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAndIncrementBindingIndex(lView: LView, isMapBased: boolean): number {
|
|
||||||
// map-based bindings use two slots because the previously constructed
|
|
||||||
// className / style value must be compared against.
|
|
||||||
const index = lView[BINDING_INDEX];
|
|
||||||
lView[BINDING_INDEX] += isMapBased ? 2 : 1;
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,9 +7,10 @@
|
||||||
*/
|
*/
|
||||||
import {assertDataInRange, assertEqual} from '../../util/assert';
|
import {assertDataInRange, assertEqual} from '../../util/assert';
|
||||||
import {TNodeType} from '../interfaces/node';
|
import {TNodeType} from '../interfaces/node';
|
||||||
import {BINDING_INDEX, HEADER_OFFSET, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
|
import {HEADER_OFFSET, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
|
||||||
import {appendChild, createTextNode} from '../node_manipulation';
|
import {appendChild, createTextNode} from '../node_manipulation';
|
||||||
import {getLView, setIsNotParent} from '../state';
|
import {getBindingIndex, getLView, setIsNotParent} from '../state';
|
||||||
|
|
||||||
import {getOrCreateTNode} from './shared';
|
import {getOrCreateTNode} from './shared';
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ import {getOrCreateTNode} from './shared';
|
||||||
export function ɵɵtext(index: number, value: string = ''): void {
|
export function ɵɵtext(index: number, value: string = ''): void {
|
||||||
const lView = getLView();
|
const lView = getLView();
|
||||||
ngDevMode && assertEqual(
|
ngDevMode && assertEqual(
|
||||||
lView[BINDING_INDEX], lView[TVIEW].bindingStartIndex,
|
getBindingIndex(), lView[TVIEW].bindingStartIndex,
|
||||||
'text nodes should be created before any bindings');
|
'text nodes should be created before any bindings');
|
||||||
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
|
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
|
||||||
const textNative = lView[index + HEADER_OFFSET] = createTextNode(value, lView[RENDERER]);
|
const textNative = lView[index + HEADER_OFFSET] = createTextNode(value, lView[RENDERER]);
|
||||||
|
|
|
@ -32,20 +32,19 @@ export const PARENT = 3;
|
||||||
export const NEXT = 4;
|
export const NEXT = 4;
|
||||||
export const QUERIES = 5;
|
export const QUERIES = 5;
|
||||||
export const T_HOST = 6;
|
export const T_HOST = 6;
|
||||||
export const BINDING_INDEX = 7;
|
export const CLEANUP = 7;
|
||||||
export const CLEANUP = 8;
|
export const CONTEXT = 8;
|
||||||
export const CONTEXT = 9;
|
export const INJECTOR = 9;
|
||||||
export const INJECTOR = 10;
|
export const RENDERER_FACTORY = 10;
|
||||||
export const RENDERER_FACTORY = 11;
|
export const RENDERER = 11;
|
||||||
export const RENDERER = 12;
|
export const SANITIZER = 12;
|
||||||
export const SANITIZER = 13;
|
export const CHILD_HEAD = 13;
|
||||||
export const CHILD_HEAD = 14;
|
export const CHILD_TAIL = 14;
|
||||||
export const CHILD_TAIL = 15;
|
export const DECLARATION_VIEW = 15;
|
||||||
export const DECLARATION_VIEW = 16;
|
export const DECLARATION_LCONTAINER = 16;
|
||||||
export const DECLARATION_LCONTAINER = 17;
|
export const PREORDER_HOOK_FLAGS = 17;
|
||||||
export const PREORDER_HOOK_FLAGS = 18;
|
|
||||||
/** Size of LView's header. Necessary to adjust for it when setting slots. */
|
/** Size of LView's header. Necessary to adjust for it when setting slots. */
|
||||||
export const HEADER_OFFSET = 19;
|
export const HEADER_OFFSET = 18;
|
||||||
|
|
||||||
|
|
||||||
// This interface replaces the real LView interface if it is an arg or a
|
// This interface replaces the real LView interface if it is an arg or a
|
||||||
|
@ -120,15 +119,6 @@ export interface LView extends Array<any> {
|
||||||
*/
|
*/
|
||||||
[T_HOST]: TViewNode|TElementNode|null;
|
[T_HOST]: TViewNode|TElementNode|null;
|
||||||
|
|
||||||
/**
|
|
||||||
* The binding index we should access next.
|
|
||||||
*
|
|
||||||
* This is stored so that bindings can continue where they left off
|
|
||||||
* if a view is left midway through processing bindings (e.g. if there is
|
|
||||||
* a setter that creates an embedded view, like in ngIf).
|
|
||||||
*/
|
|
||||||
[BINDING_INDEX]: number;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a view is destroyed, listeners need to be released and outputs need to be
|
* When a view is destroyed, listeners need to be released and outputs need to be
|
||||||
* unsubscribed. This context array stores both listener functions wrapped with
|
* unsubscribed. This context array stores both listener functions wrapped with
|
||||||
|
@ -381,6 +371,8 @@ export interface TView {
|
||||||
* starts to store bindings only. Saving this value ensures that we
|
* starts to store bindings only. Saving this value ensures that we
|
||||||
* will begin reading bindings at the correct point in the array when
|
* will begin reading bindings at the correct point in the array when
|
||||||
* we are in update mode.
|
* we are in update mode.
|
||||||
|
*
|
||||||
|
* -1 means that it has not been initialized.
|
||||||
*/
|
*/
|
||||||
bindingStartIndex: number;
|
bindingStartIndex: number;
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ import {PipeTransform} from '../change_detection/pipe_transform';
|
||||||
import {getFactoryDef} from './definition';
|
import {getFactoryDef} from './definition';
|
||||||
import {store} from './instructions/all';
|
import {store} from './instructions/all';
|
||||||
import {PipeDef, PipeDefList} from './interfaces/definition';
|
import {PipeDef, PipeDefList} from './interfaces/definition';
|
||||||
import {BINDING_INDEX, HEADER_OFFSET, LView, TVIEW} from './interfaces/view';
|
import {HEADER_OFFSET, LView, TVIEW} from './interfaces/view';
|
||||||
import {ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunctionV} from './pure_function';
|
import {ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunctionV} from './pure_function';
|
||||||
import {getLView} from './state';
|
import {getBindingIndex, getLView} from './state';
|
||||||
import {NO_CHANGE} from './tokens';
|
import {NO_CHANGE} from './tokens';
|
||||||
import {load} from './util/view_utils';
|
import {load} from './util/view_utils';
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ function unwrapValue(lView: LView, newValue: any): any {
|
||||||
newValue = WrappedValue.unwrap(newValue);
|
newValue = WrappedValue.unwrap(newValue);
|
||||||
// The NO_CHANGE value needs to be written at the index where the impacted binding value is
|
// The NO_CHANGE value needs to be written at the index where the impacted binding value is
|
||||||
// stored
|
// stored
|
||||||
const bindingToInvalidateIdx = lView[BINDING_INDEX];
|
const bindingToInvalidateIdx = getBindingIndex();
|
||||||
lView[bindingToInvalidateIdx] = NO_CHANGE;
|
lView[bindingToInvalidateIdx] = NO_CHANGE;
|
||||||
}
|
}
|
||||||
return newValue;
|
return newValue;
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {assertDefined, assertEqual} from '../util/assert';
|
||||||
import {assertLViewOrUndefined} from './assert';
|
import {assertLViewOrUndefined} from './assert';
|
||||||
import {ComponentDef, DirectiveDef} from './interfaces/definition';
|
import {ComponentDef, DirectiveDef} from './interfaces/definition';
|
||||||
import {TNode} from './interfaces/node';
|
import {TNode} from './interfaces/node';
|
||||||
import {BINDING_INDEX, CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState, TVIEW} from './interfaces/view';
|
import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState, TVIEW} from './interfaces/view';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,6 +62,11 @@ interface LFrame {
|
||||||
*/
|
*/
|
||||||
selectedIndex: number;
|
selectedIndex: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current pointer to the binding index.
|
||||||
|
*/
|
||||||
|
bindingIndex: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last viewData retrieved by nextContext().
|
* The last viewData retrieved by nextContext().
|
||||||
* Allows building nextContext() and reference() calls.
|
* Allows building nextContext() and reference() calls.
|
||||||
|
@ -433,11 +438,38 @@ export function getBindingRoot() {
|
||||||
let index = lFrame.bindingRootIndex;
|
let index = lFrame.bindingRootIndex;
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
const lView = lFrame.lView;
|
const lView = lFrame.lView;
|
||||||
index = lFrame.bindingRootIndex = lView[BINDING_INDEX] = lView[TVIEW].bindingStartIndex;
|
index = lFrame.bindingRootIndex = lView[TVIEW].bindingStartIndex;
|
||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getBindingIndex(): number {
|
||||||
|
return instructionState.lFrame.bindingIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setBindingIndex(value: number): number {
|
||||||
|
return instructionState.lFrame.bindingIndex = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function nextBindingIndex(): number {
|
||||||
|
return instructionState.lFrame.bindingIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function incrementBindingIndex(count: number): number {
|
||||||
|
const lFrame = instructionState.lFrame;
|
||||||
|
const index = lFrame.bindingIndex;
|
||||||
|
lFrame.bindingIndex = lFrame.bindingIndex + count;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a new binding root index so that host template functions can execute.
|
||||||
|
*
|
||||||
|
* Bindings inside the host template are 0 index. But because we don't know ahead of time
|
||||||
|
* how many host bindings we have we can't pre-compute them. For this reason they are all
|
||||||
|
* 0 index and we just shift the root so that they match next available location in the LView.
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
export function setBindingRoot(value: number) {
|
export function setBindingRoot(value: number) {
|
||||||
instructionState.lFrame.bindingRootIndex = value;
|
instructionState.lFrame.bindingRootIndex = value;
|
||||||
}
|
}
|
||||||
|
@ -513,6 +545,7 @@ export function enterView(newView: LView, tNode: TNode | null): void {
|
||||||
newLFrame.currentDirectiveDef = null;
|
newLFrame.currentDirectiveDef = null;
|
||||||
newLFrame.activeDirectiveId = 0;
|
newLFrame.activeDirectiveId = 0;
|
||||||
newLFrame.bindingRootIndex = -1;
|
newLFrame.bindingRootIndex = -1;
|
||||||
|
newLFrame.bindingIndex = newView === null ? -1 : newView[TVIEW].bindingStartIndex;
|
||||||
newLFrame.currentQueryIndex = 0;
|
newLFrame.currentQueryIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,6 +572,7 @@ function createLFrame(parent: LFrame | null): LFrame {
|
||||||
currentDirectiveDef: null, //
|
currentDirectiveDef: null, //
|
||||||
activeDirectiveId: 0, //
|
activeDirectiveId: 0, //
|
||||||
bindingRootIndex: -1, //
|
bindingRootIndex: -1, //
|
||||||
|
bindingIndex: -1, //
|
||||||
currentQueryIndex: 0, //
|
currentQueryIndex: 0, //
|
||||||
parent: parent !, //
|
parent: parent !, //
|
||||||
child: null, //
|
child: null, //
|
||||||
|
|
|
@ -48,6 +48,12 @@ export function assertLessThan<T>(actual: T, expected: T, msg: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function assertLessThanOrEqual<T>(actual: T, expected: T, msg: string) {
|
||||||
|
if (actual > expected) {
|
||||||
|
throwError(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function assertGreaterThan<T>(actual: T, expected: T, msg: string) {
|
export function assertGreaterThan<T>(actual: T, expected: T, msg: string) {
|
||||||
if (actual <= expected) {
|
if (actual <= expected) {
|
||||||
throwError(msg);
|
throwError(msg);
|
||||||
|
|
|
@ -127,6 +127,53 @@ describe('change detection', () => {
|
||||||
fixture.detectChanges(false);
|
fixture.detectChanges(false);
|
||||||
expect(fixture.nativeElement).toHaveText('1|dynamic');
|
expect(fixture.nativeElement).toHaveText('1|dynamic');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support re-enterant change detection', () => {
|
||||||
|
@Component({
|
||||||
|
selector: 'has-host-binding',
|
||||||
|
template: '..',
|
||||||
|
host: {
|
||||||
|
'[class.x]': 'x',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
class HasHostBinding {
|
||||||
|
x = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'child',
|
||||||
|
template: '<has-host-binding></has-host-binding>',
|
||||||
|
inputs: ['input'],
|
||||||
|
})
|
||||||
|
class Child {
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
private _input !: number;
|
||||||
|
|
||||||
|
constructor(private cdr: ChangeDetectorRef) {}
|
||||||
|
|
||||||
|
get input() { return this._input; }
|
||||||
|
|
||||||
|
set input(value: number) {
|
||||||
|
this._input = value;
|
||||||
|
this.cdr.detectChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'root',
|
||||||
|
template: '<child [input]="3"></child>',
|
||||||
|
})
|
||||||
|
class Root {
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [Root, Child, HasHostBinding],
|
||||||
|
});
|
||||||
|
|
||||||
|
TestBed.createComponent(Root).detectChanges();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('OnPush', () => {
|
describe('OnPush', () => {
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
{
|
{
|
||||||
"name": "ACTIVE_INDEX"
|
"name": "ACTIVE_INDEX"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "BINDING_INDEX"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "BLOOM_MASK"
|
"name": "BLOOM_MASK"
|
||||||
},
|
},
|
||||||
|
@ -608,6 +605,9 @@
|
||||||
{
|
{
|
||||||
"name": "setActiveHostElement"
|
"name": "setActiveHostElement"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "setBindingIndex"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "setBindingRoot"
|
"name": "setBindingRoot"
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
{
|
{
|
||||||
"name": "ACTIVE_INDEX"
|
"name": "ACTIVE_INDEX"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "BINDING_INDEX"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "BLOOM_MASK"
|
"name": "BLOOM_MASK"
|
||||||
},
|
},
|
||||||
|
@ -437,6 +434,9 @@
|
||||||
{
|
{
|
||||||
"name": "setActiveHostElement"
|
"name": "setActiveHostElement"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "setBindingIndex"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "setBindingRoot"
|
"name": "setBindingRoot"
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
{
|
{
|
||||||
"name": "ACTIVE_INDEX"
|
"name": "ACTIVE_INDEX"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "BINDING_INDEX"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "BIT_MASK_START_VALUE"
|
"name": "BIT_MASK_START_VALUE"
|
||||||
},
|
},
|
||||||
|
@ -611,9 +608,6 @@
|
||||||
{
|
{
|
||||||
"name": "getActiveDirectiveId"
|
"name": "getActiveDirectiveId"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "getAndIncrementBindingIndex"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "getBeforeNodeForView"
|
"name": "getBeforeNodeForView"
|
||||||
},
|
},
|
||||||
|
@ -1073,6 +1067,9 @@
|
||||||
{
|
{
|
||||||
"name": "nativeRemoveNode"
|
"name": "nativeRemoveNode"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "nextBindingIndex"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "nextContextImpl"
|
"name": "nextContextImpl"
|
||||||
},
|
},
|
||||||
|
@ -1208,6 +1205,9 @@
|
||||||
{
|
{
|
||||||
"name": "setActiveHostElement"
|
"name": "setActiveHostElement"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "setBindingIndex"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "setBindingRoot"
|
"name": "setBindingRoot"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue