perf(ivy): chain multiple i18nExp calls (#31258)
				
					
				
			Implement function chaining for `i18nExp` to reduce the output size. FW-1391 #resolve PR Close #31258
This commit is contained in:
		
							parent
							
								
									3846192bde
								
							
						
					
					
						commit
						ef9cb6a034
					
				| @ -464,14 +464,10 @@ describe('i18n support in the view compiler', () => { | ||||
|             $r3$.ɵɵelementEnd(); | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(1, 6, ctx.valueA)); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueB); | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(1, 6, ctx.valueA))(ctx.valueB); | ||||
|             $r3$.ɵɵi18nApply(2); | ||||
|             $r3$.ɵɵselect(3); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueA); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueB); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueA + ctx.valueB); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueC); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueA)(ctx.valueB)(ctx.valueA + ctx.valueB)(ctx.valueC); | ||||
|             $r3$.ɵɵi18nApply(4); | ||||
|           } | ||||
|         } | ||||
| @ -690,14 +686,10 @@ describe('i18n support in the view compiler', () => { | ||||
|             $r3$.ɵɵelementEnd(); | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(1, 6, ctx.valueA)); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueB); | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(1, 6, ctx.valueA))(ctx.valueB); | ||||
|             $r3$.ɵɵi18nApply(2); | ||||
|             $r3$.ɵɵselect(3); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueA); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueB); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueA + ctx.valueB); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueC); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueA)(ctx.valueB)(ctx.valueA + ctx.valueB)(ctx.valueC); | ||||
|             $r3$.ɵɵi18nApply(4); | ||||
|           } | ||||
|         } | ||||
| @ -1054,8 +1046,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵselect(1); | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(2, 2, ctx.valueA)); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueA == null ? null : ctx.valueA.a == null ? null : ctx.valueA.a.b); | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(2, 2, ctx.valueA))(ctx.valueA == null ? null : ctx.valueA.a == null ? null : ctx.valueA.a.b); | ||||
|             $r3$.ɵɵi18nApply(1); | ||||
|           } | ||||
|         } | ||||
| @ -1224,8 +1215,7 @@ describe('i18n support in the view compiler', () => { | ||||
|             $r3$.ɵɵi18nExp(ctx.one); | ||||
|             $r3$.ɵɵi18nApply(1); | ||||
|             $r3$.ɵɵselect(4); | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(5, 3, ctx.two)); | ||||
|             $r3$.ɵɵi18nExp(ctx.nestedInBlockTwo); | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(5, 3, ctx.two))(ctx.nestedInBlockTwo); | ||||
|             $r3$.ɵɵi18nApply(4); | ||||
|           } | ||||
|         } | ||||
| @ -1335,8 +1325,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵselect(2); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueB); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueC); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueB)(ctx.valueC); | ||||
|             $r3$.ɵɵi18nApply(3); | ||||
|             $r3$.ɵɵi18nExp(ctx.valueA); | ||||
|             $r3$.ɵɵi18nApply(1); | ||||
| @ -1402,8 +1391,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           if (rf & 2) { | ||||
|             const $ctx_r0$ = $r3$.ɵɵnextContext(); | ||||
|             $r3$.ɵɵselect(2); | ||||
|             $r3$.ɵɵi18nExp($ctx_r0$.valueA); | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(4, 2, $ctx_r0$.valueB)); | ||||
|             $r3$.ɵɵi18nExp($ctx_r0$.valueA)($r3$.ɵɵpipeBind1(4, 2, $ctx_r0$.valueB)); | ||||
|             $r3$.ɵɵi18nApply(2); | ||||
|           } | ||||
|         } | ||||
| @ -1527,8 +1515,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             const $ctx_r2$ = $r3$.ɵɵnextContext(2); | ||||
|             $r3$.ɵɵi18nExp($ctx_r2$.valueC); | ||||
|             $r3$.ɵɵi18nExp($ctx_r2$.valueD); | ||||
|             $r3$.ɵɵi18nExp($ctx_r2$.valueC)($ctx_r2$.valueD); | ||||
|             $r3$.ɵɵi18nApply(0); | ||||
|           } | ||||
|         } | ||||
| @ -1547,8 +1534,7 @@ describe('i18n support in the view compiler', () => { | ||||
|             const $ctx_r0$ = $r3$.ɵɵnextContext(); | ||||
|             $r3$.ɵɵselect(4); | ||||
|             $r3$.ɵɵproperty("ngIf", $ctx_r0$.exists); | ||||
|             $r3$.ɵɵi18nExp($ctx_r0$.valueA); | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(3, 3, $ctx_r0$.valueB)); | ||||
|             $r3$.ɵɵi18nExp($ctx_r0$.valueA)($r3$.ɵɵpipeBind1(3, 3, $ctx_r0$.valueB)); | ||||
|             $r3$.ɵɵi18nApply(0); | ||||
|           } | ||||
|         } | ||||
| @ -1596,8 +1582,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             const $ctx_r1$ = $r3$.ɵɵnextContext(); | ||||
|             $r3$.ɵɵi18nExp($ctx_r1$.valueE + $ctx_r1$.valueF); | ||||
|             $r3$.ɵɵi18nExp($r3$.ɵɵpipeBind1(3, 2, $ctx_r1$.valueG)); | ||||
|             $r3$.ɵɵi18nExp($ctx_r1$.valueE + $ctx_r1$.valueF)($r3$.ɵɵpipeBind1(3, 2, $ctx_r1$.valueG)); | ||||
|             $r3$.ɵɵi18nApply(0); | ||||
|           } | ||||
|         } | ||||
| @ -2554,8 +2539,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           if (rf & 2) { | ||||
|             const $ctx_r1$ = $r3$.ɵɵnextContext(); | ||||
|             $r3$.ɵɵselect(2); | ||||
|             $r3$.ɵɵi18nExp($ctx_r1$.count); | ||||
|             $r3$.ɵɵi18nExp($ctx_r1$.count); | ||||
|             $r3$.ɵɵi18nExp($ctx_r1$.count)($ctx_r1$.count); | ||||
|             $r3$.ɵɵi18nApply(2); | ||||
|           } | ||||
|         } | ||||
| @ -2615,8 +2599,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵselect(1); | ||||
|             $r3$.ɵɵi18nExp(ctx.age); | ||||
|             $r3$.ɵɵi18nExp(ctx.other); | ||||
|             $r3$.ɵɵi18nExp(ctx.age)(ctx.other); | ||||
|             $r3$.ɵɵi18nApply(1); | ||||
|           } | ||||
|         } | ||||
| @ -2742,8 +2725,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵselect(1); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender); | ||||
|             $r3$.ɵɵi18nExp(ctx.ageA + ctx.ageB + ctx.ageC); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender)(ctx.ageA + ctx.ageB + ctx.ageC); | ||||
|             $r3$.ɵɵi18nApply(1); | ||||
|           } | ||||
|         } | ||||
| @ -2808,8 +2790,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵselect(1); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender); | ||||
|             $r3$.ɵɵi18nExp(ctx.age); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender)(ctx.age); | ||||
|             $r3$.ɵɵi18nApply(1); | ||||
|           } | ||||
|         } | ||||
| @ -2914,8 +2895,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵselect(3); | ||||
|             $r3$.ɵɵproperty("ngIf", ctx.visible); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender)(ctx.gender); | ||||
|             $r3$.ɵɵi18nApply(1); | ||||
|           } | ||||
|         } | ||||
| @ -2962,8 +2942,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵselect(1); | ||||
|             $r3$.ɵɵi18nExp(ctx.age); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender); | ||||
|             $r3$.ɵɵi18nExp(ctx.age)(ctx.gender); | ||||
|             $r3$.ɵɵi18nApply(1); | ||||
|           } | ||||
|         } | ||||
| @ -3132,8 +3111,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             const $ctx_r0$ = $r3$.ɵɵnextContext(); | ||||
|             $r3$.ɵɵi18nExp($ctx_r0$.age); | ||||
|             $r3$.ɵɵi18nExp($ctx_r0$.otherAge); | ||||
|             $r3$.ɵɵi18nExp($ctx_r0$.age)($ctx_r0$.otherAge); | ||||
|             $r3$.ɵɵi18nApply(0); | ||||
|           } | ||||
|         } | ||||
| @ -3151,9 +3129,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵselect(2); | ||||
|             $r3$.ɵɵproperty("ngIf", ctx.ageVisible); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender); | ||||
|             $r3$.ɵɵi18nExp(ctx.weight); | ||||
|             $r3$.ɵɵi18nExp(ctx.height); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender)(ctx.weight)(ctx.height); | ||||
|             $r3$.ɵɵi18nApply(1); | ||||
|           } | ||||
|         } | ||||
| @ -3204,10 +3180,7 @@ describe('i18n support in the view compiler', () => { | ||||
|           } | ||||
|           if (rf & 2) { | ||||
|             $r3$.ɵɵselect(1); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender); | ||||
|             $r3$.ɵɵi18nExp(ctx.weight); | ||||
|             $r3$.ɵɵi18nExp(ctx.height); | ||||
|             $r3$.ɵɵi18nExp(ctx.age); | ||||
|             $r3$.ɵɵi18nExp(ctx.gender)(ctx.weight)(ctx.height)(ctx.age); | ||||
|             $r3$.ɵɵi18nApply(1); | ||||
|           } | ||||
|         } | ||||
|  | ||||
| @ -456,10 +456,14 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver | ||||
|     // setup accumulated bindings
 | ||||
|     const {index, bindings} = this.i18n; | ||||
|     if (bindings.size) { | ||||
|       const chainBindings: ChainableBindingInstruction[] = []; | ||||
|       bindings.forEach(binding => { | ||||
|         this.updateInstruction( | ||||
|             index, span, R3.i18nExp, () => [this.convertPropertyBinding(binding)]); | ||||
|         chainBindings.push({ | ||||
|           sourceSpan: span, | ||||
|           value: () => this.convertPropertyBinding(binding) | ||||
|         }); | ||||
|       }); | ||||
|       this.updateInstructionChain(index, R3.i18nExp, chainBindings); | ||||
|       this.updateInstruction(index, span, R3.i18nApply, [o.literal(index)]); | ||||
|     } | ||||
|     if (!selfClosing) { | ||||
| @ -641,6 +645,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver | ||||
|       if (i18nAttrs.length) { | ||||
|         let hasBindings: boolean = false; | ||||
|         const i18nAttrArgs: o.Expression[] = []; | ||||
|         const bindings: ChainableBindingInstruction[] = []; | ||||
|         i18nAttrs.forEach(attr => { | ||||
|           const message = attr.i18n !as i18n.Message; | ||||
|           if (attr instanceof t.TextAttribute) { | ||||
| @ -654,13 +659,17 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver | ||||
|               i18nAttrArgs.push(o.literal(attr.name), this.i18nTranslate(message, params)); | ||||
|               converted.expressions.forEach(expression => { | ||||
|                 hasBindings = true; | ||||
|                 this.updateInstruction( | ||||
|                     elementIndex, element.sourceSpan, R3.i18nExp, | ||||
|                     () => [this.convertExpressionBinding(expression)]); | ||||
|                 bindings.push({ | ||||
|                   sourceSpan: element.sourceSpan, | ||||
|                   value: () => this.convertExpressionBinding(expression) | ||||
|                 }); | ||||
|               }); | ||||
|             } | ||||
|           } | ||||
|         }); | ||||
|         if (bindings.length) { | ||||
|           this.updateInstructionChain(elementIndex, R3.i18nExp, bindings); | ||||
|         } | ||||
|         if (i18nAttrArgs.length) { | ||||
|           const index: o.Expression = o.literal(this.allocateDataSlot()); | ||||
|           const args = this.constantPool.getConstLiteral(o.literalArr(i18nAttrArgs), true); | ||||
| @ -733,7 +742,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver | ||||
| 
 | ||||
|         propertyBindings.push({ | ||||
|           name: prepareSyntheticPropertyName(input.name), | ||||
|           input, | ||||
|           sourceSpan: input.sourceSpan, | ||||
|           value: () => hasValue ? this.convertPropertyBinding(value) : emptyValueBindInstruction | ||||
|         }); | ||||
|       } else { | ||||
| @ -771,7 +780,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver | ||||
|               // [prop]="value"
 | ||||
|               // Collect all the properties so that we can chain into a single function at the end.
 | ||||
|               propertyBindings.push( | ||||
|                   {name: attrName, input, value: () => this.convertPropertyBinding(value), params}); | ||||
|                   {name: attrName, sourceSpan: input.sourceSpan, value: () => this.convertPropertyBinding(value), params}); | ||||
|             } | ||||
|           } else if (inputType === BindingType.Attribute) { | ||||
|             if (value instanceof Interpolation && getInterpolationArgsLength(value) > 1) { | ||||
| @ -785,7 +794,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver | ||||
|               // Collect the attribute bindings so that they can be chained at the end.
 | ||||
|               attributeBindings.push({ | ||||
|                 name: attrName, | ||||
|                 input, | ||||
|                 sourceSpan: input.sourceSpan, | ||||
|                 value: () => this.convertPropertyBinding(boundValue), params | ||||
|               }); | ||||
|             } | ||||
| @ -830,18 +839,6 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Adds an update instruction for a bound property or attribute, such as `[prop]="value"` or | ||||
|    * `[attr.title]="value"` | ||||
|    */ | ||||
|   boundUpdateInstruction( | ||||
|       instruction: o.ExternalReference, elementIndex: number, attrName: string, | ||||
|       input: t.BoundAttribute, value: any, params: any[]) { | ||||
|     this.updateInstruction(elementIndex, input.sourceSpan, instruction, () => { | ||||
|       return [o.literal(attrName), this.convertPropertyBinding(value), ...params]; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Adds an update instruction for an interpolated property or attribute, such as | ||||
|    * `prop="{{value}}"` or `attr.title="{{value}}"` | ||||
| @ -1042,7 +1039,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver | ||||
|         if (value !== undefined) { | ||||
|           this.allocateBindingSlots(value); | ||||
|           propertyBindings.push( | ||||
|               {name: input.name, input, value: () => this.convertPropertyBinding(value)}); | ||||
|               {name: input.name, sourceSpan: input.sourceSpan, value: () => this.convertPropertyBinding(value)}); | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
| @ -1093,12 +1090,17 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver | ||||
| 
 | ||||
|   private updateInstructionChain( | ||||
|       nodeIndex: number, reference: o.ExternalReference, bindings: ChainableBindingInstruction[]) { | ||||
|     const span = bindings.length ? bindings[0].input.sourceSpan : null; | ||||
|     const span = bindings.length ? bindings[0].sourceSpan : null; | ||||
| 
 | ||||
|     this.addSelectInstructionIfNecessary(nodeIndex, span); | ||||
|     this._updateCodeFns.push(() => { | ||||
|       const calls = bindings.map( | ||||
|           property => [o.literal(property.name), property.value(), ...(property.params || [])]); | ||||
|       const calls = bindings.map(property => { | ||||
|         const fnParams = [property.value(), ...(property.params || [])]; | ||||
|         if (property.name) { | ||||
|           fnParams.unshift(o.literal(property.name)); | ||||
|         } | ||||
|         return fnParams; | ||||
|       }); | ||||
| 
 | ||||
|       return chainedInstruction(span, reference, calls).toStmt(); | ||||
|     }); | ||||
| @ -2027,8 +2029,8 @@ function hasTextChildrenOnly(children: t.Node[]): boolean { | ||||
| } | ||||
| 
 | ||||
| interface ChainableBindingInstruction { | ||||
|   name: string; | ||||
|   input: t.BoundAttribute; | ||||
|   name?: string; | ||||
|   sourceSpan: ParseSourceSpan|null; | ||||
|   value: () => o.Expression; | ||||
|   params?: any[]; | ||||
| } | ||||
|  | ||||
| @ -16,7 +16,7 @@ import {assertDataInRange, assertDefined, assertEqual, assertGreaterThan} from ' | ||||
| import {attachPatchData} from './context_discovery'; | ||||
| import {bind, setDelayProjection, ɵɵload} from './instructions/all'; | ||||
| import {attachI18nOpCodesDebug} from './instructions/lview_debug'; | ||||
| import {allocExpando, elementAttributeInternal, elementPropertyInternal, getOrCreateTNode, setInputsForProperty, textBindingInternal} from './instructions/shared'; | ||||
| import {allocExpando, elementAttributeInternal, elementPropertyInternal, getOrCreateTNode, setInputsForProperty, textBindingInternal, TsickleIssue1009} from './instructions/shared'; | ||||
| import {LContainer, NATIVE} from './interfaces/container'; | ||||
| import {COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuType, TI18n, TIcu} from './interfaces/i18n'; | ||||
| import {TElementNode, TIcuContainerNode, TNode, TNodeFlags, TNodeType, TProjectionNode} from './interfaces/node'; | ||||
| @ -1012,16 +1012,19 @@ let shiftsCounter = 0; | ||||
|  * update the translated nodes. | ||||
|  * | ||||
|  * @param value The binding's value | ||||
|  * @returns This function returns itself so that it may be chained | ||||
|  * (e.g. `i18nExp(ctx.name)(ctx.title)`) | ||||
|  * | ||||
|  * @codeGenApi | ||||
|  */ | ||||
| export function ɵɵi18nExp<T>(value: T): void { | ||||
| export function ɵɵi18nExp<T>(value: T): TsickleIssue1009 { | ||||
|   const lView = getLView(); | ||||
|   const expression = bind(lView, value); | ||||
|   if (expression !== NO_CHANGE) { | ||||
|     changeMask = changeMask | (1 << shiftsCounter); | ||||
|   } | ||||
|   shiftsCounter++; | ||||
|   return ɵɵi18nExp; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  | ||||
							
								
								
									
										2
									
								
								tools/public_api_guard/core/core.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								tools/public_api_guard/core/core.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -851,7 +851,7 @@ export declare function ɵɵi18nAttributes(index: number, values: string[]): voi | ||||
| 
 | ||||
| export declare function ɵɵi18nEnd(): void; | ||||
| 
 | ||||
| export declare function ɵɵi18nExp<T>(value: T): void; | ||||
| export declare function ɵɵi18nExp<T>(value: T): TsickleIssue1009; | ||||
| 
 | ||||
| /** @deprecated */ | ||||
| export declare function ɵɵi18nLocalize(input: string, placeholders?: { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user