feat(ivy): render flags support in host bindings function (FW-649) (#27204)
PR Close #27204
This commit is contained in:

committed by
Misko Hevery

parent
bf71b107b3
commit
dc300c5c41
@ -49,11 +49,6 @@ export interface R3ConstructorFactoryMetadata {
|
||||
* function could be different, and other options control how it will be invoked.
|
||||
*/
|
||||
injectFn: o.ExternalReference;
|
||||
|
||||
/**
|
||||
* Function that allows extra statements to be inserted into factory function.
|
||||
*/
|
||||
extraStatementFn: ((instance: o.Expression) => o.Statement[])|null;
|
||||
}
|
||||
|
||||
export enum R3FactoryDelegateType {
|
||||
@ -208,22 +203,10 @@ export function compileFactoryFunction(meta: R3FactoryMetadata):
|
||||
} else if (isExpressionFactoryMetadata(meta)) {
|
||||
// TODO(alxhub): decide whether to lower the value here or in the caller
|
||||
retExpr = makeConditionalFactory(meta.expression);
|
||||
} else if (meta.extraStatementFn) {
|
||||
// if extraStatementsFn is specified and the 'makeConditionalFactory' function
|
||||
// was not invoked, we need to create a reference to the instance, so we can
|
||||
// pass it as an argument to the 'extraStatementFn' function while calling it
|
||||
const variable = o.variable('f');
|
||||
body.push(variable.set(ctorExpr).toDeclStmt());
|
||||
retExpr = variable;
|
||||
} else {
|
||||
retExpr = ctorExpr;
|
||||
}
|
||||
|
||||
if (meta.extraStatementFn) {
|
||||
const extraStmts = meta.extraStatementFn(retExpr);
|
||||
body.push(...extraStmts);
|
||||
}
|
||||
|
||||
return {
|
||||
factory: o.fn(
|
||||
[new o.FnParam('t', o.DYNAMIC_TYPE)], [...body, new o.ReturnStatement(retExpr)],
|
||||
|
@ -101,7 +101,6 @@ export function compileInjector(meta: R3InjectorMetadata): R3InjectorDef {
|
||||
type: meta.type,
|
||||
deps: meta.deps,
|
||||
injectFn: R3.inject,
|
||||
extraStatementFn: null,
|
||||
});
|
||||
const expression = o.importExpr(R3.defineInjector).callFn([mapToMapExpression({
|
||||
factory: result.factory,
|
||||
|
@ -43,7 +43,6 @@ export function compilePipeFromMetadata(metadata: R3PipeMetadata) {
|
||||
type: metadata.type,
|
||||
deps: metadata.deps,
|
||||
injectFn: R3.directiveInject,
|
||||
extraStatementFn: null,
|
||||
});
|
||||
definitionMapValues.push({key: 'factory', value: templateFactory.factory, quoted: false});
|
||||
|
||||
|
@ -55,7 +55,6 @@ function baseDirectiveFields(
|
||||
type: meta.type,
|
||||
deps: meta.deps,
|
||||
injectFn: R3.directiveInject,
|
||||
extraStatementFn: createFactoryExtraStatementsFn(meta, bindingParser)
|
||||
});
|
||||
definitionMap.set('factory', result.factory);
|
||||
|
||||
@ -67,8 +66,8 @@ function baseDirectiveFields(
|
||||
let hostVars = Object.keys(meta.host.properties).length;
|
||||
|
||||
const elVarExp = o.variable('elIndex');
|
||||
const dirVarExp = o.variable('dirIndex');
|
||||
const styleBuilder = new StylingBuilder(elVarExp, dirVarExp);
|
||||
const contextVarExp = o.variable(CONTEXT_NAME);
|
||||
const styleBuilder = new StylingBuilder(elVarExp, contextVarExp);
|
||||
|
||||
const allOtherAttributes: any = {};
|
||||
const attrNames = Object.getOwnPropertyNames(meta.host.attributes);
|
||||
@ -93,15 +92,15 @@ function baseDirectiveFields(
|
||||
// e.g. `attributes: ['role', 'listbox']`
|
||||
definitionMap.set('attributes', createHostAttributesArray(allOtherAttributes));
|
||||
|
||||
// e.g. `hostBindings: (dirIndex, elIndex) => { ... }
|
||||
// e.g. `hostBindings: (rf, ctx, elIndex) => { ... }
|
||||
definitionMap.set(
|
||||
'hostBindings',
|
||||
createHostBindingsFunction(
|
||||
meta, elVarExp, dirVarExp, styleBuilder, bindingParser, constantPool, (slots: number) => {
|
||||
const originalSlots = hostVars;
|
||||
hostVars += slots;
|
||||
return originalSlots;
|
||||
}));
|
||||
'hostBindings', createHostBindingsFunction(
|
||||
meta, elVarExp, contextVarExp, styleBuilder, bindingParser, constantPool,
|
||||
(slots: number) => {
|
||||
const originalSlots = hostVars;
|
||||
hostVars += slots;
|
||||
return originalSlots;
|
||||
}));
|
||||
|
||||
if (hostVars) {
|
||||
// e.g. `hostVars: 2
|
||||
@ -643,18 +642,26 @@ function createViewQueriesFunction(
|
||||
|
||||
// Return a host binding function or null if one is not necessary.
|
||||
function createHostBindingsFunction(
|
||||
meta: R3DirectiveMetadata, elVarExp: o.ReadVarExpr, dirVarExp: o.ReadVarExpr,
|
||||
meta: R3DirectiveMetadata, elVarExp: o.ReadVarExpr, bindingContext: o.ReadVarExpr,
|
||||
styleBuilder: StylingBuilder, bindingParser: BindingParser, constantPool: ConstantPool,
|
||||
allocatePureFunctionSlots: (slots: number) => number): o.Expression|null {
|
||||
const statements: o.Statement[] = [];
|
||||
const createStatements: o.Statement[] = [];
|
||||
const updateStatements: o.Statement[] = [];
|
||||
|
||||
const hostBindingSourceSpan = meta.typeSourceSpan;
|
||||
|
||||
const directiveSummary = metadataAsSummary(meta);
|
||||
|
||||
// Calculate host event bindings
|
||||
const eventBindings =
|
||||
bindingParser.createDirectiveHostEventAsts(directiveSummary, hostBindingSourceSpan);
|
||||
if (eventBindings && eventBindings.length) {
|
||||
const listeners = createHostListeners(bindingContext, eventBindings, meta);
|
||||
createStatements.push(...listeners);
|
||||
}
|
||||
|
||||
// Calculate the host property bindings
|
||||
const bindings = bindingParser.createBoundHostProperties(directiveSummary, hostBindingSourceSpan);
|
||||
const bindingContext = o.importExpr(R3.load).callFn([dirVarExp]);
|
||||
|
||||
const bindingFn = (implicit: any, value: AST) => {
|
||||
return convertPropertyBinding(
|
||||
@ -683,14 +690,14 @@ function createHostBindingsFunction(
|
||||
|
||||
const {bindingName, instruction} = getBindingNameAndInstruction(name);
|
||||
|
||||
statements.push(...bindingExpr.stmts);
|
||||
statements.push(o.importExpr(instruction)
|
||||
.callFn([
|
||||
elVarExp,
|
||||
o.literal(bindingName),
|
||||
o.importExpr(R3.bind).callFn([bindingExpr.currValExpr]),
|
||||
])
|
||||
.toStmt());
|
||||
updateStatements.push(...bindingExpr.stmts);
|
||||
updateStatements.push(o.importExpr(instruction)
|
||||
.callFn([
|
||||
elVarExp,
|
||||
o.literal(bindingName),
|
||||
o.importExpr(R3.bind).callFn([bindingExpr.currValExpr]),
|
||||
])
|
||||
.toStmt());
|
||||
}
|
||||
}
|
||||
|
||||
@ -698,24 +705,31 @@ function createHostBindingsFunction(
|
||||
const createInstruction = styleBuilder.buildCreateLevelInstruction(null, constantPool);
|
||||
if (createInstruction) {
|
||||
const createStmt = createStylingStmt(createInstruction, bindingContext, bindingFn);
|
||||
statements.push(createStmt);
|
||||
createStatements.push(createStmt);
|
||||
}
|
||||
|
||||
styleBuilder.buildUpdateLevelInstructions(valueConverter).forEach(instruction => {
|
||||
const updateStmt = createStylingStmt(instruction, bindingContext, bindingFn);
|
||||
statements.push(updateStmt);
|
||||
updateStatements.push(updateStmt);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (statements.length > 0) {
|
||||
const typeName = meta.name;
|
||||
if (createStatements.length > 0 || updateStatements.length > 0) {
|
||||
const hostBindingsFnName = meta.name ? `${meta.name}_HostBindings` : null;
|
||||
const statements: o.Statement[] = [];
|
||||
if (createStatements.length > 0) {
|
||||
statements.push(renderFlagCheckIfStmt(core.RenderFlags.Create, createStatements));
|
||||
}
|
||||
if (updateStatements.length > 0) {
|
||||
statements.push(renderFlagCheckIfStmt(core.RenderFlags.Update, updateStatements));
|
||||
}
|
||||
return o.fn(
|
||||
[
|
||||
new o.FnParam(dirVarExp.name !, o.NUMBER_TYPE),
|
||||
new o.FnParam(elVarExp.name !, o.NUMBER_TYPE),
|
||||
new o.FnParam(RENDER_FLAGS, o.NUMBER_TYPE), new o.FnParam(CONTEXT_NAME, null),
|
||||
new o.FnParam(elVarExp.name !, o.NUMBER_TYPE)
|
||||
],
|
||||
statements, o.INFERRED_TYPE, null, typeName ? `${typeName}_HostBindings` : null);
|
||||
statements, o.INFERRED_TYPE, null, hostBindingsFnName);
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -745,15 +759,6 @@ function getBindingNameAndInstruction(bindingName: string):
|
||||
return {bindingName, instruction};
|
||||
}
|
||||
|
||||
function createFactoryExtraStatementsFn(meta: R3DirectiveMetadata, bindingParser: BindingParser):
|
||||
((instance: o.Expression) => o.Statement[])|null {
|
||||
const eventBindings =
|
||||
bindingParser.createDirectiveHostEventAsts(metadataAsSummary(meta), meta.typeSourceSpan);
|
||||
return eventBindings && eventBindings.length ?
|
||||
(instance: o.Expression) => createHostListeners(instance, eventBindings, meta) :
|
||||
null;
|
||||
}
|
||||
|
||||
function createHostListeners(
|
||||
bindingContext: o.Expression, eventBindings: ParsedEvent[],
|
||||
meta: R3DirectiveMetadata): o.Statement[] {
|
||||
|
@ -80,8 +80,7 @@ export class StylingBuilder {
|
||||
private _useDefaultSanitizer = false;
|
||||
private _applyFnRequired = false;
|
||||
|
||||
constructor(
|
||||
private _elementIndexExpr: o.Expression, private _directiveIndexExpr: o.Expression|null) {}
|
||||
constructor(private _elementIndexExpr: o.Expression, private _directiveExpr: o.Expression|null) {}
|
||||
|
||||
registerBoundInput(input: t.BoundAttribute): boolean {
|
||||
// [attr.style] or [attr.class] are skipped in the code below,
|
||||
@ -217,15 +216,15 @@ export class StylingBuilder {
|
||||
// can be processed during runtime. These initial styles values are bound to
|
||||
// a constant because the inital style values do not change (since they're static).
|
||||
params.push(constantPool.getConstLiteral(initialStyles, true));
|
||||
} else if (useSanitizer || this._directiveIndexExpr) {
|
||||
} else if (useSanitizer || this._directiveExpr) {
|
||||
// no point in having an extra `null` value unless there are follow-up params
|
||||
params.push(o.NULL_EXPR);
|
||||
}
|
||||
|
||||
if (useSanitizer || this._directiveIndexExpr) {
|
||||
if (useSanitizer || this._directiveExpr) {
|
||||
params.push(useSanitizer ? o.importExpr(R3.defaultStyleSanitizer) : o.NULL_EXPR);
|
||||
if (this._directiveIndexExpr) {
|
||||
params.push(this._directiveIndexExpr);
|
||||
if (this._directiveExpr) {
|
||||
params.push(this._directiveExpr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -260,12 +259,12 @@ export class StylingBuilder {
|
||||
|
||||
if (mapBasedStyleValue) {
|
||||
params.push(convertFn(mapBasedStyleValue));
|
||||
} else if (this._directiveIndexExpr) {
|
||||
} else if (this._directiveExpr) {
|
||||
params.push(o.NULL_EXPR);
|
||||
}
|
||||
|
||||
if (this._directiveIndexExpr) {
|
||||
params.push(this._directiveIndexExpr);
|
||||
if (this._directiveExpr) {
|
||||
params.push(this._directiveExpr);
|
||||
}
|
||||
|
||||
return params;
|
||||
@ -289,13 +288,13 @@ export class StylingBuilder {
|
||||
if (allowUnits) {
|
||||
if (input.unit) {
|
||||
params.push(o.literal(input.unit));
|
||||
} else if (this._directiveIndexExpr) {
|
||||
} else if (this._directiveExpr) {
|
||||
params.push(o.NULL_EXPR);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._directiveIndexExpr) {
|
||||
params.push(this._directiveIndexExpr);
|
||||
if (this._directiveExpr) {
|
||||
params.push(this._directiveExpr);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
@ -325,8 +324,8 @@ export class StylingBuilder {
|
||||
reference: R3.elementStylingApply,
|
||||
buildParams: () => {
|
||||
const params: o.Expression[] = [this._elementIndexExpr];
|
||||
if (this._directiveIndexExpr) {
|
||||
params.push(this._directiveIndexExpr);
|
||||
if (this._directiveExpr) {
|
||||
params.push(this._directiveExpr);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
Reference in New Issue
Block a user