perf(ivy): chain styling instructions (#33837)
Adds support for chaining of `styleProp`, `classProp` and `stylePropInterpolateX` instructions whenever possible which should help generate less code. Note that one complication here is for `stylePropInterpolateX` instructions where we have to break into multiple chains if there are other styling instructions inbetween the interpolations which helps maintain the execution order. PR Close #33837
This commit is contained in:

committed by
Alex Rickabaugh

parent
f69c6e204a
commit
8a052dc858
@ -708,8 +708,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
const limit = stylingInstructions.length - 1;
|
||||
for (let i = 0; i <= limit; i++) {
|
||||
const instruction = stylingInstructions[i];
|
||||
this._bindingSlots += instruction.allocateBindingSlots;
|
||||
this.processStylingInstruction(elementIndex, instruction, false);
|
||||
this._bindingSlots += this.processStylingUpdateInstruction(elementIndex, instruction);
|
||||
}
|
||||
|
||||
// the reason why `undefined` is used is because the renderer understands this as a
|
||||
@ -1071,25 +1070,30 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
});
|
||||
}
|
||||
|
||||
private processStylingInstruction(
|
||||
elementIndex: number, instruction: StylingInstruction|null, createMode: boolean) {
|
||||
private processStylingUpdateInstruction(
|
||||
elementIndex: number, instruction: StylingInstruction|null) {
|
||||
let allocateBindingSlots = 0;
|
||||
if (instruction) {
|
||||
if (createMode) {
|
||||
this.creationInstruction(instruction.sourceSpan, instruction.reference, () => {
|
||||
return instruction.params(value => this.convertPropertyBinding(value)) as o.Expression[];
|
||||
});
|
||||
} else {
|
||||
this.updateInstructionWithAdvance(
|
||||
elementIndex, instruction.sourceSpan, instruction.reference, () => {
|
||||
return instruction
|
||||
.params(value => {
|
||||
return (instruction.supportsInterpolation && value instanceof Interpolation) ?
|
||||
const calls: ChainableBindingInstruction[] = [];
|
||||
|
||||
instruction.calls.forEach(call => {
|
||||
allocateBindingSlots += call.allocateBindingSlots;
|
||||
calls.push({
|
||||
sourceSpan: call.sourceSpan,
|
||||
value: () => {
|
||||
return call
|
||||
.params(
|
||||
value => (call.supportsInterpolation && value instanceof Interpolation) ?
|
||||
this.getUpdateInstructionArguments(value) :
|
||||
this.convertPropertyBinding(value);
|
||||
}) as o.Expression[];
|
||||
});
|
||||
}
|
||||
this.convertPropertyBinding(value)) as o.Expression[];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.updateInstructionChainWithAdvance(elementIndex, instruction.reference, calls);
|
||||
}
|
||||
|
||||
return allocateBindingSlots;
|
||||
}
|
||||
|
||||
private creationInstruction(
|
||||
@ -1127,8 +1131,13 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
|
||||
this._updateCodeFns.push(() => {
|
||||
const calls = bindings.map(property => {
|
||||
const fnParams = [property.value(), ...(property.params || [])];
|
||||
const value = property.value();
|
||||
const fnParams = Array.isArray(value) ? value : [value];
|
||||
if (property.params) {
|
||||
fnParams.push(...property.params);
|
||||
}
|
||||
if (property.name) {
|
||||
// We want the property name to always be the first function parameter.
|
||||
fnParams.unshift(o.literal(property.name));
|
||||
}
|
||||
return fnParams;
|
||||
@ -2045,7 +2054,7 @@ function hasTextChildrenOnly(children: t.Node[]): boolean {
|
||||
interface ChainableBindingInstruction {
|
||||
name?: string;
|
||||
sourceSpan: ParseSourceSpan|null;
|
||||
value: () => o.Expression;
|
||||
value: () => o.Expression | o.Expression[];
|
||||
params?: any[];
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user