refactor(ivy): remove reserveSlots instruction (#25533)

PR Close #25533
This commit is contained in:
Kara Erickson
2018-08-15 16:32:08 -07:00
committed by Jason Aden
parent 21d22ce4ad
commit 4708cb91ef
8 changed files with 281 additions and 295 deletions

View File

@ -7,7 +7,7 @@
*/
import {assertEqual, assertLessThan} from './assert';
import {NO_CHANGE, _getViewData, bindingUpdated, bindingUpdated2, bindingUpdated4, createLNode, getPreviousOrParentNode, getRenderer, load, resetApplicationState} from './instructions';
import {NO_CHANGE, _getViewData, bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4, createLNode, getPreviousOrParentNode, getRenderer, initBindings, load, resetApplicationState} from './instructions';
import {RENDER_PARENT} from './interfaces/container';
import {LContainerNode, LNode, TContainerNode, TElementNode, TNodeType} from './interfaces/node';
import {BINDING_INDEX, HEADER_OFFSET, TVIEW} from './interfaces/view';
@ -383,7 +383,8 @@ export function i18nExpMapping(
* @returns The concatenated string when any of the arguments changes, `NO_CHANGE` otherwise.
*/
export function i18nInterpolation1(instructions: I18nExpInstruction[], v0: any): string|NO_CHANGE {
const different = bindingUpdated(v0);
initBindings();
const different = bindingUpdated(_getViewData()[BINDING_INDEX]++, v0);
if (!different) {
return NO_CHANGE;
@ -414,7 +415,10 @@ export function i18nInterpolation1(instructions: I18nExpInstruction[], v0: any):
*/
export function i18nInterpolation2(instructions: I18nExpInstruction[], v0: any, v1: any): string|
NO_CHANGE {
const different = bindingUpdated2(v0, v1);
initBindings();
const viewData = _getViewData();
const different = bindingUpdated2(viewData[BINDING_INDEX], v0, v1);
viewData[BINDING_INDEX] += 2;
if (!different) {
return NO_CHANGE;
@ -452,8 +456,10 @@ export function i18nInterpolation2(instructions: I18nExpInstruction[], v0: any,
*/
export function i18nInterpolation3(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any): string|NO_CHANGE {
let different = bindingUpdated2(v0, v1);
different = bindingUpdated(v2) || different;
initBindings();
const viewData = _getViewData();
const different = bindingUpdated3(viewData[BINDING_INDEX], v0, v1, v2);
viewData[BINDING_INDEX] += 3;
if (!different) {
return NO_CHANGE;
@ -493,7 +499,10 @@ export function i18nInterpolation3(
*/
export function i18nInterpolation4(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any): string|NO_CHANGE {
const different = bindingUpdated4(v0, v1, v2, v3);
initBindings();
const viewData = _getViewData();
const different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
viewData[BINDING_INDEX] += 4;
if (!different) {
return NO_CHANGE;
@ -535,8 +544,11 @@ export function i18nInterpolation4(
export function i18nInterpolation5(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any): string|
NO_CHANGE {
let different = bindingUpdated4(v0, v1, v2, v3);
different = bindingUpdated(v4) || different;
initBindings();
const viewData = _getViewData();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated(viewData[BINDING_INDEX] + 4, v4) || different;
viewData[BINDING_INDEX] += 5;
if (!different) {
return NO_CHANGE;
@ -580,8 +592,11 @@ export function i18nInterpolation5(
i18nInterpolation6(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any, v5: any):
string|NO_CHANGE {
let different = bindingUpdated4(v0, v1, v2, v3);
different = bindingUpdated2(v4, v5) || different;
initBindings();
const viewData = _getViewData();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated2(viewData[BINDING_INDEX] + 4, v4, v5) || different;
viewData[BINDING_INDEX] += 6;
if (!different) {
return NO_CHANGE;
@ -626,9 +641,11 @@ i18nInterpolation6(
export function i18nInterpolation7(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any, v5: any,
v6: any): string|NO_CHANGE {
let different = bindingUpdated4(v0, v1, v2, v3);
different = bindingUpdated2(v4, v5) || different;
different = bindingUpdated(v6) || different;
initBindings();
const viewData = _getViewData();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated3(viewData[BINDING_INDEX] + 4, v4, v5, v6) || different;
viewData[BINDING_INDEX] += 7;
if (!different) {
return NO_CHANGE;
@ -674,8 +691,11 @@ export function i18nInterpolation7(
export function i18nInterpolation8(
instructions: I18nExpInstruction[], v0: any, v1: any, v2: any, v3: any, v4: any, v5: any,
v6: any, v7: any): string|NO_CHANGE {
let different = bindingUpdated4(v0, v1, v2, v3);
different = bindingUpdated4(v4, v5, v6, v7) || different;
initBindings();
const viewData = _getViewData();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated4(viewData[BINDING_INDEX] + 4, v4, v5, v6, v7) || different;
viewData[BINDING_INDEX] += 8;
if (!different) {
return NO_CHANGE;
@ -713,10 +733,12 @@ export function i18nInterpolation8(
*/
export function i18nInterpolationV(instructions: I18nExpInstruction[], values: any[]): string|
NO_CHANGE {
initBindings();
const viewData = _getViewData();
let different = false;
for (let i = 0; i < values.length; i++) {
// Check if bindings have changed
bindingUpdated(values[i]) && (different = true);
bindingUpdated(viewData[BINDING_INDEX]++, values[i]) && (different = true);
}
if (!different) {

View File

@ -369,6 +369,7 @@ export function executeInitAndContentHooks(): void {
export function createLViewData<T>(
renderer: Renderer3, tView: TView, context: T | null, flags: LViewFlags,
sanitizer?: Sanitizer | null): LViewData {
// TODO(kara): create from blueprint
return [
tView, // tView
viewData, // parent
@ -2506,14 +2507,14 @@ export const NO_CHANGE = {} as NO_CHANGE;
* This function must be called before any binding related function is called
* (ie `bind()`, `interpolationX()`, `pureFunctionX()`)
*/
function initBindings() {
ngDevMode && assertEqual(
viewData[BINDING_INDEX], -1,
'Binding index should not yet be set ' + viewData[BINDING_INDEX]);
export function initBindings() {
// TODO(kara): remove this check when we have pre-filled array
if (tView.bindingStartIndex === -1) {
tView.bindingStartIndex = viewData.length;
}
viewData[BINDING_INDEX] = tView.bindingStartIndex;
if (viewData[BINDING_INDEX] === -1) {
viewData[BINDING_INDEX] = tView.bindingStartIndex;
}
}
/**
@ -2522,26 +2523,11 @@ function initBindings() {
* @param value Value to diff
*/
export function bind<T>(value: T): T|NO_CHANGE {
return bindingUpdated(value) ? value : NO_CHANGE;
initBindings();
return bindingUpdated(viewData[BINDING_INDEX]++, value) ? value : NO_CHANGE;
}
/**
* Reserves slots for pure functions (`pureFunctionX` instructions)
*
* Bindings for pure functions are stored after the LNodes in the data array but before the binding.
*
* ----------------------------------------------------------------------------
* | LNodes ... | pure function bindings | regular bindings / interpolations |
* ----------------------------------------------------------------------------
* ^
* TView.bindingStartIndex
*
* Pure function instructions are given an offset from TView.bindingStartIndex.
* Subtracting the offset from TView.bindingStartIndex gives the first index where the bindings
* are stored.
*
* NOTE: reserveSlots instructions are only ever allowed at the very end of the creation block
*/
// TODO(kara): Remove this when updating the compiler (cannot remove without breaking JIT test)
export function reserveSlots(numSlots: number) {
// Init the slots with a unique `NO_CHANGE` value so that the first change is always detected
// whether it happens or not during the first change detection pass - pure functions checks
@ -2553,29 +2539,6 @@ export function reserveSlots(numSlots: number) {
initBindings();
}
/**
* Sets up the binding index before executing any `pureFunctionX` instructions.
*
* The index must be restored after the pure function is executed
*
* {@link reserveSlots}
*/
export function moveBindingIndexToReservedSlot(offset: number): number {
const currentSlot = viewData[BINDING_INDEX];
viewData[BINDING_INDEX] = tView.bindingStartIndex - offset;
return currentSlot;
}
/**
* Restores the binding index to the given value.
*
* This function is typically used to restore the index after a `pureFunctionX` has
* been executed.
*/
export function restoreBindingIndex(index: number): void {
viewData[BINDING_INDEX] = index;
}
/**
* Create interpolation bindings with a variable number of expressions.
*
@ -2591,12 +2554,12 @@ export function restoreBindingIndex(index: number): void {
export function interpolationV(values: any[]): string|NO_CHANGE {
ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');
ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values');
initBindings();
let different = false;
for (let i = 1; i < values.length; i += 2) {
// Check if bindings (odd indexes) have changed
bindingUpdated(values[i]) && (different = true);
bindingUpdated(viewData[BINDING_INDEX]++, values[i]) && (different = true);
}
if (!different) {
@ -2620,15 +2583,17 @@ export function interpolationV(values: any[]): string|NO_CHANGE {
* @param suffix static value used for concatenation only.
*/
export function interpolation1(prefix: string, v0: any, suffix: string): string|NO_CHANGE {
const different = bindingUpdated(v0);
initBindings();
const different = bindingUpdated(viewData[BINDING_INDEX]++, v0);
return different ? prefix + stringify(v0) + suffix : NO_CHANGE;
}
/** Creates an interpolation binding with 2 expressions. */
export function interpolation2(
prefix: string, v0: any, i0: string, v1: any, suffix: string): string|NO_CHANGE {
const different = bindingUpdated2(v0, v1);
initBindings();
const different = bindingUpdated2(viewData[BINDING_INDEX], v0, v1);
viewData[BINDING_INDEX] += 2;
return different ? prefix + stringify(v0) + i0 + stringify(v1) + suffix : NO_CHANGE;
}
@ -2637,8 +2602,9 @@ export function interpolation2(
export function interpolation3(
prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, suffix: string): string|
NO_CHANGE {
let different = bindingUpdated2(v0, v1);
different = bindingUpdated(v2) || different;
initBindings();
const different = bindingUpdated3(viewData[BINDING_INDEX], v0, v1, v2);
viewData[BINDING_INDEX] += 3;
return different ? prefix + stringify(v0) + i0 + stringify(v1) + i1 + stringify(v2) + suffix :
NO_CHANGE;
@ -2648,7 +2614,9 @@ export function interpolation3(
export function interpolation4(
prefix: string, v0: any, i0: string, v1: any, i1: string, v2: any, i2: string, v3: any,
suffix: string): string|NO_CHANGE {
const different = bindingUpdated4(v0, v1, v2, v3);
initBindings();
const different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
viewData[BINDING_INDEX] += 4;
return different ?
prefix + stringify(v0) + i0 + stringify(v1) + i1 + stringify(v2) + i2 + stringify(v3) +
@ -2660,8 +2628,10 @@ export function interpolation4(
export function interpolation5(
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 {
let different = bindingUpdated4(v0, v1, v2, v3);
different = bindingUpdated(v4) || different;
initBindings();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated(viewData[BINDING_INDEX] + 4, v4) || different;
viewData[BINDING_INDEX] += 5;
return different ?
prefix + stringify(v0) + i0 + stringify(v1) + i1 + stringify(v2) + i2 + stringify(v3) + i3 +
@ -2673,8 +2643,10 @@ export function interpolation5(
export function interpolation6(
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 {
let different = bindingUpdated4(v0, v1, v2, v3);
different = bindingUpdated2(v4, v5) || different;
initBindings();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated2(viewData[BINDING_INDEX] + 4, v4, v5) || different;
viewData[BINDING_INDEX] += 6;
return different ?
prefix + stringify(v0) + i0 + stringify(v1) + i1 + stringify(v2) + i2 + stringify(v3) + i3 +
@ -2687,9 +2659,10 @@ export function interpolation7(
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|
NO_CHANGE {
let different = bindingUpdated4(v0, v1, v2, v3);
different = bindingUpdated2(v4, v5) || different;
different = bindingUpdated(v6) || different;
initBindings();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated3(viewData[BINDING_INDEX] + 4, v4, v5, v6) || different;
viewData[BINDING_INDEX] += 7;
return different ?
prefix + stringify(v0) + i0 + stringify(v1) + i1 + stringify(v2) + i2 + stringify(v3) + i3 +
@ -2702,8 +2675,10 @@ export function interpolation8(
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,
suffix: string): string|NO_CHANGE {
let different = bindingUpdated4(v0, v1, v2, v3);
different = bindingUpdated4(v4, v5, v6, v7) || different;
initBindings();
let different = bindingUpdated4(viewData[BINDING_INDEX], v0, v1, v2, v3);
different = bindingUpdated4(viewData[BINDING_INDEX] + 4, v4, v5, v6, v7) || different;
viewData[BINDING_INDEX] += 8;
return different ?
prefix + stringify(v0) + i0 + stringify(v1) + i1 + stringify(v2) + i2 + stringify(v3) + i3 +
@ -2770,49 +2745,51 @@ export function loadElement(index: number): LElementNode {
return loadElementInternal(index, viewData);
}
/** Gets the current binding value and increments the binding index. */
export function consumeBinding(): any {
ngDevMode && assertDataInRange(viewData[BINDING_INDEX]);
/** Gets the current binding value. */
export function getBinding(bindingIndex: number): any {
ngDevMode && assertDataInRange(viewData[bindingIndex]);
ngDevMode &&
assertNotEqual(
viewData[viewData[BINDING_INDEX]], NO_CHANGE, 'Stored value should never be NO_CHANGE.');
return viewData[viewData[BINDING_INDEX]++];
assertNotEqual(viewData[bindingIndex], NO_CHANGE, 'Stored value should never be NO_CHANGE.');
return viewData[bindingIndex];
}
/** Updates binding if changed, then returns whether it was updated. */
export function bindingUpdated(value: any): boolean {
export function bindingUpdated(bindingIndex: number, value: any): boolean {
ngDevMode && assertNotEqual(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
if (viewData[BINDING_INDEX] === -1) initBindings();
const bindingIndex = viewData[BINDING_INDEX];
if (bindingIndex >= viewData.length) {
viewData[viewData[BINDING_INDEX]++] = value;
viewData[bindingIndex] = value;
} else if (isDifferent(viewData[bindingIndex], value, checkNoChangesMode)) {
throwErrorIfNoChangesMode(creationMode, checkNoChangesMode, viewData[bindingIndex], value);
viewData[viewData[BINDING_INDEX]++] = value;
viewData[bindingIndex] = value;
} else {
viewData[BINDING_INDEX]++;
return false;
}
return true;
}
/** Updates binding if changed, then returns the latest value. */
export function checkAndUpdateBinding(value: any): any {
bindingUpdated(value);
return value;
/** Updates binding and returns the value. */
export function updateBinding(bindingIndex: number, value: any): any {
return viewData[bindingIndex] = value;
}
/** Updates 2 bindings if changed, then returns whether either was updated. */
export function bindingUpdated2(exp1: any, exp2: any): boolean {
const different = bindingUpdated(exp1);
return bindingUpdated(exp2) || different;
export function bindingUpdated2(bindingIndex: number, exp1: any, exp2: any): boolean {
const different = bindingUpdated(bindingIndex, exp1);
return bindingUpdated(bindingIndex + 1, exp2) || different;
}
/** Updates 3 bindings if changed, then returns whether any was updated. */
export function bindingUpdated3(bindingIndex: number, exp1: any, exp2: any, exp3: any): boolean {
const different = bindingUpdated2(bindingIndex, exp1, exp2);
return bindingUpdated(bindingIndex + 2, exp3) || different;
}
/** Updates 4 bindings if changed, then returns whether any was updated. */
export function bindingUpdated4(exp1: any, exp2: any, exp3: any, exp4: any): boolean {
const different = bindingUpdated2(exp1, exp2);
return bindingUpdated2(exp3, exp4) || different;
export function bindingUpdated4(
bindingIndex: number, exp1: any, exp2: any, exp3: any, exp4: any): boolean {
const different = bindingUpdated2(bindingIndex, exp1, exp2);
return bindingUpdated2(bindingIndex + 2, exp3, exp4) || different;
}
export function getTView(): TView {
@ -2856,22 +2833,6 @@ function assertDataNext(index: number, arr?: any[]) {
arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
}
/**
* On the first template pass, the reserved slots should be set `NO_CHANGE`.
*
* If not, they might not have been actually reserved.
*/
export function assertReservedSlotInitialized(slotOffset: number, numSlots: number) {
if (firstTemplatePass) {
const startIndex = tView.bindingStartIndex - slotOffset;
for (let i = 0; i < numSlots; i++) {
assertEqual(
viewData[startIndex + i], NO_CHANGE,
'The reserved slots should be set to `NO_CHANGE` on first template pass');
}
}
}
export function _getComponentHostLElementNode<T>(component: T): LElementNode {
ngDevMode && assertDefined(component, 'expecting component got null');
const lElementNode = (component as any)[NG_HOST_SYMBOL] as LElementNode;

View File

@ -6,34 +6,44 @@
* found in the LICENSE file at https://angular.io/license
*/
import {assertReservedSlotInitialized, bindingUpdated, bindingUpdated2, bindingUpdated4, checkAndUpdateBinding, consumeBinding, getCreationMode, moveBindingIndexToReservedSlot, restoreBindingIndex} from './instructions';
import {bindingUpdated, bindingUpdated2, bindingUpdated4, updateBinding, getBinding, getCreationMode, getTView, initBindings, bindingUpdated3,} from './instructions';
/**
* Bindings for pure functions are stored after regular bindings.
*
* ----------------------------------------------------------------------------
* | LNodes ... | regular bindings / interpolations | pure function bindings
* ----------------------------------------------------------------------------
* ^
* TView.bindingStartIndex
*
* Pure function instructions are given an offset from TView.bindingStartIndex.
* Adding the offset to TView.bindingStartIndex gives the first index where the bindings
* are stored.
*/
/**
* If the value hasn't been saved, calls the pure function to store and return the
* value. If it has been saved, returns the saved value.
*
* @param slotOffset the offset from binding root to the reserved slot
* @param pureFn Function that returns a value
* @param slotOffset the offset in the reserved slot space {@link reserveSlots}
* @param thisArg Optional calling context of pureFn
* @returns value
*/
export function pureFunction0<T>(slotOffset: number, pureFn: () => T, thisArg?: any): T {
ngDevMode && assertReservedSlotInitialized(slotOffset, 1);
const index = moveBindingIndexToReservedSlot(slotOffset);
const value = getCreationMode() ?
checkAndUpdateBinding(thisArg ? pureFn.call(thisArg) : pureFn()) :
consumeBinding();
restoreBindingIndex(index);
return value;
initBindings(); // TODO(kara): remove this check when we have pre-filled array
const bindingIndex = getTView().bindingStartIndex + slotOffset;
return getCreationMode() ?
updateBinding(bindingIndex, thisArg ? pureFn.call(thisArg) : pureFn()) :
getBinding(bindingIndex);
}
/**
* If the value of the provided exp has changed, calls the pure function to return
* an updated value. Or if the value has not changed, returns cached value.
*
* @param slotOffset the offset in the reserved slot space {@link reserveSlots}
* @param slotOffset the offset from binding root to the reserved slot
* @param pureFn Function that returns an updated value
* @param exp Updated expression value
* @param thisArg Optional calling context of pureFn
@ -41,20 +51,18 @@ export function pureFunction0<T>(slotOffset: number, pureFn: () => T, thisArg?:
*/
export function pureFunction1(
slotOffset: number, pureFn: (v: any) => any, exp: any, thisArg?: any): any {
ngDevMode && assertReservedSlotInitialized(slotOffset, 2);
const index = moveBindingIndexToReservedSlot(slotOffset);
const value = bindingUpdated(exp) ?
checkAndUpdateBinding(thisArg ? pureFn.call(thisArg, exp) : pureFn(exp)) :
consumeBinding();
restoreBindingIndex(index);
return value;
initBindings(); // TODO(kara): remove this check when we have pre-filled array
const bindingIndex = getTView().bindingStartIndex + slotOffset;
return bindingUpdated(bindingIndex, exp) ?
updateBinding(bindingIndex + 1, thisArg ? pureFn.call(thisArg, exp) : pureFn(exp)) :
getBinding(bindingIndex + 1);
}
/**
* If the value of any provided exp has changed, calls the pure function to return
* an updated value. Or if no values have changed, returns cached value.
*
* @param slotOffset the offset in the reserved slot space {@link reserveSlots}
* @param slotOffset the offset from binding root to the reserved slot
* @param pureFn
* @param exp1
* @param exp2
@ -64,20 +72,19 @@ export function pureFunction1(
export function pureFunction2(
slotOffset: number, pureFn: (v1: any, v2: any) => any, exp1: any, exp2: any,
thisArg?: any): any {
ngDevMode && assertReservedSlotInitialized(slotOffset, 3);
const index = moveBindingIndexToReservedSlot(slotOffset);
const value = bindingUpdated2(exp1, exp2) ?
checkAndUpdateBinding(thisArg ? pureFn.call(thisArg, exp1, exp2) : pureFn(exp1, exp2)) :
consumeBinding();
restoreBindingIndex(index);
return value;
initBindings(); // TODO(kara): remove this check when we have pre-filled array
const bindingIndex = getTView().bindingStartIndex + slotOffset;
return bindingUpdated2(bindingIndex, exp1, exp2) ?
updateBinding(
bindingIndex + 2, thisArg ? pureFn.call(thisArg, exp1, exp2) : pureFn(exp1, exp2)) :
getBinding(bindingIndex + 2);
}
/**
* If the value of any provided exp has changed, calls the pure function to return
* an updated value. Or if no values have changed, returns cached value.
*
* @param slotOffset the offset in the reserved slot space {@link reserveSlots}
* @param slotOffset the offset from binding root to the reserved slot
* @param pureFn
* @param exp1
* @param exp2
@ -88,22 +95,20 @@ export function pureFunction2(
export function pureFunction3(
slotOffset: number, pureFn: (v1: any, v2: any, v3: any) => any, exp1: any, exp2: any, exp3: any,
thisArg?: any): any {
ngDevMode && assertReservedSlotInitialized(slotOffset, 4);
const index = moveBindingIndexToReservedSlot(slotOffset);
const different = bindingUpdated2(exp1, exp2);
const value = bindingUpdated(exp3) || different ?
checkAndUpdateBinding(
initBindings(); // TODO(kara): remove this check when we have pre-filled array
const bindingIndex = getTView().bindingStartIndex + slotOffset;
return bindingUpdated3(bindingIndex, exp1, exp2, exp3) ?
updateBinding(
bindingIndex + 3,
thisArg ? pureFn.call(thisArg, exp1, exp2, exp3) : pureFn(exp1, exp2, exp3)) :
consumeBinding();
restoreBindingIndex(index);
return value;
getBinding(bindingIndex + 3);
}
/**
* If the value of any provided exp has changed, calls the pure function to return
* an updated value. Or if no values have changed, returns cached value.
*
* @param slotOffset the offset in the reserved slot space {@link reserveSlots}
* @param slotOffset the offset from binding root to the reserved slot
* @param pureFn
* @param exp1
* @param exp2
@ -115,21 +120,20 @@ export function pureFunction3(
export function pureFunction4(
slotOffset: number, pureFn: (v1: any, v2: any, v3: any, v4: any) => any, exp1: any, exp2: any,
exp3: any, exp4: any, thisArg?: any): any {
ngDevMode && assertReservedSlotInitialized(slotOffset, 5);
const index = moveBindingIndexToReservedSlot(slotOffset);
const value = bindingUpdated4(exp1, exp2, exp3, exp4) ?
checkAndUpdateBinding(
initBindings(); // TODO(kara): remove this check when we have pre-filled array
const bindingIndex = getTView().bindingStartIndex + slotOffset;
return bindingUpdated4(bindingIndex, exp1, exp2, exp3, exp4) ?
updateBinding(
bindingIndex + 4,
thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4) : pureFn(exp1, exp2, exp3, exp4)) :
consumeBinding();
restoreBindingIndex(index);
return value;
getBinding(bindingIndex + 4);
}
/**
* If the value of any provided exp has changed, calls the pure function to return
* an updated value. Or if no values have changed, returns cached value.
*
* @param slotOffset the offset in the reserved slot space {@link reserveSlots}
* @param slotOffset the offset from binding root to the reserved slot
* @param pureFn
* @param exp1
* @param exp2
@ -142,23 +146,21 @@ export function pureFunction4(
export function pureFunction5(
slotOffset: number, pureFn: (v1: any, v2: any, v3: any, v4: any, v5: any) => any, exp1: any,
exp2: any, exp3: any, exp4: any, exp5: any, thisArg?: any): any {
ngDevMode && assertReservedSlotInitialized(slotOffset, 6);
const index = moveBindingIndexToReservedSlot(slotOffset);
const different = bindingUpdated4(exp1, exp2, exp3, exp4);
const value = bindingUpdated(exp5) || different ?
checkAndUpdateBinding(
thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5) :
pureFn(exp1, exp2, exp3, exp4, exp5)) :
consumeBinding();
restoreBindingIndex(index);
return value;
initBindings(); // TODO(kara): remove this check when we have pre-filled array
const bindingIndex = getTView().bindingStartIndex + slotOffset;
const different = bindingUpdated4(bindingIndex, exp1, exp2, exp3, exp4);
return bindingUpdated(bindingIndex + 4, exp5) || different ?
updateBinding(
bindingIndex + 5, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5) :
pureFn(exp1, exp2, exp3, exp4, exp5)) :
getBinding(bindingIndex + 5);
}
/**
* If the value of any provided exp has changed, calls the pure function to return
* an updated value. Or if no values have changed, returns cached value.
*
* @param slotOffset the offset in the reserved slot space {@link reserveSlots}
* @param slotOffset the offset from binding root to the reserved slot
* @param pureFn
* @param exp1
* @param exp2
@ -172,23 +174,21 @@ export function pureFunction5(
export function pureFunction6(
slotOffset: number, pureFn: (v1: any, v2: any, v3: any, v4: any, v5: any, v6: any) => any,
exp1: any, exp2: any, exp3: any, exp4: any, exp5: any, exp6: any, thisArg?: any): any {
ngDevMode && assertReservedSlotInitialized(slotOffset, 7);
const index = moveBindingIndexToReservedSlot(slotOffset);
const different = bindingUpdated4(exp1, exp2, exp3, exp4);
const value = bindingUpdated2(exp5, exp6) || different ?
checkAndUpdateBinding(
thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6) :
pureFn(exp1, exp2, exp3, exp4, exp5, exp6)) :
consumeBinding();
restoreBindingIndex(index);
return value;
initBindings(); // TODO(kara): remove this check when we have pre-filled array
const bindingIndex = getTView().bindingStartIndex + slotOffset;
const different = bindingUpdated4(bindingIndex, exp1, exp2, exp3, exp4);
return bindingUpdated2(bindingIndex + 4, exp5, exp6) || different ?
updateBinding(
bindingIndex + 6, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6) :
pureFn(exp1, exp2, exp3, exp4, exp5, exp6)) :
getBinding(bindingIndex + 6);
}
/**
* If the value of any provided exp has changed, calls the pure function to return
* an updated value. Or if no values have changed, returns cached value.
*
* @param slotOffset the offset in the reserved slot space {@link reserveSlots}
* @param slotOffset the offset from binding root to the reserved slot
* @param pureFn
* @param exp1
* @param exp2
@ -204,24 +204,22 @@ export function pureFunction7(
slotOffset: number,
pureFn: (v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any) => any, exp1: any,
exp2: any, exp3: any, exp4: any, exp5: any, exp6: any, exp7: any, thisArg?: any): any {
ngDevMode && assertReservedSlotInitialized(slotOffset, 8);
const index = moveBindingIndexToReservedSlot(slotOffset);
let different = bindingUpdated4(exp1, exp2, exp3, exp4);
different = bindingUpdated2(exp5, exp6) || different;
const value = bindingUpdated(exp7) || different ?
checkAndUpdateBinding(
thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7) :
pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7)) :
consumeBinding();
restoreBindingIndex(index);
return value;
initBindings(); // TODO(kara): remove this check when we have pre-filled array
const bindingIndex = getTView().bindingStartIndex + slotOffset;
let different = bindingUpdated4(bindingIndex, exp1, exp2, exp3, exp4);
return bindingUpdated3(bindingIndex + 4, exp5, exp6, exp7) || different ?
updateBinding(
bindingIndex + 7, thisArg ?
pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7) :
pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7)) :
getBinding(bindingIndex + 7);
}
/**
* If the value of any provided exp has changed, calls the pure function to return
* an updated value. Or if no values have changed, returns cached value.
*
* @param slotOffset the offset in the reserved slot space {@link reserveSlots}
* @param slotOffset the offset from binding root to the reserved slot
* @param pureFn
* @param exp1
* @param exp2
@ -239,16 +237,15 @@ export function pureFunction8(
pureFn: (v1: any, v2: any, v3: any, v4: any, v5: any, v6: any, v7: any, v8: any) => any,
exp1: any, exp2: any, exp3: any, exp4: any, exp5: any, exp6: any, exp7: any, exp8: any,
thisArg?: any): any {
ngDevMode && assertReservedSlotInitialized(slotOffset, 9);
const index = moveBindingIndexToReservedSlot(slotOffset);
const different = bindingUpdated4(exp1, exp2, exp3, exp4);
const value = bindingUpdated4(exp5, exp6, exp7, exp8) || different ?
checkAndUpdateBinding(
thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8) :
pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8)) :
consumeBinding();
restoreBindingIndex(index);
return value;
initBindings(); // TODO(kara): remove this check when we have pre-filled array
const bindingIndex = getTView().bindingStartIndex + slotOffset;
const different = bindingUpdated4(bindingIndex, exp1, exp2, exp3, exp4);
return bindingUpdated4(bindingIndex + 4, exp5, exp6, exp7, exp8) || different ?
updateBinding(
bindingIndex + 8, thisArg ?
pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8) :
pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8)) :
getBinding(bindingIndex + 8);
}
/**
@ -257,7 +254,7 @@ export function pureFunction8(
* If the value of any provided exp has changed, calls the pure function to return
* an updated value. Or if no values have changed, returns cached value.
*
* @param slotOffset the offset in the reserved slot space {@link reserveSlots}
* @param slotOffset the offset from binding root to the reserved slot
* @param pureFn A pure function that takes binding values and builds an object or array
* containing those values.
* @param exps An array of binding values
@ -266,14 +263,12 @@ export function pureFunction8(
*/
export function pureFunctionV(
slotOffset: number, pureFn: (...v: any[]) => any, exps: any[], thisArg?: any): any {
ngDevMode && assertReservedSlotInitialized(slotOffset, exps.length + 1);
const index = moveBindingIndexToReservedSlot(slotOffset);
initBindings(); // TODO(kara): remove this check when we have pre-filled array
let bindingIndex = getTView().bindingStartIndex + slotOffset;
let different = false;
for (let i = 0; i < exps.length; i++) {
bindingUpdated(exps[i]) && (different = true);
bindingUpdated(bindingIndex++, exps[i]) && (different = true);
}
const value = different ? checkAndUpdateBinding(pureFn.apply(thisArg, exps)) : consumeBinding();
restoreBindingIndex(index);
return value;
return different ? updateBinding(bindingIndex, pureFn.apply(thisArg, exps)) :
getBinding(bindingIndex);
}