fix(compiler): update compiler to generate new slot allocations (#25607)

PR Close #25607
This commit is contained in:
Kara Erickson 2018-08-21 18:52:26 -07:00 committed by Matias Niemelä
parent 5c95b4b3a3
commit 27e2039630
9 changed files with 62 additions and 52 deletions

View File

@ -364,13 +364,12 @@ describe('compiler compliance', () => {
if (rf & 1) { if (rf & 1) {
$r3$.ɵelement(0, "div"); $r3$.ɵelement(0, "div");
$r3$.ɵpipe(1,"pipe"); $r3$.ɵpipe(1,"pipe");
$r3$.ɵreserveSlots(10);
} }
if (rf & 2) { if (rf & 2) {
$r3$.ɵelementProperty(0, "ternary", $r3$.ɵbind((ctx.cond ? $r3$.ɵpureFunction1(6, _c0, ctx.a): _c1))); $r3$.ɵelementProperty(0, "ternary", $r3$.ɵbind((ctx.cond ? $r3$.ɵpureFunction1(8, _c0, ctx.a): _c1)));
$r3$.ɵelementProperty(0, "pipe", $r3$.ɵbind($r3$.ɵpipeBind3(1, 4, ctx.value, 1, 2))); $r3$.ɵelementProperty(0, "pipe", $r3$.ɵbind($r3$.ɵpipeBind3(1, 4, ctx.value, 1, 2)));
$r3$.ɵelementProperty(0, "and", $r3$.ɵbind((ctx.cond && $r3$.ɵpureFunction1(8, _c0, ctx.b)))); $r3$.ɵelementProperty(0, "and", $r3$.ɵbind((ctx.cond && $r3$.ɵpureFunction1(10, _c0, ctx.b))));
$r3$.ɵelementProperty(0, "or", $r3$.ɵbind((ctx.cond || $r3$.ɵpureFunction1(10, _c0, ctx.c)))); $r3$.ɵelementProperty(0, "or", $r3$.ɵbind((ctx.cond || $r3$.ɵpureFunction1(12, _c0, ctx.c))));
} }
} }
`; `;
@ -656,7 +655,7 @@ describe('compiler compliance', () => {
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵelementStart(0, "ul", null, $c1$); $r3$.ɵelementStart(0, "ul", null, $c1$);
$r3$.ɵtemplate(2, MyComponent_li_Template_2, 2, 1, null, $c2$); $r3$.ɵtemplate(2, MyComponent_li_Template_2, 2, 2, null, $c2$);
$r3$.ɵelementEnd(); $r3$.ɵelementEnd();
} }
}, },
@ -718,10 +717,9 @@ describe('compiler compliance', () => {
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵelement(0, "my-comp"); $r3$.ɵelement(0, "my-comp");
$r3$.ɵreserveSlots(2);
} }
if (rf & 2) { if (rf & 2) {
$r3$.ɵelementProperty(0, "names", $r3$.ɵbind($r3$.ɵpureFunction1(2, $e0_ff$, ctx.customName))); $r3$.ɵelementProperty(0, "names", $r3$.ɵbind($r3$.ɵpureFunction1(1, $e0_ff$, ctx.customName)));
} }
}, },
directives: [MyComp] directives: [MyComp]
@ -800,12 +798,11 @@ describe('compiler compliance', () => {
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵelement(0, "my-comp"); $r3$.ɵelement(0, "my-comp");
$r3$.ɵreserveSlots(10);
} }
if (rf & 2) { if (rf & 2) {
$r3$.ɵelementProperty( $r3$.ɵelementProperty(
0, "names", 0, "names",
$r3$.ɵbind($r3$.ɵpureFunctionV(10, $e0_ff$, [ctx.n0, ctx.n1, ctx.n2, ctx.n3, ctx.n4, ctx.n5, ctx.n6, ctx.n7, ctx.n8]))); $r3$.ɵbind($r3$.ɵpureFunctionV(1, $e0_ff$, [ctx.n0, ctx.n1, ctx.n2, ctx.n3, ctx.n4, ctx.n5, ctx.n6, ctx.n7, ctx.n8])));
} }
}, },
directives: [MyComp] directives: [MyComp]
@ -864,10 +861,9 @@ describe('compiler compliance', () => {
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵelement(0, "object-comp"); $r3$.ɵelement(0, "object-comp");
$r3$.ɵreserveSlots(2);
} }
if (rf & 2) { if (rf & 2) {
$r3$.ɵelementProperty(0, "config", $r3$.ɵbind($r3$.ɵpureFunction1(2, $e0_ff$, ctx.name))); $r3$.ɵelementProperty(0, "config", $r3$.ɵbind($r3$.ɵpureFunction1(1, $e0_ff$, ctx.name)));
} }
}, },
directives: [ObjectComp] directives: [ObjectComp]
@ -932,12 +928,11 @@ describe('compiler compliance', () => {
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵelement(0, "nested-comp"); $r3$.ɵelement(0, "nested-comp");
$r3$.ɵreserveSlots(7);
} }
if (rf & 2) { if (rf & 2) {
$r3$.ɵelementProperty( $r3$.ɵelementProperty(
0, "config", 0, "config",
$r3$.ɵbind($r3$.ɵpureFunction2(7, $e0_ff_2$, ctx.name, $r3$.ɵpureFunction1(4, $e0_ff_1$, $r3$.ɵpureFunction1(2, $e0_ff$, ctx.duration))))); $r3$.ɵbind($r3$.ɵpureFunction2(5, $e0_ff_2$, ctx.name, $r3$.ɵpureFunction1(3, $e0_ff_1$, $r3$.ɵpureFunction1(1, $e0_ff$, ctx.duration)))));
} }
}, },
directives: [NestedComp] directives: [NestedComp]
@ -1254,11 +1249,10 @@ describe('compiler compliance', () => {
$r3$.ɵtext(4); $r3$.ɵtext(4);
$r3$.ɵpipe(5, "myPipe"); $r3$.ɵpipe(5, "myPipe");
$r3$.ɵelementEnd(); $r3$.ɵelementEnd();
$r3$.ɵreserveSlots(15);
} }
if (rf & 2) { if (rf & 2) {
$r3$.ɵtextBinding(0, $r3$.ɵinterpolation1("", $r3$.ɵpipeBind2(1, 3, $r3$.ɵpipeBind2(2, 6, ctx.name, ctx.size), ctx.size), "")); $r3$.ɵtextBinding(0, $r3$.ɵinterpolation1("", $r3$.ɵpipeBind2(1, 2, $r3$.ɵpipeBind2(2, 5, ctx.name, ctx.size), ctx.size), ""));
$r3$.ɵtextBinding(4, $r3$.ɵinterpolation1("", $r3$.ɵpipeBindV(5, 13 , $r3$.ɵpureFunction1(15, $c0$, ctx.name)), "")); $r3$.ɵtextBinding(4, $r3$.ɵinterpolation1("", $r3$.ɵpipeBindV(5, 8, $r3$.ɵpureFunction1(15, $c0$, ctx.name)), ""));
} }
}, },
pipes: [MyPurePipe, MyPipe] pipes: [MyPurePipe, MyPipe]
@ -1373,7 +1367,7 @@ describe('compiler compliance', () => {
if (rf & 1) { if (rf & 1) {
$r3$.ɵelementStart(0, "div"); $r3$.ɵelementStart(0, "div");
$r3$.ɵtext(1); $r3$.ɵtext(1);
$r3$.ɵtemplate(2, MyComponent_div_span_Template_2, 2, 1, null, $c2$); $r3$.ɵtemplate(2, MyComponent_div_span_Template_2, 2, 3, null, $c2$);
$r3$.ɵelement(3, "span", null, $c4$); $r3$.ɵelement(3, "span", null, $c4$);
$r3$.ɵelementEnd(); $r3$.ɵelementEnd();
} }
@ -1396,7 +1390,7 @@ describe('compiler compliance', () => {
if (rf & 1) { if (rf & 1) {
$r3$.ɵelement(0, "div", null, $c1$); $r3$.ɵelement(0, "div", null, $c1$);
$r3$.ɵtext(2); $r3$.ɵtext(2);
$r3$.ɵtemplate(3, MyComponent_div_Template_3, 5, 1, null, $c2$); $r3$.ɵtemplate(3, MyComponent_div_Template_3, 5, 2, null, $c2$);
$r3$.ɵelement(4, "div", null, $c3$); $r3$.ɵelement(4, "div", null, $c3$);
} }
if (rf & 2) { if (rf & 2) {
@ -1460,7 +1454,7 @@ describe('compiler compliance', () => {
if (rf & 1) { if (rf & 1) {
$i0$.ɵelementStart(0, "div"); $i0$.ɵelementStart(0, "div");
$i0$.ɵelement(1, "div", null, $c1$); $i0$.ɵelement(1, "div", null, $c1$);
$i0$.ɵtemplate(3, MyComponent_div_span_Template_3, 2, 1, null, $c2$); $i0$.ɵtemplate(3, MyComponent_div_span_Template_3, 2, 2, null, $c2$);
$i0$.ɵelementEnd(); $i0$.ɵelementEnd();
} }
if (rf & 2) { if (rf & 2) {
@ -1839,7 +1833,7 @@ describe('compiler compliance', () => {
$r3$.ɵtext(2); $r3$.ɵtext(2);
$r3$.ɵelementEnd(); $r3$.ɵelementEnd();
$r3$.ɵelementStart(3, "ul"); $r3$.ɵelementStart(3, "ul");
$r3$.ɵtemplate(4, MyComponent_li_li_Template_4, 2, 1, null, $c1$); $r3$.ɵtemplate(4, MyComponent_li_li_Template_4, 2, 2, null, $c1$);
$r3$.ɵelementEnd(); $r3$.ɵelementEnd();
$r3$.ɵelementEnd(); $r3$.ɵelementEnd();
} }

View File

@ -155,7 +155,7 @@ describe('compiler compliance: template', () => {
// ... // ...
template:function MyComponent_Template(rf, ctx){ template:function MyComponent_Template(rf, ctx){
if (rf & 1) { if (rf & 1) {
$i0$.ɵtemplate(0, MyComponent_span_Template_0, 2, 1, null, _c0); $i0$.ɵtemplate(0, MyComponent_span_Template_0, 2, 2, null, _c0);
} }
if (rf & 2) { if (rf & 2) {
$i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items)); $i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items));
@ -211,7 +211,7 @@ describe('compiler compliance: template', () => {
function MyComponent_div_Template_0(rf, ctx) { function MyComponent_div_Template_0(rf, ctx) {
if (rf & 1) { if (rf & 1) {
$i0$.ɵelementStart(0, "div"); $i0$.ɵelementStart(0, "div");
$i0$.ɵtemplate(1, MyComponent_div_span_Template_1, 2, 1, null, $c1$); $i0$.ɵtemplate(1, MyComponent_div_span_Template_1, 2, 2, null, $c1$);
$i0$.ɵelementEnd(); $i0$.ɵelementEnd();
} }
if (rf & 2) { if (rf & 2) {
@ -279,7 +279,7 @@ describe('compiler compliance: template', () => {
function MyComponent_div_div_Template_1(rf, ctx) { function MyComponent_div_div_Template_1(rf, ctx) {
if (rf & 1) { if (rf & 1) {
$i0$.ɵelementStart(0, "div"); $i0$.ɵelementStart(0, "div");
$i0$.ɵtemplate(1, MyComponent_div_div_div_Template_1, 2, 1, null, _c0); $i0$.ɵtemplate(1, MyComponent_div_div_div_Template_1, 2, 2, null, _c0);
$i0$.ɵelementEnd(); $i0$.ɵelementEnd();
} }
if (rf & 2) { if (rf & 2) {

View File

@ -190,9 +190,6 @@ export class Identifiers {
moduleName: CORE, moduleName: CORE,
}; };
// Reserve slots for pure functions
static reserveSlots: o.ExternalReference = {name: 'ɵreserveSlots', moduleName: CORE};
// sanitization-related functions // sanitization-related functions
static sanitizeHtml: o.ExternalReference = {name: 'ɵzh', moduleName: CORE}; static sanitizeHtml: o.ExternalReference = {name: 'ɵzh', moduleName: CORE};
static sanitizeStyle: o.ExternalReference = {name: 'ɵzs', moduleName: CORE}; static sanitizeStyle: o.ExternalReference = {name: 'ɵzs', moduleName: CORE};

View File

@ -110,7 +110,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
this._valueConverter = new ValueConverter( this._valueConverter = new ValueConverter(
constantPool, () => this.allocateDataSlot(), constantPool, () => this.allocateDataSlot(),
(numSlots: number): number => this._pureFunctionSlots += numSlots, (numSlots: number) => this.allocatePureFunctionSlots(numSlots),
(name, localName, slot, value: o.ReadVarExpr) => { (name, localName, slot, value: o.ReadVarExpr) => {
const pipeType = pipeTypeByName.get(name); const pipeType = pipeTypeByName.get(name);
if (pipeType) { if (pipeType) {
@ -171,24 +171,27 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
// This is the initial pass through the nodes of this template. In this pass, we // This is the initial pass through the nodes of this template. In this pass, we
// queue all creation mode and update mode instructions for generation in the second // queue all creation mode and update mode instructions for generation in the second
// pass. It's necessary to separate the passes to ensure local refs are defined before // pass. It's necessary to separate the passes to ensure local refs are defined before
// resolving bindings. // resolving bindings. We also count bindings in this pass as we walk bound expressions.
t.visitAll(this, nodes); t.visitAll(this, nodes);
// Add total binding count to pure function count so pure function instructions are
// generated with the correct slot offset when update instructions are processed.
this._pureFunctionSlots += this._bindingSlots;
// Pipes are walked in the first pass (to enqueue `pipe()` creation instructions and
// `pipeBind` update instructions), so we have to update the slot offsets manually
// to account for bindings.
this._valueConverter.updatePipeSlotOffsets(this._bindingSlots);
// Nested templates must be processed before creation instructions so template() // Nested templates must be processed before creation instructions so template()
// instructions can be generated with the correct internal const count. // instructions can be generated with the correct internal const count.
this._nestedTemplateFns.forEach(buildTemplateFn => buildTemplateFn()); this._nestedTemplateFns.forEach(buildTemplateFn => buildTemplateFn());
// Generate all the update mode instructions (e.g. resolve property or text bindings)
const updateStatements = this._updateCodeFns.map((fn: () => o.Statement) => fn());
// Generate all the creation mode instructions (e.g. resolve bindings in listeners) // Generate all the creation mode instructions (e.g. resolve bindings in listeners)
const creationStatements = this._creationCodeFns.map((fn: () => o.Statement) => fn()); const creationStatements = this._creationCodeFns.map((fn: () => o.Statement) => fn());
// To count slots for the reserveSlots() instruction, all bindings must have been visited. // Generate all the update mode instructions (e.g. resolve property or text bindings)
if (this._pureFunctionSlots > 0) { const updateStatements = this._updateCodeFns.map((fn: () => o.Statement) => fn());
creationStatements.push(
instruction(null, R3.reserveSlots, [o.literal(this._pureFunctionSlots)]).toStmt());
}
// Variable declaration must occur after binding resolution so we can generate context // Variable declaration must occur after binding resolution so we can generate context
// instructions that build on each other. e.g. const b = x().$implicit(); const b = x(); // instructions that build on each other. e.g. const b = x().$implicit(); const b = x();
@ -635,6 +638,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
// TODO(chuckj): runtime: security context? // TODO(chuckj): runtime: security context?
const value = input.value.visit(this._valueConverter); const value = input.value.visit(this._valueConverter);
this.allocateBindingSlots(value);
this.updateInstruction(input.sourceSpan, instruction, () => { this.updateInstruction(input.sourceSpan, instruction, () => {
return [ return [
o.literal(elementIndex), o.literal(input.name), o.literal(elementIndex), o.literal(input.name),
@ -722,6 +726,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
const context = o.variable(CONTEXT_NAME); const context = o.variable(CONTEXT_NAME);
template.inputs.forEach(input => { template.inputs.forEach(input => {
const value = input.value.visit(this._valueConverter); const value = input.value.visit(this._valueConverter);
this.allocateBindingSlots(value);
this.updateInstruction(template.sourceSpan, R3.elementProperty, () => { this.updateInstruction(template.sourceSpan, R3.elementProperty, () => {
return [ return [
o.literal(templateIndex), o.literal(input.name), o.literal(templateIndex), o.literal(input.name),
@ -767,6 +772,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
this.creationInstruction(text.sourceSpan, R3.text, [o.literal(nodeIndex)]); this.creationInstruction(text.sourceSpan, R3.text, [o.literal(nodeIndex)]);
const value = text.value.visit(this._valueConverter); const value = text.value.visit(this._valueConverter);
this.allocateBindingSlots(value);
this.updateInstruction( this.updateInstruction(
text.sourceSpan, R3.textBinding, text.sourceSpan, R3.textBinding,
() => [o.literal(nodeIndex), this.convertPropertyBinding(o.variable(CONTEXT_NAME), value)]); () => [o.literal(nodeIndex), this.convertPropertyBinding(o.variable(CONTEXT_NAME), value)]);
@ -800,7 +806,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
getConstCount() { return this._dataIndex; } getConstCount() { return this._dataIndex; }
getVarCount() { return this._bindingSlots + this._pureFunctionSlots; } getVarCount() { return this._pureFunctionSlots; }
private bindingContext() { return `${this._bindingContext++}`; } private bindingContext() { return `${this._bindingContext++}`; }
@ -829,10 +835,18 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
this.instructionFn(this._updateCodeFns, span, reference, paramsOrFn || []); this.instructionFn(this._updateCodeFns, span, reference, paramsOrFn || []);
} }
private allocatePureFunctionSlots(numSlots: number): number {
const originalSlots = this._pureFunctionSlots;
this._pureFunctionSlots += numSlots;
return originalSlots;
}
private allocateBindingSlots(value: AST) {
this._bindingSlots += value instanceof Interpolation ? value.expressions.length : 1;
}
private convertPropertyBinding(implicit: o.Expression, value: AST, skipBindFn?: boolean): private convertPropertyBinding(implicit: o.Expression, value: AST, skipBindFn?: boolean):
o.Expression { o.Expression {
if (!skipBindFn) this._bindingSlots++;
const interpolationFn = const interpolationFn =
value instanceof Interpolation ? interpolate : () => error('Unexpected interpolation'); value instanceof Interpolation ? interpolate : () => error('Unexpected interpolation');
@ -875,6 +889,8 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
} }
class ValueConverter extends AstMemoryEfficientTransformer { class ValueConverter extends AstMemoryEfficientTransformer {
private _pipeBindExprs: FunctionCall[] = [];
constructor( constructor(
private constantPool: ConstantPool, private allocateSlot: () => number, private constantPool: ConstantPool, private allocateSlot: () => number,
private allocatePureFunctionSlots: (numSlots: number) => number, private allocatePureFunctionSlots: (numSlots: number) => number,
@ -897,11 +913,21 @@ class ValueConverter extends AstMemoryEfficientTransformer {
const convertedArgs: AST[] = const convertedArgs: AST[] =
isVarLength ? this.visitAll([new LiteralArray(pipe.span, args)]) : this.visitAll(args); isVarLength ? this.visitAll([new LiteralArray(pipe.span, args)]) : this.visitAll(args);
return new FunctionCall(pipe.span, target, [ const pipeBindExpr = new FunctionCall(pipe.span, target, [
new LiteralPrimitive(pipe.span, slot), new LiteralPrimitive(pipe.span, slot),
new LiteralPrimitive(pipe.span, pureFunctionSlot), new LiteralPrimitive(pipe.span, pureFunctionSlot),
...convertedArgs, ...convertedArgs,
]); ]);
this._pipeBindExprs.push(pipeBindExpr);
return pipeBindExpr;
}
updatePipeSlotOffsets(bindingSlots: number) {
this._pipeBindExprs.forEach((pipe: FunctionCall) => {
// update the slot offset arg (index 1) to account for binding slots
const slotOffset = pipe.args[1] as LiteralPrimitive;
(slotOffset.value as number) += bindingSlots;
});
} }
visitLiteralArray(array: LiteralArray, context: any): AST { visitLiteralArray(array: LiteralArray, context: any): AST {

View File

@ -87,7 +87,6 @@ export {
elementProperty as ɵelementProperty, elementProperty as ɵelementProperty,
projectionDef as ɵprojectionDef, projectionDef as ɵprojectionDef,
reference as ɵreference, reference as ɵreference,
reserveSlots as ɵreserveSlots,
elementAttribute as ɵelementAttribute, elementAttribute as ɵelementAttribute,
elementStyling as ɵelementStyling, elementStyling as ɵelementStyling,
elementStylingMap as ɵelementStylingMap, elementStylingMap as ɵelementStylingMap,

View File

@ -76,8 +76,6 @@ export {
reference, reference,
reserveSlots,
embeddedViewStart, embeddedViewStart,
embeddedViewEnd, embeddedViewEnd,
detectChanges, detectChanges,

View File

@ -2559,9 +2559,6 @@ export function bind<T>(value: T): T|NO_CHANGE {
return bindingUpdated(viewData[BINDING_INDEX]++, value) ? value : NO_CHANGE; return bindingUpdated(viewData[BINDING_INDEX]++, value) ? value : NO_CHANGE;
} }
// TODO(kara): Remove this when updating the compiler (cannot remove without breaking JIT test)
export function reserveSlots(numSlots: number) {}
/** /**
* Create interpolation bindings with a variable number of expressions. * Create interpolation bindings with a variable number of expressions.
* *

View File

@ -90,7 +90,6 @@ export const angularCoreEnv: {[name: string]: Function} = {
'ɵquery': r3.query, 'ɵquery': r3.query,
'ɵqueryRefresh': r3.queryRefresh, 'ɵqueryRefresh': r3.queryRefresh,
'ɵregisterContentQuery': r3.registerContentQuery, 'ɵregisterContentQuery': r3.registerContentQuery,
'ɵreserveSlots': r3.reserveSlots,
'ɵreference': r3.reference, 'ɵreference': r3.reference,
'ɵelementStyling': r3.elementStyling, 'ɵelementStyling': r3.elementStyling,
'ɵelementStylingMap': r3.elementStylingMap, 'ɵelementStylingMap': r3.elementStylingMap,

View File

@ -68,7 +68,7 @@ function getPipeDef(name: string, registry: PipeDefList | null): PipeDefInternal
* the pipe only when an input to the pipe changes. * the pipe only when an input to the pipe changes.
* *
* @param index Pipe index where the pipe was stored on creation. * @param index Pipe index where the pipe was stored on creation.
* @param slotOffset the offset in the reserved slot space {@link reserveSlots} * @param slotOffset the offset in the reserved slot space
* @param v1 1st argument to {@link PipeTransform#transform}. * @param v1 1st argument to {@link PipeTransform#transform}.
*/ */
export function pipeBind1(index: number, slotOffset: number, v1: any): any { export function pipeBind1(index: number, slotOffset: number, v1: any): any {
@ -84,7 +84,7 @@ export function pipeBind1(index: number, slotOffset: number, v1: any): any {
* the pipe only when an input to the pipe changes. * the pipe only when an input to the pipe changes.
* *
* @param index Pipe index where the pipe was stored on creation. * @param index Pipe index where the pipe was stored on creation.
* @param slotOffset the offset in the reserved slot space {@link reserveSlots} * @param slotOffset the offset in the reserved slot space
* @param v1 1st argument to {@link PipeTransform#transform}. * @param v1 1st argument to {@link PipeTransform#transform}.
* @param v2 2nd argument to {@link PipeTransform#transform}. * @param v2 2nd argument to {@link PipeTransform#transform}.
*/ */
@ -101,7 +101,7 @@ export function pipeBind2(index: number, slotOffset: number, v1: any, v2: any):
* the pipe only when an input to the pipe changes. * the pipe only when an input to the pipe changes.
* *
* @param index Pipe index where the pipe was stored on creation. * @param index Pipe index where the pipe was stored on creation.
* @param slotOffset the offset in the reserved slot space {@link reserveSlots} * @param slotOffset the offset in the reserved slot space
* @param v1 1st argument to {@link PipeTransform#transform}. * @param v1 1st argument to {@link PipeTransform#transform}.
* @param v2 2nd argument to {@link PipeTransform#transform}. * @param v2 2nd argument to {@link PipeTransform#transform}.
* @param v3 4rd argument to {@link PipeTransform#transform}. * @param v3 4rd argument to {@link PipeTransform#transform}.
@ -120,7 +120,7 @@ export function pipeBind3(index: number, slotOffset: number, v1: any, v2: any, v
* the pipe only when an input to the pipe changes. * the pipe only when an input to the pipe changes.
* *
* @param index Pipe index where the pipe was stored on creation. * @param index Pipe index where the pipe was stored on creation.
* @param slotOffset the offset in the reserved slot space {@link reserveSlots} * @param slotOffset the offset in the reserved slot space
* @param v1 1st argument to {@link PipeTransform#transform}. * @param v1 1st argument to {@link PipeTransform#transform}.
* @param v2 2nd argument to {@link PipeTransform#transform}. * @param v2 2nd argument to {@link PipeTransform#transform}.
* @param v3 3rd argument to {@link PipeTransform#transform}. * @param v3 3rd argument to {@link PipeTransform#transform}.
@ -141,7 +141,7 @@ export function pipeBind4(
* the pipe only when an input to the pipe changes. * the pipe only when an input to the pipe changes.
* *
* @param index Pipe index where the pipe was stored on creation. * @param index Pipe index where the pipe was stored on creation.
* @param slotOffset the offset in the reserved slot space {@link reserveSlots} * @param slotOffset the offset in the reserved slot space
* @param values Array of arguments to pass to {@link PipeTransform#transform} method. * @param values Array of arguments to pass to {@link PipeTransform#transform} method.
*/ */
export function pipeBindV(index: number, slotOffset: number, values: any[]): any { export function pipeBindV(index: number, slotOffset: number, values: any[]): any {