diff --git a/packages/core/src/render3/pipe.ts b/packages/core/src/render3/pipe.ts index aeb7019afa..30ba298e53 100644 --- a/packages/core/src/render3/pipe.ts +++ b/packages/core/src/render3/pipe.ts @@ -13,8 +13,8 @@ import {getFactoryDef} from './definition'; import {store} from './instructions/all'; import {PipeDef, PipeDefList} from './interfaces/definition'; import {HEADER_OFFSET, LView, TVIEW} from './interfaces/view'; -import {ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunctionV} from './pure_function'; -import {getBindingIndex, getLView} from './state'; +import {pureFunction1Internal, pureFunction2Internal, pureFunction3Internal, pureFunction4Internal, pureFunctionVInternal} from './pure_function'; +import {getBindingIndex, getBindingRoot, getLView} from './state'; import {NO_CHANGE} from './tokens'; import {load} from './util/view_utils'; @@ -89,7 +89,8 @@ export function ɵɵpipeBind1(index: number, slotOffset: number, v1: any): any { const pipeInstance = load(lView, index); return unwrapValue( lView, isPure(lView, index) ? - ɵɵpureFunction1(slotOffset, pipeInstance.transform, v1, pipeInstance) : + pureFunction1Internal( + lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, pipeInstance) : pipeInstance.transform(v1)); } @@ -111,7 +112,8 @@ export function ɵɵpipeBind2(index: number, slotOffset: number, v1: any, v2: an const pipeInstance = load(lView, index); return unwrapValue( lView, isPure(lView, index) ? - ɵɵpureFunction2(slotOffset, pipeInstance.transform, v1, v2, pipeInstance) : + pureFunction2Internal( + lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, pipeInstance) : pipeInstance.transform(v1, v2)); } @@ -133,9 +135,10 @@ export function ɵɵpipeBind3(index: number, slotOffset: number, v1: any, v2: an const lView = getLView(); const pipeInstance = load(lView, index); return unwrapValue( - lView, isPure(lView, index) ? - ɵɵpureFunction3(slotOffset, pipeInstance.transform, v1, v2, v3, pipeInstance) : - pipeInstance.transform(v1, v2, v3)); + lView, isPure(lView, index) ? pureFunction3Internal( + lView, getBindingRoot(), slotOffset, pipeInstance.transform, + v1, v2, v3, pipeInstance) : + pipeInstance.transform(v1, v2, v3)); } /** @@ -158,9 +161,10 @@ export function ɵɵpipeBind4( const lView = getLView(); const pipeInstance = load(lView, index); return unwrapValue( - lView, isPure(lView, index) ? - ɵɵpureFunction4(slotOffset, pipeInstance.transform, v1, v2, v3, v4, pipeInstance) : - pipeInstance.transform(v1, v2, v3, v4)); + lView, isPure(lView, index) ? pureFunction4Internal( + lView, getBindingRoot(), slotOffset, pipeInstance.transform, + v1, v2, v3, v4, pipeInstance) : + pipeInstance.transform(v1, v2, v3, v4)); } /** @@ -180,7 +184,8 @@ export function ɵɵpipeBindV(index: number, slotOffset: number, values: [any, . const pipeInstance = load(lView, index); return unwrapValue( lView, isPure(lView, index) ? - ɵɵpureFunctionV(slotOffset, pipeInstance.transform, values, pipeInstance) : + pureFunctionVInternal( + lView, getBindingRoot(), slotOffset, pipeInstance.transform, values, pipeInstance) : pipeInstance.transform.apply(pipeInstance, values)); } diff --git a/packages/core/src/render3/pure_function.ts b/packages/core/src/render3/pure_function.ts index 980e0620bb..b9d3e2b8d5 100644 --- a/packages/core/src/render3/pure_function.ts +++ b/packages/core/src/render3/pure_function.ts @@ -7,6 +7,7 @@ */ import {bindingUpdated, bindingUpdated2, bindingUpdated3, bindingUpdated4, getBinding, updateBinding} from './bindings'; +import {LView} from './interfaces/view'; import {getBindingRoot, getLView} from './state'; import {NO_CHANGE} from './tokens'; @@ -41,7 +42,6 @@ import {NO_CHANGE} from './tokens'; * @codeGenApi */ export function ɵɵpureFunction0(slotOffset: number, pureFn: () => T, thisArg?: any): T { - // TODO(kara): use bindingRoot instead of bindingStartIndex when implementing host bindings const bindingIndex = getBindingRoot() + slotOffset; const lView = getLView(); return lView[bindingIndex] === NO_CHANGE ? @@ -63,12 +63,7 @@ export function ɵɵpureFunction0(slotOffset: number, pureFn: () => T, thisAr */ export function ɵɵpureFunction1( slotOffset: number, pureFn: (v: any) => any, exp: any, thisArg?: any): any { - // TODO(kara): use bindingRoot instead of bindingStartIndex when implementing host bindings - const lView = getLView(); - const bindingIndex = getBindingRoot() + slotOffset; - return bindingUpdated(lView, bindingIndex, exp) ? - updateBinding(lView, bindingIndex + 1, thisArg ? pureFn.call(thisArg, exp) : pureFn(exp)) : - getBinding(lView, bindingIndex + 1); + return pureFunction1Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp, thisArg); } /** @@ -87,14 +82,8 @@ export function ɵɵpureFunction1( export function ɵɵpureFunction2( slotOffset: number, pureFn: (v1: any, v2: any) => any, exp1: any, exp2: any, thisArg?: any): any { - // TODO(kara): use bindingRoot instead of bindingStartIndex when implementing host bindings - const bindingIndex = getBindingRoot() + slotOffset; - const lView = getLView(); - return bindingUpdated2(lView, bindingIndex, exp1, exp2) ? - updateBinding( - lView, bindingIndex + 2, - thisArg ? pureFn.call(thisArg, exp1, exp2) : pureFn(exp1, exp2)) : - getBinding(lView, bindingIndex + 2); + return pureFunction2Internal( + getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, thisArg); } /** @@ -114,14 +103,8 @@ 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 { - // TODO(kara): use bindingRoot instead of bindingStartIndex when implementing host bindings - const bindingIndex = getBindingRoot() + slotOffset; - const lView = getLView(); - return bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) ? - updateBinding( - lView, bindingIndex + 3, - thisArg ? pureFn.call(thisArg, exp1, exp2, exp3) : pureFn(exp1, exp2, exp3)) : - getBinding(lView, bindingIndex + 3); + return pureFunction3Internal( + getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, thisArg); } /** @@ -142,14 +125,8 @@ 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 { - // TODO(kara): use bindingRoot instead of bindingStartIndex when implementing host bindings - const bindingIndex = getBindingRoot() + slotOffset; - const lView = getLView(); - return bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) ? - updateBinding( - lView, bindingIndex + 4, - thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4) : pureFn(exp1, exp2, exp3, exp4)) : - getBinding(lView, bindingIndex + 4); + return pureFunction4Internal( + getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg); } /** @@ -171,7 +148,6 @@ 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 { - // TODO(kara): use bindingRoot instead of bindingStartIndex when implementing host bindings const bindingIndex = getBindingRoot() + slotOffset; const lView = getLView(); const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4); @@ -202,7 +178,6 @@ 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 { - // TODO(kara): use bindingRoot instead of bindingStartIndex when implementing host bindings const bindingIndex = getBindingRoot() + slotOffset; const lView = getLView(); const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4); @@ -236,7 +211,6 @@ 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 { - // TODO(kara): use bindingRoot instead of bindingStartIndex when implementing host bindings const bindingIndex = getBindingRoot() + slotOffset; const lView = getLView(); let different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4); @@ -272,7 +246,6 @@ 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 { - // TODO(kara): use bindingRoot instead of bindingStartIndex when implementing host bindings const bindingIndex = getBindingRoot() + slotOffset; const lView = getLView(); const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4); @@ -301,10 +274,131 @@ export function ɵɵpureFunction8( */ export function ɵɵpureFunctionV( slotOffset: number, pureFn: (...v: any[]) => any, exps: any[], thisArg?: any): any { - // TODO(kara): use bindingRoot instead of bindingStartIndex when implementing host bindings - let bindingIndex = getBindingRoot() + slotOffset; + return pureFunctionVInternal(getLView(), getBindingRoot(), slotOffset, pureFn, exps, thisArg); +} + + +/** + * 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 lView LView in which the function is being executed. + * @param bindingRoot Binding root index. + * @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 + * @returns Updated or cached value + */ +export function pureFunction1Internal( + lView: LView, bindingRoot: number, slotOffset: number, pureFn: (v: any) => any, exp: any, + thisArg?: any): any { + const bindingIndex = bindingRoot + slotOffset; + return bindingUpdated(lView, bindingIndex, exp) ? + updateBinding(lView, bindingIndex + 1, thisArg ? pureFn.call(thisArg, exp) : pureFn(exp)) : + getBinding(lView, 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 lView LView in which the function is being executed. + * @param bindingRoot Binding root index. + * @param slotOffset the offset from binding root to the reserved slot + * @param pureFn + * @param exp1 + * @param exp2 + * @param thisArg Optional calling context of pureFn + * @returns Updated or cached value + */ +export function pureFunction2Internal( + lView: LView, bindingRoot: number, slotOffset: number, pureFn: (v1: any, v2: any) => any, + exp1: any, exp2: any, thisArg?: any): any { + const bindingIndex = bindingRoot + slotOffset; + return bindingUpdated2(lView, bindingIndex, exp1, exp2) ? + updateBinding( + lView, bindingIndex + 2, + thisArg ? pureFn.call(thisArg, exp1, exp2) : pureFn(exp1, exp2)) : + getBinding(lView, 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 lView LView in which the function is being executed. + * @param bindingRoot Binding root index. + * @param slotOffset the offset from binding root to the reserved slot + * @param pureFn + * @param exp1 + * @param exp2 + * @param exp3 + * @param thisArg Optional calling context of pureFn + * @returns Updated or cached value + */ +export function pureFunction3Internal( + lView: LView, bindingRoot: number, slotOffset: number, + pureFn: (v1: any, v2: any, v3: any) => any, exp1: any, exp2: any, exp3: any, + thisArg?: any): any { + const bindingIndex = bindingRoot + slotOffset; + return bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) ? + updateBinding( + lView, bindingIndex + 3, + thisArg ? pureFn.call(thisArg, exp1, exp2, exp3) : pureFn(exp1, exp2, exp3)) : + getBinding(lView, 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 lView LView in which the function is being executed. + * @param bindingRoot Binding root index. + * @param slotOffset the offset from binding root to the reserved slot + * @param pureFn + * @param exp1 + * @param exp2 + * @param exp3 + * @param exp4 + * @param thisArg Optional calling context of pureFn + * @returns Updated or cached value + * + */ +export function pureFunction4Internal( + lView: LView, bindingRoot: number, slotOffset: number, + pureFn: (v1: any, v2: any, v3: any, v4: any) => any, exp1: any, exp2: any, exp3: any, exp4: any, + thisArg?: any): any { + const bindingIndex = bindingRoot + slotOffset; + return bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) ? + updateBinding( + lView, bindingIndex + 4, + thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4) : pureFn(exp1, exp2, exp3, exp4)) : + getBinding(lView, bindingIndex + 4); +} + +/** + * pureFunction instruction that can support any number of bindings. + * + * 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 lView LView in which the function is being executed. + * @param bindingRoot Binding root index. + * @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 + * @param thisArg Optional calling context of pureFn + * @returns Updated or cached value + */ +export function pureFunctionVInternal( + lView: LView, bindingRoot: number, slotOffset: number, pureFn: (...v: any[]) => any, + exps: any[], thisArg?: any): any { + let bindingIndex = bindingRoot + slotOffset; let different = false; - const lView = getLView(); for (let i = 0; i < exps.length; i++) { bindingUpdated(lView, bindingIndex++, exps[i]) && (different = true); }