refactor(ivy): remove reserveSlots instruction (#25533)
PR Close #25533
This commit is contained in:

committed by
Jason Aden

parent
21d22ce4ad
commit
4708cb91ef
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user