refactor(ivy): remove reserveSlots instruction (#25533)
PR Close #25533
This commit is contained in:
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);
|
||||
}
|
||||
|
|
|
@ -503,7 +503,6 @@ describe('components & directives', () => {
|
|||
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, 'my-array-comp');
|
||||
$r3$.ɵreserveSlots(1);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(
|
||||
|
@ -570,7 +569,6 @@ describe('components & directives', () => {
|
|||
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, 'my-comp');
|
||||
$r3$.ɵreserveSlots(1);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(
|
||||
|
@ -614,7 +612,6 @@ describe('components & directives', () => {
|
|||
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, 'my-array-comp');
|
||||
$r3$.ɵreserveSlots(2);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(
|
||||
|
@ -726,7 +723,6 @@ describe('components & directives', () => {
|
|||
template: function MyApp_Template(rf: $RenderFlags$, c: $any$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, 'my-comp');
|
||||
$r3$.ɵreserveSlots(10);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(
|
||||
|
@ -805,7 +801,6 @@ describe('components & directives', () => {
|
|||
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, 'object-comp');
|
||||
$r3$.ɵreserveSlots(2);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(
|
||||
|
@ -892,7 +887,6 @@ describe('components & directives', () => {
|
|||
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelement(0, 'nested-comp');
|
||||
$r3$.ɵreserveSlots(7);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵelementProperty(
|
||||
|
|
|
@ -88,7 +88,6 @@ describe('pipes', () => {
|
|||
$r3$.ɵtext(0);
|
||||
$r3$.ɵpipe(1, 'myPipe');
|
||||
$r3$.ɵpipe(2, 'myPurePipe');
|
||||
$r3$.ɵreserveSlots(6);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵtextBinding(
|
||||
|
@ -150,6 +149,21 @@ describe('pipes', () => {
|
|||
// /NORMATIVE
|
||||
}
|
||||
|
||||
function MyApp_div_Template_4(rf: $RenderFlags$, ctx: any) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, 'div');
|
||||
$r3$.ɵtext(1);
|
||||
$r3$.ɵpipe(2, 'myPurePipe');
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵreserveSlots(3);
|
||||
}
|
||||
if (rf & 2) {
|
||||
const $comp$ = $r3$.ɵnextContext();
|
||||
$r3$.ɵtextBinding(
|
||||
1, $r3$.ɵinterpolation1('', $r3$.ɵpipeBind2(2, 3, $comp$.name, $comp$.size), ''));
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `{{name | myPurePipe:size}}{{name | myPurePipe:size}}
|
||||
<div *oneTimeIf="more">{{name | myPurePipe:size}}</div>`
|
||||
|
@ -170,7 +184,7 @@ describe('pipes', () => {
|
|||
$r3$.ɵpipe(1, 'myPurePipe');
|
||||
$r3$.ɵtext(2);
|
||||
$r3$.ɵpipe(3, 'myPurePipe');
|
||||
$r3$.ɵtemplate(4, C4, '', ['oneTimeIf', '']);
|
||||
$r3$.ɵtemplate(4, MyApp_div_Template_4, '', ['oneTimeIf', '']);
|
||||
$r3$.ɵreserveSlots(6);
|
||||
}
|
||||
if (rf & 2) {
|
||||
|
@ -182,20 +196,6 @@ describe('pipes', () => {
|
|||
$r3$.ɵcontainerRefreshStart(4);
|
||||
$r3$.ɵcontainerRefreshEnd();
|
||||
}
|
||||
|
||||
function C4(rf: $RenderFlags$, ctx1: $any$) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵelementStart(0, 'div');
|
||||
$r3$.ɵtext(1);
|
||||
$r3$.ɵpipe(2, 'myPurePipe');
|
||||
$r3$.ɵelementEnd();
|
||||
$r3$.ɵreserveSlots(3);
|
||||
}
|
||||
if (rf & 2) {
|
||||
$r3$.ɵtextBinding(
|
||||
1, $r3$.ɵinterpolation1('', $r3$.ɵpipeBind2(2, 3, ctx.name, ctx.size), ''));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// /NORMATIVE
|
||||
|
|
|
@ -10,7 +10,7 @@ import {Directive, OnChanges, OnDestroy, Pipe, PipeTransform} from '@angular/cor
|
|||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||
|
||||
import {defineDirective, definePipe} from '../../src/render3/definition';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, load, loadDirective, reserveSlots, text, textBinding} from '../../src/render3/instructions';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, load, loadDirective, text, textBinding} from '../../src/render3/instructions';
|
||||
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
||||
import {pipe, pipeBind1, pipeBind3, pipeBind4, pipeBindV} from '../../src/render3/pipe';
|
||||
|
||||
|
@ -38,10 +38,9 @@ describe('pipe', () => {
|
|||
if (rf & RenderFlags.Create) {
|
||||
text(0);
|
||||
pipe(1, 'countingPipe');
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
textBinding(0, interpolation1('', pipeBind1(1, 2, person.name), ''));
|
||||
textBinding(0, interpolation1('', pipeBind1(1, 1, person.name), ''));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,10 +53,9 @@ describe('pipe', () => {
|
|||
if (rf & RenderFlags.Create) {
|
||||
text(0);
|
||||
pipe(1, 'randomPipeName');
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
textBinding(0, interpolation1('', pipeBind1(1, 2, ctx.value), ''));
|
||||
textBinding(0, interpolation1('', pipeBind1(1, 1, ctx.value), ''));
|
||||
}
|
||||
}, [], pipes);
|
||||
|
||||
|
@ -99,10 +97,9 @@ describe('pipe', () => {
|
|||
elementStart(0, 'div', ['myDir', '']);
|
||||
pipe(1, 'double');
|
||||
elementEnd();
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'elprop', bind(pipeBind1(1, 2, ctx)));
|
||||
elementProperty(0, 'elprop', bind(pipeBind1(1, 1, ctx)));
|
||||
directive = loadDirective(0);
|
||||
}
|
||||
}
|
||||
|
@ -115,11 +112,10 @@ describe('pipe', () => {
|
|||
if (rf & RenderFlags.Create) {
|
||||
text(0);
|
||||
pipe(1, 'multiArgPipe');
|
||||
reserveSlots(4);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
textBinding(
|
||||
0, interpolation1('', pipeBind3(1, 4, person.name, 'one', person.address !.city), ''));
|
||||
0, interpolation1('', pipeBind3(1, 1, person.name, 'one', person.address !.city), ''));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,12 +129,11 @@ describe('pipe', () => {
|
|||
text(0);
|
||||
pipe(1, 'multiArgPipe');
|
||||
pipe(2, 'multiArgPipe');
|
||||
reserveSlots(9);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
textBinding(
|
||||
0, interpolation1(
|
||||
'', pipeBind4(2, 9, pipeBindV(1, 4, [person.name, 'a', 'b']), 0, 1, 2), ''));
|
||||
'', pipeBind4(2, 5, pipeBindV(1, 1, [person.name, 'a', 'b']), 0, 1, 2), ''));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,10 +158,9 @@ describe('pipe', () => {
|
|||
elementStart(0, 'div');
|
||||
pipe(1, 'identityPipe');
|
||||
elementEnd();
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'someProp', bind(pipeBind1(1, 2, 'Megatron')));
|
||||
elementProperty(0, 'someProp', bind(pipeBind1(1, 1, 'Megatron')));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,10 +178,9 @@ describe('pipe', () => {
|
|||
if (rf & RenderFlags.Create) {
|
||||
text(0);
|
||||
pipe(1, 'countingPipe');
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
textBinding(0, interpolation1('', pipeBind1(1, 2, person.name), ''));
|
||||
textBinding(0, interpolation1('', pipeBind1(1, 1, person.name), ''));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,10 +207,9 @@ describe('pipe', () => {
|
|||
if (rf & RenderFlags.Create) {
|
||||
text(0);
|
||||
pipe(1, 'countingImpurePipe');
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
textBinding(0, interpolation1('', pipeBind1(1, 2, person.name), ''));
|
||||
textBinding(0, interpolation1('', pipeBind1(1, 1, person.name), ''));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,7 +228,6 @@ describe('pipe', () => {
|
|||
pipe(3, 'countingImpurePipe');
|
||||
elementEnd();
|
||||
container(4);
|
||||
reserveSlots(4);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'someProp', bind(pipeBind1(1, 2, true)));
|
||||
|
@ -251,10 +242,9 @@ describe('pipe', () => {
|
|||
elementStart(0, 'div');
|
||||
pipe(1, 'countingImpurePipe');
|
||||
elementEnd();
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf1 & RenderFlags.Update) {
|
||||
elementProperty(0, 'someProp', bind(pipeBind1(1, 2, true)));
|
||||
elementProperty(0, 'someProp', bind(pipeBind1(1, 1, true)));
|
||||
pipeInstances.push(load<CountingImpurePipe>(1));
|
||||
}
|
||||
}
|
||||
|
@ -306,10 +296,9 @@ describe('pipe', () => {
|
|||
if (rf1 & RenderFlags.Create) {
|
||||
text(0);
|
||||
pipe(1, 'pipeWithOnDestroy');
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
textBinding(0, interpolation1('', pipeBind1(1, 2, person.age), ''));
|
||||
textBinding(0, interpolation1('', pipeBind1(1, 1, person.age), ''));
|
||||
}
|
||||
}
|
||||
embeddedViewEnd();
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {defineComponent} from '../../src/render3/index';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, load, loadDirective, reserveSlots} from '../../src/render3/instructions';
|
||||
import {AttributeMarker, defineComponent, template} from '../../src/render3/index';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, loadDirective, nextContext} from '../../src/render3/instructions';
|
||||
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
||||
import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunction5, pureFunction6, pureFunction7, pureFunction8, pureFunctionV} from '../../src/render3/pure_function';
|
||||
import {renderToHtml} from '../../test/render3/render_util';
|
||||
import {ComponentFixture, createComponent, renderToHtml} from '../../test/render3/render_util';
|
||||
import {NgIf} from './common_with_def';
|
||||
|
||||
describe('array literals', () => {
|
||||
let myComp: MyComp;
|
||||
|
@ -36,10 +37,9 @@ describe('array literals', () => {
|
|||
function Template(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
element(0, 'my-comp');
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'names', bind(pureFunction1(2, e0_ff, ctx.customName)));
|
||||
elementProperty(0, 'names', bind(pureFunction1(1, e0_ff, ctx.customName)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,39 @@ describe('array literals', () => {
|
|||
expect(myComp !.names).toEqual(['should not be overwritten']);
|
||||
});
|
||||
|
||||
it('should support array literals in dynamic views', () => {
|
||||
const e0_ff = (v: any) => ['Nancy', v, 'Bess'];
|
||||
|
||||
function IfTemplate(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
element(0, 'my-comp');
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
const comp = nextContext();
|
||||
elementProperty(0, 'names', bind(pureFunction1(1, e0_ff, comp.customName)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <my-comp *ngIf="showing" [names]="['Nancy', customName, 'Bess']"></my-comp>
|
||||
*/
|
||||
const App = createComponent('app', function(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
template(0, IfTemplate, null, [AttributeMarker.SelectOnly, 'ngIf']);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'ngIf', bind(ctx.showing));
|
||||
}
|
||||
}, [MyComp, NgIf]);
|
||||
|
||||
const fixture = new ComponentFixture(App);
|
||||
fixture.component.showing = true;
|
||||
fixture.component.customName = 'Carson';
|
||||
fixture.update();
|
||||
|
||||
expect(myComp !.names).toEqual(['Nancy', 'Carson', 'Bess']);
|
||||
});
|
||||
|
||||
it('should support multiple array literals passed through to one node', () => {
|
||||
let manyPropComp: ManyPropComp;
|
||||
|
||||
|
@ -92,7 +125,6 @@ describe('array literals', () => {
|
|||
function Template(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
element(0, 'many-prop-comp');
|
||||
reserveSlots(4);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'names1', bind(pureFunction1(2, e0_ff, ctx.customName)));
|
||||
|
@ -133,10 +165,9 @@ describe('array literals', () => {
|
|||
elementStart(0, 'my-comp');
|
||||
myComps.push(loadDirective(0));
|
||||
elementEnd();
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'names', bind(ctx.someFn(pureFunction1(2, e0_ff, ctx.customName))));
|
||||
elementProperty(0, 'names', bind(ctx.someFn(pureFunction1(1, e0_ff, ctx.customName))));
|
||||
}
|
||||
},
|
||||
directives: directives
|
||||
|
@ -171,10 +202,9 @@ describe('array literals', () => {
|
|||
function Template(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
element(0, 'my-comp');
|
||||
reserveSlots(3);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'names', bind(pureFunction2(3, e0_ff, ctx.customName, ctx.customName2)));
|
||||
elementProperty(0, 'names', bind(pureFunction2(1, e0_ff, ctx.customName, ctx.customName2)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,19 +273,18 @@ describe('array literals', () => {
|
|||
elementStart(5, 'my-comp');
|
||||
f8Comp = loadDirective(5);
|
||||
elementEnd();
|
||||
reserveSlots(39);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'names', bind(pureFunction3(4, e0_ff, c[5], c[6], c[7])));
|
||||
elementProperty(1, 'names', bind(pureFunction4(9, e2_ff, c[4], c[5], c[6], c[7])));
|
||||
elementProperty(0, 'names', bind(pureFunction3(6, e0_ff, c[5], c[6], c[7])));
|
||||
elementProperty(1, 'names', bind(pureFunction4(10, e2_ff, c[4], c[5], c[6], c[7])));
|
||||
elementProperty(2, 'names', bind(pureFunction5(15, e4_ff, c[3], c[4], c[5], c[6], c[7])));
|
||||
elementProperty(
|
||||
3, 'names', bind(pureFunction6(22, e6_ff, c[2], c[3], c[4], c[5], c[6], c[7])));
|
||||
3, 'names', bind(pureFunction6(21, e6_ff, c[2], c[3], c[4], c[5], c[6], c[7])));
|
||||
elementProperty(
|
||||
4, 'names', bind(pureFunction7(30, e8_ff, c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
|
||||
4, 'names', bind(pureFunction7(28, e8_ff, c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
|
||||
elementProperty(
|
||||
5, 'names',
|
||||
bind(pureFunction8(39, e10_ff, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
|
||||
bind(pureFunction8(36, e10_ff, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,12 +327,11 @@ describe('array literals', () => {
|
|||
function Template(rf: RenderFlags, c: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
element(0, 'my-comp');
|
||||
reserveSlots(12);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(
|
||||
0, 'names', bind(pureFunctionV(12, e0_ff, [
|
||||
c[0], c[1], c[2], c[3], pureFunction1(2, e0_ff_1, c[4]), c[5], c[6], c[7], c[8]
|
||||
0, 'names', bind(pureFunctionV(3, e0_ff, [
|
||||
c[0], c[1], c[2], c[3], pureFunction1(1, e0_ff_1, c[4]), c[5], c[6], c[7], c[8]
|
||||
])));
|
||||
}
|
||||
}
|
||||
|
@ -349,10 +377,9 @@ describe('object literals', () => {
|
|||
function Template(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
element(0, 'object-comp');
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'config', bind(pureFunction1(2, e0_ff, ctx.name)));
|
||||
elementProperty(0, 'config', bind(pureFunction1(1, e0_ff, ctx.name)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,13 +411,12 @@ describe('object literals', () => {
|
|||
function Template(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
element(0, 'object-comp');
|
||||
reserveSlots(7);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(
|
||||
0, 'config', bind(pureFunction2(
|
||||
7, e0_ff, ctx.name,
|
||||
pureFunction1(4, e0_ff_1, pureFunction1(2, e0_ff_2, ctx.duration)))));
|
||||
5, e0_ff, ctx.name,
|
||||
pureFunction1(3, e0_ff_1, pureFunction1(1, e0_ff_2, ctx.duration)))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,12 +482,11 @@ describe('object literals', () => {
|
|||
elementStart(0, 'object-comp');
|
||||
objectComps.push(loadDirective(0));
|
||||
elementEnd();
|
||||
reserveSlots(3);
|
||||
}
|
||||
if (rf1 & RenderFlags.Update) {
|
||||
elementProperty(
|
||||
0, 'config',
|
||||
bind(pureFunction2(3, e0_ff, ctx.configs[i].opacity, ctx.configs[i].duration)));
|
||||
bind(pureFunction2(1, e0_ff, ctx.configs[i].opacity, ctx.configs[i].duration)));
|
||||
}
|
||||
embeddedViewEnd();
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import {Component, ComponentFactoryResolver, ElementRef, EmbeddedViewRef, NgModuleRef, Pipe, PipeTransform, RendererFactory2, TemplateRef, ViewContainerRef, createInjector, defineInjector, ɵAPP_ROOT as APP_ROOT, ɵNgModuleDef as NgModuleDef} from '../../src/core';
|
||||
import {templateRefExtractor} from '../../src/render3/di';
|
||||
import {AttributeMarker, NgOnChangesFeature, defineComponent, defineDirective, definePipe, injectComponentFactoryResolver, injectTemplateRef, injectViewContainerRef} from '../../src/render3/index';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation3, loadDirective, nextContext, projection, projectionDef, reference, reserveSlots, template, text, textBinding} from '../../src/render3/instructions';
|
||||
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, interpolation3, loadDirective, nextContext, projection, projectionDef, reference, template, text, textBinding} from '../../src/render3/instructions';
|
||||
import {RenderFlags} from '../../src/render3/interfaces/definition';
|
||||
import {NgModuleFactory} from '../../src/render3/ng_module_ref';
|
||||
import {pipe, pipeBind1} from '../../src/render3/pipe';
|
||||
|
@ -410,6 +410,16 @@ describe('ViewContainerRef', () => {
|
|||
});
|
||||
}
|
||||
|
||||
function SomeComponent_Template_0(rf: RenderFlags, ctx: any) {
|
||||
if (rf & RenderFlags.Create) {
|
||||
element(0, 'child');
|
||||
pipe(1, 'starPipe');
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'name', bind(pipeBind1(1, 2, 'C')));
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<ng-template #foo>
|
||||
|
@ -426,21 +436,11 @@ describe('ViewContainerRef', () => {
|
|||
factory: () => new SomeComponent(),
|
||||
template: (rf: RenderFlags, cmp: SomeComponent) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
template(0, (rf: RenderFlags, ctx: any) => {
|
||||
if (rf & RenderFlags.Create) {
|
||||
element(0, 'child');
|
||||
pipe(1, 'starPipe');
|
||||
reserveSlots(2);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(0, 'name', bind(pipeBind1(1, 2, 'C')));
|
||||
}
|
||||
}, null, [], ['foo', ''], templateRefExtractor);
|
||||
template(0, SomeComponent_Template_0, null, [], ['foo', ''], templateRefExtractor);
|
||||
pipe(2, 'starPipe');
|
||||
element(3, 'child', ['vcref', '']);
|
||||
pipe(4, 'starPipe');
|
||||
element(5, 'child');
|
||||
reserveSlots(4);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
const tplRef = reference(1);
|
||||
|
|
Loading…
Reference in New Issue