refactor(ivy): add element instruction, reducing output size (#24379)

- Adds an element instruction
- Reduces size of compiled output slightly

PR Close #24379
This commit is contained in:
Ben Lesh
2018-06-08 10:48:27 -07:00
committed by Miško Hevery
parent 014949f74c
commit 8dd99ac550
19 changed files with 127 additions and 128 deletions

View File

@ -23,7 +23,9 @@ export class Identifiers {
static namespaceSVG: o.ExternalReference = {name: 'ɵNS', moduleName: CORE};
static createElement: o.ExternalReference = {name: 'ɵE', moduleName: CORE};
static element: o.ExternalReference = {name: 'ɵEe', moduleName: CORE};
static elementStart: o.ExternalReference = {name: 'ɵE', moduleName: CORE};
static elementEnd: o.ExternalReference = {name: 'ɵe', moduleName: CORE};

View File

@ -357,32 +357,44 @@ export class TemplateDefinitionBuilder implements t.Visitor<void>, LocalResolver
this.addNamespaceInstruction(currentNamespace, element);
}
this.instruction(
this._creationCode, element.sourceSpan, R3.createElement, ...trimTrailingNulls(parameters));
const isEmptyElement = element.children.length === 0 && element.outputs.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 (isEmptyElement) {
this.instruction(
this._creationCode, outputAst.sourceSpan, R3.listener, o.literal(outputAst.name),
handler);
});
this._creationCode, element.sourceSpan, R3.element, ...trimTrailingNulls(parameters));
} else {
// Generate the instruction create element instruction
if (i18nMessages.length > 0) {
this._creationCode.push(...i18nMessages);
}
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) => {
@ -422,9 +434,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 (!isEmptyElement) {
// Finish element construction mode.
this.instruction(
this._creationCode, element.endSourceSpan || element.sourceSpan, R3.elementEnd);
}
// Restore the state before exiting this node
this._inI18nSection = wasInI18nSection;

View File

@ -52,8 +52,7 @@ describe('compiler compliance', () => {
$r3$.ɵE(0, 'div', $c1$);
$r3$.ɵNS();
$r3$.ɵE(1, 'svg');
$r3$.ɵE(2, 'circle', $c2$);
$r3$.ɵe();
$r3$.ɵEe(2, 'circle', $c2$);
$r3$.ɵe();
$r3$.ɵNH();
$r3$.ɵE(3, 'p');
@ -101,8 +100,7 @@ describe('compiler compliance', () => {
$r3$.ɵE(0, 'div', $c1$);
$r3$.ɵNM();
$r3$.ɵE(1, 'math');
$r3$.ɵE(2, 'infinity');
$r3$.ɵe();
$r3$.ɵEe(2, 'infinity');
$r3$.ɵe();
$r3$.ɵNH();
$r3$.ɵE(3, 'p');
@ -189,8 +187,7 @@ describe('compiler compliance', () => {
const template = `
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵe();
$r3$.ɵEe(0, 'div');
}
if (rf & 2) {
$r3$.ɵp(0, 'id', $r3$.ɵb(ctx.id));
@ -234,9 +231,8 @@ describe('compiler compliance', () => {
const template = `
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵEe(0, 'div');
$r3$.ɵPp(1,'pipe');
$r3$.ɵe();
$r3$.ɵrS(10);
}
if (rf & 2) {
@ -280,8 +276,7 @@ describe('compiler compliance', () => {
const template = `
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵe();
$r3$.ɵEe(0, 'div');
}
if (rf & 2) {
$r3$.ɵkn(0, 'error', $r3$.ɵb(ctx.error));
@ -353,8 +348,7 @@ describe('compiler compliance', () => {
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
if (rf & 1) {
$r3$.ɵE(0, 'child', $c1$);
$r3$.ɵe();
$r3$.ɵEe(0, 'child', $c1$);
$r3$.ɵT(1, '!');
}
},
@ -560,8 +554,7 @@ describe('compiler compliance', () => {
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'my-comp');
$r3$.ɵe();
$r3$.ɵEe(0, 'my-comp');
$r3$.ɵrS(2);
}
if (rf & 2) {
@ -640,8 +633,7 @@ describe('compiler compliance', () => {
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'my-comp');
$r3$.ɵe();
$r3$.ɵEe(0, 'my-comp');
$r3$.ɵrS(10);
}
if (rf & 2) {
@ -702,8 +694,7 @@ describe('compiler compliance', () => {
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'object-comp');
$r3$.ɵe();
$r3$.ɵEe(0, 'object-comp');
$r3$.ɵrS(2);
}
if (rf & 2) {
@ -768,8 +759,7 @@ describe('compiler compliance', () => {
factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) {
if (rf & 1) {
$r3$.ɵE(0, 'nested-comp');
$r3$.ɵe();
$r3$.ɵEe(0, 'nested-comp');
$r3$.ɵrS(7);
}
if (rf & 2) {
@ -913,8 +903,7 @@ describe('compiler compliance', () => {
var $tmp$: $any$;
if (rf & 1) {
$r3$.ɵQ(0, SomeDirective, true);
$r3$.ɵE(1, 'div', $e0_attrs$);
$r3$.ɵe();
$r3$.ɵEe(1, 'div', $e0_attrs$);
}
if (rf & 2) {
($r3$.ɵqR(($tmp$ = $r3$.ɵld(0))) && (ctx.someDir = $tmp$.first));
@ -1108,8 +1097,7 @@ describe('compiler compliance', () => {
factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
if (rf & 1) {
$r3$.ɵE(0, 'input', null, $c1$);
$r3$.ɵe();
$r3$.ɵEe(0, 'input', null, $c1$);
$r3$.ɵT(2);
}
const $user$ = $r3$.ɵld(1);
@ -1188,10 +1176,8 @@ describe('compiler compliance', () => {
factory: function SimpleLayout_Factory() { return new SimpleLayout(); },
template: function SimpleLayout_Template(rf: IDENT, ctx: IDENT) {
if (rf & 1) {
$r3$.ɵE(0, 'lifecycle-comp');
$r3$.ɵe();
$r3$.ɵE(1, 'lifecycle-comp');
$r3$.ɵe();
$r3$.ɵEe(0, 'lifecycle-comp');
$r3$Ee(1, 'lifecycle-comp');
}
if (rf & 2) {
$r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name1));
@ -1319,8 +1305,7 @@ describe('compiler compliance', () => {
if (rf & 1) {
$r3$.ɵNS();
$r3$.ɵE(0,'g');
$r3$.ɵE(1,'circle');
$r3$.ɵe();
$r3$.ɵEe(1,'circle');
$r3$.ɵe();
}
}

View File

@ -75,8 +75,7 @@ describe('compiler compliance: bindings', () => {
const template = `
template:function MyComponent_Template(rf: IDENT, $ctx$: IDENT){
if (rf & 1) {
$i0$.ɵE(0, 'a');
$i0$.ɵe();
$i0$.ɵEe(0, 'a');
}
if (rf & 2) {
$i0$.ɵp(0, 'title', $i0$.ɵb($ctx$.title));
@ -108,8 +107,7 @@ describe('compiler compliance: bindings', () => {
const template = `
template:function MyComponent_Template(rf: IDENT, $ctx$: IDENT){
if (rf & 1) {
$i0$.ɵE(0, 'a');
$i0$.ɵe();
$i0$.ɵEe(0, 'a');
}
if (rf & 2) {
$i0$.ɵp(0, 'title', $i0$.ɵi1('Hello ', $ctx$.name, ''));

View File

@ -148,8 +148,7 @@ describe('i18n support in the view compiler', () => {
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
if (rf & 1) {
$r3$.ɵE(0, 'div', $c1$);
$r3$.ɵe();
$r3$.ɵEe(0, 'div', $c1$);
}
}
`;

View File

@ -40,8 +40,7 @@ describe('compiler compliance: styling', () => {
const template = `
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵe();
$r3$.ɵEe(0, 'div');
}
if (rf & 2) {
$r3$.ɵs(0,$r3$.ɵb($ctx$.myStyleExp));
@ -78,8 +77,7 @@ describe('compiler compliance: styling', () => {
const template = `
template: function MyComponent_Template(rf: $RenderFlags$, $ctx$: $MyComponent$) {
if (rf & 1) {
$r3$.ɵE(0, 'div');
$r3$.ɵe();
$r3$.ɵEe(0, 'div');
}
if (rf & 2) {
$r3$.ɵk(0,$r3$.ɵb($ctx$.myClassExp));