perf(ivy): chain host binding instructions (#31296)
Adds chaining to the `property`, `attribute` and `updateSyntheticHostBinding` instructions when they're used in a host binding. This PR resolves FW-1404. PR Close #31296
This commit is contained in:

committed by
Alex Rickabaugh

parent
c6b29f4c6d
commit
81332150aa
@ -30,7 +30,7 @@ import {prepareSyntheticListenerFunctionName, prepareSyntheticPropertyName, type
|
||||
import {R3ComponentDef, R3ComponentMetadata, R3DirectiveDef, R3DirectiveMetadata, R3HostMetadata, R3QueryMetadata} from './api';
|
||||
import {Instruction, StylingBuilder} from './styling_builder';
|
||||
import {BindingScope, TemplateDefinitionBuilder, ValueConverter, makeBindingParser, prepareEventListenerParameters, renderFlagCheckIfStmt, resolveSanitizationFn} from './template';
|
||||
import {CONTEXT_NAME, DefinitionMap, RENDER_FLAGS, TEMPORARY_NAME, asLiteral, conditionallyCreateMapObjectLiteral, getQueryPredicate, temporaryAllocator} from './util';
|
||||
import {CONTEXT_NAME, DefinitionMap, RENDER_FLAGS, TEMPORARY_NAME, asLiteral, chainedInstruction, conditionallyCreateMapObjectLiteral, getQueryPredicate, temporaryAllocator} from './util';
|
||||
|
||||
const EMPTY_ARRAY: any[] = [];
|
||||
|
||||
@ -638,6 +638,10 @@ function createHostBindingsFunction(
|
||||
|
||||
// Calculate the host property bindings
|
||||
const bindings = bindingParser.createBoundHostProperties(directiveSummary, hostBindingSourceSpan);
|
||||
const propertyBindings: o.Expression[][] = [];
|
||||
const attributeBindings: o.Expression[][] = [];
|
||||
const syntheticHostBindings: o.Expression[][] = [];
|
||||
|
||||
(bindings || []).forEach((binding: ParsedProperty) => {
|
||||
const name = binding.name;
|
||||
const stylingInputWasSet =
|
||||
@ -681,10 +685,32 @@ function createHostBindingsFunction(
|
||||
}
|
||||
|
||||
updateStatements.push(...bindingExpr.stmts);
|
||||
updateStatements.push(o.importExpr(instruction).callFn(instructionParams).toStmt());
|
||||
|
||||
if (instruction === R3.property) {
|
||||
propertyBindings.push(instructionParams);
|
||||
} else if (instruction === R3.attribute) {
|
||||
attributeBindings.push(instructionParams);
|
||||
} else if (instruction === R3.updateSyntheticHostBinding) {
|
||||
syntheticHostBindings.push(instructionParams);
|
||||
} else {
|
||||
updateStatements.push(o.importExpr(instruction).callFn(instructionParams).toStmt());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (propertyBindings.length > 0) {
|
||||
updateStatements.push(chainedInstruction(R3.property, propertyBindings).toStmt());
|
||||
}
|
||||
|
||||
if (attributeBindings.length > 0) {
|
||||
updateStatements.push(chainedInstruction(R3.attribute, attributeBindings).toStmt());
|
||||
}
|
||||
|
||||
if (syntheticHostBindings.length > 0) {
|
||||
updateStatements.push(
|
||||
chainedInstruction(R3.updateSyntheticHostBinding, syntheticHostBindings).toStmt());
|
||||
}
|
||||
|
||||
// since we're dealing with directives/components and both have hostBinding
|
||||
// functions, we need to generate a special hostAttrs instruction that deals
|
||||
// with both the assignment of styling as well as static attributes to the host
|
||||
|
@ -37,7 +37,8 @@ import {I18nMetaVisitor} from './i18n/meta';
|
||||
import {getSerializedI18nContent} from './i18n/serializer';
|
||||
import {I18N_ICU_MAPPING_PREFIX, TRANSLATION_PREFIX, assembleBoundTextPlaceholders, assembleI18nBoundString, formatI18nPlaceholderName, getTranslationConstPrefix, getTranslationDeclStmts, icuFromI18nMessage, isI18nRootNode, isSingleI18nIcu, metaFromI18nMessage, placeholdersToParams, wrapI18nPlaceholder} from './i18n/util';
|
||||
import {Instruction, StylingBuilder} from './styling_builder';
|
||||
import {CONTEXT_NAME, IMPLICIT_REFERENCE, NON_BINDABLE_ATTR, REFERENCE_PREFIX, RENDER_FLAGS, asLiteral, getAttrsForDirectiveMatching, invalid, trimTrailingNulls, unsupported} from './util';
|
||||
import {CONTEXT_NAME, IMPLICIT_REFERENCE, NON_BINDABLE_ATTR, REFERENCE_PREFIX, RENDER_FLAGS, asLiteral, chainedInstruction, getAttrsForDirectiveMatching, invalid, trimTrailingNulls, unsupported} from './util';
|
||||
|
||||
|
||||
|
||||
// Selector attribute name of `<ng-content>`
|
||||
@ -1105,7 +1106,7 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
|
||||
return fnParams;
|
||||
});
|
||||
|
||||
return chainedInstruction(span, reference, calls).toStmt();
|
||||
return chainedInstruction(reference, calls, span).toStmt();
|
||||
});
|
||||
}
|
||||
|
||||
@ -1417,22 +1418,6 @@ function instruction(
|
||||
return o.importExpr(reference, null, span).callFn(params, span);
|
||||
}
|
||||
|
||||
function chainedInstruction(
|
||||
span: ParseSourceSpan | null, reference: o.ExternalReference, calls: o.Expression[][]) {
|
||||
let expression = o.importExpr(reference, null, span) as o.Expression;
|
||||
|
||||
if (calls.length > 0) {
|
||||
for (let i = 0; i < calls.length; i++) {
|
||||
expression = expression.callFn(calls[i], span);
|
||||
}
|
||||
} else {
|
||||
// Add a blank invocation, in case the `calls` array is empty.
|
||||
expression = expression.callFn([], span);
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
// e.g. x(2);
|
||||
function generateNextContextExpr(relativeLevelDiff: number): o.Expression {
|
||||
return o.importExpr(R3.nextContext)
|
||||
|
@ -8,11 +8,14 @@
|
||||
|
||||
import {ConstantPool} from '../../constant_pool';
|
||||
import * as o from '../../output/output_ast';
|
||||
import {ParseSourceSpan} from '../../parse_util';
|
||||
import {splitAtColon} from '../../util';
|
||||
import * as t from '../r3_ast';
|
||||
|
||||
import {R3QueryMetadata} from './api';
|
||||
import {isI18nAttribute} from './i18n/util';
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in
|
||||
* quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may
|
||||
@ -181,3 +184,20 @@ export function getAttrsForDirectiveMatching(elOrTpl: t.Element | t.Template):
|
||||
|
||||
return attributesMap;
|
||||
}
|
||||
|
||||
/** Returns a call expression to a chained instruction, e.g. `property(params[0])(params[1])`. */
|
||||
export function chainedInstruction(
|
||||
reference: o.ExternalReference, calls: o.Expression[][], span?: ParseSourceSpan | null) {
|
||||
let expression = o.importExpr(reference, null, span) as o.Expression;
|
||||
|
||||
if (calls.length > 0) {
|
||||
for (let i = 0; i < calls.length; i++) {
|
||||
expression = expression.callFn(calls[i], span);
|
||||
}
|
||||
} else {
|
||||
// Add a blank invocation, in case the `calls` array is empty.
|
||||
expression = expression.callFn([], span);
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
Reference in New Issue
Block a user