diff --git a/packages/compiler/src/render3/r3_identifiers.ts b/packages/compiler/src/render3/r3_identifiers.ts index a37e2a7bdc..b9bf96b0d3 100644 --- a/packages/compiler/src/render3/r3_identifiers.ts +++ b/packages/compiler/src/render3/r3_identifiers.ts @@ -17,12 +17,10 @@ export class Identifiers { static PATCH_DEPS = 'patchedDeps'; /* Instructions */ - static elementStart: o.ExternalReference = {name: 'ɵE', moduleName: CORE}; + static createElement: 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}; diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts index 607703732d..b0d21a9a11 100644 --- a/packages/compiler/src/render3/view/template.ts +++ b/packages/compiler/src/render3/view/template.ts @@ -314,42 +314,32 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver if (i18nMessages.length > 0) { this._creationCode.push(...i18nMessages); } - - let isSelfClosingElement = element.outputs.length === 0 && element.children.length === 0; - + this.instruction( + this._creationCode, element.sourceSpan, R3.createElement, ...trimTrailingNulls(parameters)); const implicit = o.variable(CONTEXT_NAME); - if (isSelfClosingElement) { + // 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, element.sourceSpan, R3.element, ...trimTrailingNulls(parameters)); - } else { - this.instruction( - this._creationCode, element.sourceSpan, R3.elementStart, - ...trimTrailingNulls(parameters)); + this._creationCode, outputAst.sourceSpan, R3.listener, o.literal(outputAst.name), + handler); + }); - // 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) => { @@ -377,11 +367,10 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver t.visitAll(this, element.children); } - if (!isSelfClosingElement) { - // Finish element construction mode. - this.instruction( - this._creationCode, element.endSourceSpan || element.sourceSpan, R3.elementEnd); - } + // Finish element construction mode. + this.instruction( + this._creationCode, element.endSourceSpan || element.sourceSpan, R3.elementEnd); + // Restore the state before exiting this node this._inI18nSection = wasInI18nSection; } diff --git a/packages/compiler/test/render3/r3_compiler_compliance_spec.ts b/packages/compiler/test/render3/r3_compiler_compliance_spec.ts index 74045c062b..a60ccb687c 100644 --- a/packages/compiler/test/render3/r3_compiler_compliance_spec.ts +++ b/packages/compiler/test/render3/r3_compiler_compliance_spec.ts @@ -90,7 +90,8 @@ describe('compiler compliance', () => { const template = ` template: function MyComponent_Template(rf: IDENT, ctx: IDENT) { if (rf & 1) { - $r3$.ɵEe(0, 'div'); + $r3$.ɵE(0, 'div'); + $r3$.ɵe(); } if (rf & 2) { $r3$.ɵp(0, 'id', $r3$.ɵb(ctx.id)); @@ -134,8 +135,9 @@ describe('compiler compliance', () => { const template = ` template: function MyComponent_Template(rf: IDENT, ctx: IDENT) { if (rf & 1) { - $r3$.ɵEe(0, 'div'); + $r3$.ɵE(0, 'div'); $r3$.ɵPp(1,'pipe'); + $r3$.ɵe(); $r3$.ɵrS(10); } if (rf & 2) { @@ -179,7 +181,8 @@ describe('compiler compliance', () => { const template = ` template: function MyComponent_Template(rf: IDENT, ctx: IDENT) { if (rf & 1) { - $r3$.ɵEe(0, 'div'); + $r3$.ɵE(0, 'div'); + $r3$.ɵe(); } if (rf & 2) { $r3$.ɵkn(0, 'error', $r3$.ɵb(ctx.error)); @@ -251,7 +254,8 @@ describe('compiler compliance', () => { factory: function MyComponent_Factory() { return new MyComponent(); }, template: function MyComponent_Template(rf: IDENT, ctx: IDENT) { if (rf & 1) { - $r3$.ɵEe(0, 'child', $c1$); + $r3$.ɵE(0, 'child', $c1$); + $r3$.ɵe(); $r3$.ɵT(1, '!'); } }, @@ -457,7 +461,8 @@ describe('compiler compliance', () => { factory: function MyApp_Factory() { return new MyApp(); }, template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { if (rf & 1) { - $r3$.ɵEe(0, 'my-comp'); + $r3$.ɵE(0, 'my-comp'); + $r3$.ɵe(); $r3$.ɵrS(2); } if (rf & 2) { @@ -536,7 +541,8 @@ describe('compiler compliance', () => { factory: function MyApp_Factory() { return new MyApp(); }, template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { if (rf & 1) { - $r3$.ɵEe(0, 'my-comp'); + $r3$.ɵE(0, 'my-comp'); + $r3$.ɵe(); $r3$.ɵrS(10); } if (rf & 2) { @@ -597,7 +603,8 @@ describe('compiler compliance', () => { factory: function MyApp_Factory() { return new MyApp(); }, template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { if (rf & 1) { - $r3$.ɵEe(0, 'object-comp'); + $r3$.ɵE(0, 'object-comp'); + $r3$.ɵe(); $r3$.ɵrS(2); } if (rf & 2) { @@ -662,7 +669,8 @@ describe('compiler compliance', () => { factory: function MyApp_Factory() { return new MyApp(); }, template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { if (rf & 1) { - $r3$.ɵEe(0, 'nested-comp'); + $r3$.ɵE(0, 'nested-comp'); + $r3$.ɵe(); $r3$.ɵrS(7); } if (rf & 2) { @@ -806,7 +814,8 @@ describe('compiler compliance', () => { var $tmp$: $any$; if (rf & 1) { $r3$.ɵQ(0, SomeDirective, true); - $r3$.ɵEe(1, 'div', $e0_attrs$); + $r3$.ɵE(1, 'div', $e0_attrs$); + $r3$.ɵe(); } if (rf & 2) { ($r3$.ɵqR(($tmp$ = $r3$.ɵld(0))) && (ctx.someDir = $tmp$.first)); @@ -1000,7 +1009,8 @@ describe('compiler compliance', () => { factory: function MyComponent_Factory() { return new MyComponent(); }, template: function MyComponent_Template(rf: IDENT, ctx: IDENT) { if (rf & 1) { - $r3$.ɵEe(0, 'input', null, $c1$); + $r3$.ɵE(0, 'input', null, $c1$); + $r3$.ɵe(); $r3$.ɵT(2); } const $user$ = $r3$.ɵld(1); @@ -1079,8 +1089,10 @@ describe('compiler compliance', () => { factory: function SimpleLayout_Factory() { return new SimpleLayout(); }, template: function SimpleLayout_Template(rf: IDENT, ctx: IDENT) { if (rf & 1) { - $r3$.ɵEe(0, 'lifecycle-comp'); - $r3$.ɵEe(1, 'lifecycle-comp'); + $r3$.ɵE(0, 'lifecycle-comp'); + $r3$.ɵe(); + $r3$.ɵE(1, 'lifecycle-comp'); + $r3$.ɵe(); } if (rf & 2) { $r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name1)); diff --git a/packages/compiler/test/render3/r3_view_compiler_binding_spec.ts b/packages/compiler/test/render3/r3_view_compiler_binding_spec.ts index a9f4f3672e..8b0a9edcbe 100644 --- a/packages/compiler/test/render3/r3_view_compiler_binding_spec.ts +++ b/packages/compiler/test/render3/r3_view_compiler_binding_spec.ts @@ -75,7 +75,8 @@ describe('compiler compliance: bindings', () => { const template = ` template:function MyComponent_Template(rf: IDENT, $ctx$: IDENT){ if (rf & 1) { - $i0$.ɵEe(0, 'a'); + $i0$.ɵE(0, 'a'); + $i0$.ɵe(); } if (rf & 2) { $i0$.ɵp(0, 'title', $i0$.ɵb($ctx$.title)); @@ -107,7 +108,8 @@ describe('compiler compliance: bindings', () => { const template = ` template:function MyComponent_Template(rf: IDENT, $ctx$: IDENT){ if (rf & 1) { - $i0$.ɵEe(0, 'a'); + $i0$.ɵE(0, 'a'); + $i0$.ɵe(); } if (rf & 2) { $i0$.ɵp(0, 'title', $i0$.ɵi1('Hello ', $ctx$.name, '')); diff --git a/packages/compiler/test/render3/r3_view_compiler_i18n_spec.ts b/packages/compiler/test/render3/r3_view_compiler_i18n_spec.ts index 1065b3acb9..3839df2615 100644 --- a/packages/compiler/test/render3/r3_view_compiler_i18n_spec.ts +++ b/packages/compiler/test/render3/r3_view_compiler_i18n_spec.ts @@ -148,7 +148,8 @@ describe('i18n support in the view compiler', () => { … template: function MyComponent_Template(rf: IDENT, ctx: IDENT) { if (rf & 1) { - $r3$.ɵEe(0, 'div', $c1$); + $r3$.ɵE(0, 'div', $c1$); + $r3$.ɵe(); } } `; diff --git a/packages/compiler/test/render3/r3_view_compiler_template_spec.ts b/packages/compiler/test/render3/r3_view_compiler_template_spec.ts index 86d96f9850..12041faec4 100644 --- a/packages/compiler/test/render3/r3_view_compiler_template_spec.ts +++ b/packages/compiler/test/render3/r3_view_compiler_template_spec.ts @@ -109,43 +109,4 @@ describe('compiler compliance: template', () => { expectEmit(result.source, template, 'Incorrect template'); }); - // tslint:disable-next-line:ban - describe('element with no children', () => { - it('should just use the element instruction', () => { - const files = { - app: { - 'spec.ts': ` - import {Component, NgModule} from '@angular/core'; - import {CommonModule} from '@angular/common'; - - @Component({ - selector: 'my-component', - template: \` -
\` - }) - export class MyComponent { - } - - @NgModule({declarations: [MyComponent], imports: [CommonModule]}) - export class MyModule {} - ` - } - }; - - const template = ` - // ... - template:function MyComponent_Template(rf: IDENT, $ctx$: IDENT){ - if (rf & 1) { - $i0$.ɵEe(0,'div'); - } - }`; - - debugger; - - const result = compile(files, angularFiles); - - expectEmit(result.source, template, 'Incorrect template'); - }); - }); - }); diff --git a/packages/core/src/core_render3_private_export.ts b/packages/core/src/core_render3_private_export.ts index edcd9abbf5..ff8c7449b4 100644 --- a/packages/core/src/core_render3_private_export.ts +++ b/packages/core/src/core_render3_private_export.ts @@ -28,7 +28,6 @@ export { NC as ɵNC, C as ɵC, E as ɵE, - Ee as ɵEe, L as ɵL, T as ɵT, V as ɵV, diff --git a/packages/core/src/render3/index.ts b/packages/core/src/render3/index.ts index 19929ac932..0e8e091bc3 100644 --- a/packages/core/src/render3/index.ts +++ b/packages/core/src/render3/index.ts @@ -50,7 +50,6 @@ export { elementEnd as e, elementProperty as p, elementStart as E, - element as Ee, elementStyle as s, elementStyleNamed as sn, diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index 30fcc1fe80..ef9e7d9540 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -1032,15 +1032,6 @@ export function elementEnd() { queueLifecycleHooks(previousOrParentNode.tNode.flags, currentView); } -/** Marks the beginning and end of an element in one call. */ -export function element( - index: number, name: string, attrs?: TAttributes | null | undefined, - localRefs?: string[] | null | undefined): RElement { - const relement = elementStart(index, name, attrs, localRefs); - elementEnd(); - return relement; -} - /** * Updates the value of removes an attribute on an Element. * diff --git a/packages/core/src/render3/node_selector_matcher.ts b/packages/core/src/render3/node_selector_matcher.ts index efba0295ee..5f6f8b5ed0 100644 --- a/packages/core/src/render3/node_selector_matcher.ts +++ b/packages/core/src/render3/node_selector_matcher.ts @@ -12,7 +12,6 @@ import {assertNotNull} from './assert'; import {AttributeMarker, TAttributes, TNode, unusedValueExportToPlacateAjd as unused1} from './interfaces/node'; import {CssSelector, CssSelectorList, NG_PROJECT_AS_ATTR_NAME, SelectorFlags, unusedValueExportToPlacateAjd as unused2} from './interfaces/projection'; - const unusedValueToPlacateAjd = unused1 + unused2; function isCssClassMatching(nodeClassAttrVal: string, cssClassToMatch: string): boolean { diff --git a/packages/core/test/render3/compiler_canonical/component_directives_spec.ts b/packages/core/test/render3/compiler_canonical/component_directives_spec.ts index f928655a46..7c1e6a7845 100644 --- a/packages/core/test/render3/compiler_canonical/component_directives_spec.ts +++ b/packages/core/test/render3/compiler_canonical/component_directives_spec.ts @@ -69,7 +69,8 @@ describe('components & directives', () => { factory: () => new MyComponent(), template: function(rf: $RenderFlags$, ctx: $MyComponent$) { if (rf & 1) { - $r3$.ɵEe(0, 'child', $e0_attrs$); + $r3$.ɵE(0, 'child', $e0_attrs$); + $r3$.ɵe(); $r3$.ɵT(1, '!'); } } @@ -454,7 +455,8 @@ describe('components & directives', () => { factory: function MyApp_Factory() { return new MyApp(); }, template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { if (rf & 1) { - $r3$.ɵEe(0, 'my-array-comp'); + $r3$.ɵE(0, 'my-array-comp'); + $r3$.ɵe(); } if (rf & 2) { $r3$.ɵp(0, 'names', rf & 1 ? $e0_arr$ : $r3$.ɵNC); @@ -498,7 +500,8 @@ describe('components & directives', () => { factory: function MyApp_Factory() { return new MyApp(); }, template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { if (rf & 1) { - $r3$.ɵEe(0, 'my-array-comp'); + $r3$.ɵE(0, 'my-array-comp'); + $r3$.ɵe(); $r3$.ɵrS(1); } if (rf & 2) { @@ -603,7 +606,8 @@ describe('components & directives', () => { factory: function MyApp_Factory() { return new MyApp(); }, template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { if (rf & 1) { - $r3$.ɵEe(0, 'my-array-comp'); + $r3$.ɵE(0, 'my-array-comp'); + $r3$.ɵe(); $r3$.ɵrS(2); } if (rf & 2) { @@ -713,7 +717,8 @@ describe('components & directives', () => { factory: function MyApp_Factory() { return new MyApp(); }, template: function MyApp_Template(rf: $RenderFlags$, c: $any$) { if (rf & 1) { - $r3$.ɵEe(0, 'my-comp'); + $r3$.ɵE(0, 'my-comp'); + $r3$.ɵe(); $r3$.ɵrS(10); } if (rf & 2) { diff --git a/packages/core/test/render3/compiler_canonical/query_spec.ts b/packages/core/test/render3/compiler_canonical/query_spec.ts index a5d51d0391..d3e19413e3 100644 --- a/packages/core/test/render3/compiler_canonical/query_spec.ts +++ b/packages/core/test/render3/compiler_canonical/query_spec.ts @@ -58,7 +58,8 @@ describe('queries', () => { if (rf & 1) { $r3$.ɵQ(0, SomeDirective, false); $r3$.ɵQ(1, SomeDirective, false); - $r3$.ɵEe(2, 'div', $e1_attrs$); + $r3$.ɵE(2, 'div', $e1_attrs$); + $r3$.ɵe(); } if (rf & 2) { $r3$.ɵqR($tmp$ = $r3$.ɵld>(0)) && (ctx.someDir = $tmp$.first); diff --git a/packages/core/test/render3/instructions_spec.ts b/packages/core/test/render3/instructions_spec.ts index 237744cee4..7056457990 100644 --- a/packages/core/test/render3/instructions_spec.ts +++ b/packages/core/test/render3/instructions_spec.ts @@ -10,14 +10,14 @@ import {NgForOfContext} from '@angular/common'; import {RenderFlags, directiveInject} from '../../src/render3'; import {defineComponent} from '../../src/render3/definition'; -import {bind, container, element, elementAttribute, elementClass, elementEnd, elementProperty, elementStart, elementStyle, elementStyleNamed, interpolation1, renderTemplate, setHtmlNS, setSvgNS, text, textBinding} from '../../src/render3/instructions'; +import {bind, container, elementAttribute, elementClass, elementEnd, elementProperty, elementStart, elementStyle, elementStyleNamed, interpolation1, renderTemplate, setHtmlNS, setSvgNS, text, textBinding} from '../../src/render3/instructions'; import {LElementNode, LNode, NS} from '../../src/render3/interfaces/node'; import {RElement, domRendererFactory3} from '../../src/render3/interfaces/renderer'; import {TrustedString, bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl, sanitizeHtml, sanitizeResourceUrl, sanitizeScript, sanitizeStyle, sanitizeUrl} from '../../src/sanitization/sanitization'; import {Sanitizer, SecurityContext} from '../../src/sanitization/security'; import {NgForOf} from './common_with_def'; -import {ComponentFixture, TemplateFixture, toHtml} from './render_util'; +import {ComponentFixture, TemplateFixture} from './render_util'; describe('instructions', () => { function createAnchor() { @@ -94,12 +94,13 @@ describe('instructions', () => { it('should use sanitizer function even on elements with namespaced attributes', () => { const t = new TemplateFixture(() => { - element(0, 'div', [ + elementStart(0, 'div', [ NS.FULL, 'http://www.example.com/2004/test', 'whatever', 'abc', ]); + elementEnd(); }); t.update(() => elementAttribute(0, 'title', 'javascript:true', sanitizeUrl)); @@ -450,7 +451,8 @@ describe('instructions', () => { 'title', 'abc', ]); - element(2, 'circle', ['cx', '200', 'cy', '150', 'fill', '#0000ff']); + elementStart(2, 'circle', ['cx', '200', 'cy', '150', 'fill', '#0000ff']); + elementEnd(); elementEnd(); setHtmlNS(); elementEnd(); @@ -468,7 +470,7 @@ describe('instructions', () => { it('should set an attribute with a namespace', () => { const t = new TemplateFixture(() => { - element(0, 'div', [ + elementStart(0, 'div', [ 'id', 'container', // test:title="abc" @@ -477,6 +479,7 @@ describe('instructions', () => { 'title', 'abc', ]); + elementEnd(); }); const standardHTML = '
'; @@ -487,7 +490,7 @@ describe('instructions', () => { it('should set attributes including more than one namespaced attribute', () => { const t = new TemplateFixture(() => { - element(0, 'div', [ + elementStart(0, 'div', [ 'id', 'container', @@ -513,6 +516,7 @@ describe('instructions', () => { 'shazbot', 'wocka wocka', ]); + elementEnd(); }); const standardHTML =