feat(ivy): add element instruction (#23899)

Adds a simplified element instruction that can be used if an element
has no children.

PR Close #23899
This commit is contained in:
Ben Lesh
2018-05-25 16:23:00 -07:00
committed by Victor Berchet
parent d6989c80d3
commit b415010222
13 changed files with 117 additions and 78 deletions

View File

@ -17,10 +17,12 @@ export class Identifiers {
static PATCH_DEPS = 'patchedDeps';
/* Instructions */
static createElement: o.ExternalReference = {name: 'ɵE', moduleName: CORE};
static elementStart: o.ExternalReference = {name: 'ɵE', moduleName: CORE};
static elementEnd: o.ExternalReference = {name: 'ɵe', moduleName: CORE};
static element: o.ExternalReference = {name: 'ɵEe', moduleName: CORE};
static elementProperty: o.ExternalReference = {name: 'ɵp', moduleName: CORE};
static elementAttribute: o.ExternalReference = {name: 'ɵa', moduleName: CORE};

View File

@ -314,32 +314,42 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
if (i18nMessages.length > 0) {
this._creationCode.push(...i18nMessages);
}
this.instruction(
this._creationCode, element.sourceSpan, R3.createElement, ...trimTrailingNulls(parameters));
let isSelfClosingElement = element.outputs.length === 0 && element.children.length === 0;
const implicit = o.variable(CONTEXT_NAME);
// Generate Listeners (outputs)
element.outputs.forEach((outputAst: t.BoundEvent) => {
const elName = sanitizeIdentifier(element.name);
const evName = sanitizeIdentifier(outputAst.name);
const functionName = `${this.templateName}_${elName}_${evName}_listener`;
const localVars: o.Statement[] = [];
const bindingScope =
this._bindingScope.nestedScope((lhsVar: o.ReadVarExpr, rhsExpression: o.Expression) => {
localVars.push(
lhsVar.set(rhsExpression).toDeclStmt(o.INFERRED_TYPE, [o.StmtModifier.Final]));
});
const bindingExpr = convertActionBinding(
bindingScope, implicit, outputAst.handler, 'b', () => error('Unexpected interpolation'));
const handler = o.fn(
[new o.FnParam('$event', o.DYNAMIC_TYPE)], [...localVars, ...bindingExpr.render3Stmts],
o.INFERRED_TYPE, null, functionName);
if (isSelfClosingElement) {
this.instruction(
this._creationCode, outputAst.sourceSpan, R3.listener, o.literal(outputAst.name),
handler);
});
this._creationCode, element.sourceSpan, R3.element, ...trimTrailingNulls(parameters));
} else {
this.instruction(
this._creationCode, element.sourceSpan, R3.elementStart,
...trimTrailingNulls(parameters));
// Generate Listeners (outputs)
element.outputs.forEach((outputAst: t.BoundEvent) => {
const elName = sanitizeIdentifier(element.name);
const evName = sanitizeIdentifier(outputAst.name);
const functionName = `${this.templateName}_${elName}_${evName}_listener`;
const localVars: o.Statement[] = [];
const bindingScope =
this._bindingScope.nestedScope((lhsVar: o.ReadVarExpr, rhsExpression: o.Expression) => {
localVars.push(
lhsVar.set(rhsExpression).toDeclStmt(o.INFERRED_TYPE, [o.StmtModifier.Final]));
});
const bindingExpr = convertActionBinding(
bindingScope, implicit, outputAst.handler, 'b',
() => error('Unexpected interpolation'));
const handler = o.fn(
[new o.FnParam('$event', o.DYNAMIC_TYPE)], [...localVars, ...bindingExpr.render3Stmts],
o.INFERRED_TYPE, null, functionName);
this.instruction(
this._creationCode, outputAst.sourceSpan, R3.listener, o.literal(outputAst.name),
handler);
});
}
// Generate element input bindings
element.inputs.forEach((input: t.BoundAttribute) => {
@ -367,10 +377,11 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
t.visitAll(this, element.children);
}
// Finish element construction mode.
this.instruction(
this._creationCode, element.endSourceSpan || element.sourceSpan, R3.elementEnd);
if (!isSelfClosingElement) {
// Finish element construction mode.
this.instruction(
this._creationCode, element.endSourceSpan || element.sourceSpan, R3.elementEnd);
}
// Restore the state before exiting this node
this._inI18nSection = wasInI18nSection;
}