diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index c58178658fa160..bd410c5a04ec85 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -19,7 +19,7 @@ import {assertNodeType} from './node_assert'; import {appendChild, insertChild, insertView, appendProjectedNode, removeView, canInsertNativeNode} from './node_manipulation'; import {matchingSelectorIndex} from './node_selector_matcher'; import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveType} from './interfaces/definition'; -import {RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, ObjectOrientedRenderer3, RendererStyleFlags3} from './interfaces/renderer'; +import {RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, ObjectOrientedRenderer3, RendererStyleFlags3, isProceduralRenderer} from './interfaces/renderer'; import {isDifferent, stringify} from './util'; import {executeHooks, executeContentHooks, queueLifecycleHooks, queueInitHooks, executeInitHooks} from './hooks'; @@ -569,8 +569,8 @@ export function listener(eventName: string, listener: EventListener, useCapture // In order to match current behavior, native DOM event listeners must be added for all // events (including outputs). - if ((renderer as ProceduralRenderer3).listen) { - const cleanupFn = (renderer as ProceduralRenderer3).listen(native, eventName, listener); + if (isProceduralRenderer(renderer)) { + const cleanupFn = renderer.listen(native, eventName, listener); (cleanup || (cleanup = currentView.cleanup = [])).push(cleanupFn, null); } else { native.addEventListener(eventName, listener, useCapture); diff --git a/packages/core/src/render3/interfaces/renderer.ts b/packages/core/src/render3/interfaces/renderer.ts index cb7f249a1bd60d..042e6f996f9ea4 100644 --- a/packages/core/src/render3/interfaces/renderer.ts +++ b/packages/core/src/render3/interfaces/renderer.ts @@ -41,6 +41,12 @@ export interface ObjectOrientedRenderer3 { querySelector(selectors: string): RElement|null; } +/** Returns wether the `renderer` is a `ProceduralRenderer3` */ +export function isProceduralRenderer(renderer: ProceduralRenderer3 | ObjectOrientedRenderer3): + renderer is ProceduralRenderer3 { + return !!((renderer as any).listen); +} + /** * Procedural style of API needed to create elements and text nodes. * diff --git a/packages/core/src/render3/node_manipulation.ts b/packages/core/src/render3/node_manipulation.ts index ff1b2d6b2a0ff1..d40c92ef620a03 100644 --- a/packages/core/src/render3/node_manipulation.ts +++ b/packages/core/src/render3/node_manipulation.ts @@ -11,7 +11,7 @@ import {callHooks} from './hooks'; import {LContainer, unusedValueExportToPlacateAjd as unused1} from './interfaces/container'; import {LContainerNode, LElementNode, LNode, LNodeFlags, LProjectionNode, LTextNode, LViewNode, unusedValueExportToPlacateAjd as unused2} from './interfaces/node'; import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection'; -import {ProceduralRenderer3, RElement, RNode, RText, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer'; +import {ProceduralRenderer3, RElement, RNode, RText, isProceduralRenderer, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer'; import {HookData, LView, LViewOrLContainer, TView, unusedValueExportToPlacateAjd as unused5} from './interfaces/view'; import {assertNodeType} from './node_assert'; @@ -174,16 +174,15 @@ export function addRemoveViewFromContainer( const type = node.flags & LNodeFlags.TYPE_MASK; let nextNode: LNode|null = null; const renderer = container.view.renderer; - const isFnRenderer = (renderer as ProceduralRenderer3).listen; if (type === LNodeFlags.Element) { - insertMode ? (isFnRenderer ? - (renderer as ProceduralRenderer3) - .insertBefore !(parent, node.native !, beforeNode as RNode | null) : - parent.insertBefore(node.native !, beforeNode as RNode | null, true)) : - (isFnRenderer ? - (renderer as ProceduralRenderer3) - .removeChild !(parent as RElement, node.native !) : - parent.removeChild(node.native !)); + if (insertMode) { + isProceduralRenderer(renderer) ? + renderer.insertBefore(parent, node.native !, beforeNode as RNode | null) : + parent.insertBefore(node.native !, beforeNode as RNode | null, true); + } else { + isProceduralRenderer(renderer) ? renderer.removeChild(parent as RElement, node.native !) : + parent.removeChild(node.native !); + } nextNode = node.next; } else if (type === LNodeFlags.Container) { // if we get to a container, it must be a root node of a view because we are only @@ -421,7 +420,7 @@ export function canInsertNativeNode(parent: LNode, currentView: LView): boolean } /** - * Appends the provided child element to the provided parent. + * Appends the `child` element to the `parent`. * * The element insertion might be delayed {@link canInsertNativeNode} * @@ -434,9 +433,8 @@ export function appendChild(parent: LNode, child: RNode | null, currentView: LVi if (child !== null && canInsertNativeNode(parent, currentView)) { // We only add element if not in View or not projected. const renderer = currentView.renderer; - (renderer as ProceduralRenderer3).listen ? - (renderer as ProceduralRenderer3).appendChild !(parent.native !as RElement, child) : - parent.native !.appendChild(child); + isProceduralRenderer(renderer) ? renderer.appendChild(parent.native !as RElement, child) : + parent.native !.appendChild(child); return true; } return false; @@ -455,9 +453,8 @@ export function insertChild(node: LNode, currentView: LView): void { if (canInsertNativeNode(parent, currentView)) { let nativeSibling: RNode|null = findNextRNodeSibling(node, null); const renderer = currentView.renderer; - (renderer as ProceduralRenderer3).listen ? - (renderer as ProceduralRenderer3) - .insertBefore !(parent.native !, node.native !, nativeSibling) : + isProceduralRenderer(renderer) ? + renderer.insertBefore(parent.native !, node.native !, nativeSibling) : parent.native !.insertBefore(node.native !, nativeSibling, false); } } diff --git a/packages/core/test/render3/object_literal_spec.ts b/packages/core/test/render3/object_literal_spec.ts index a9ee43e97ea369..941c79e459fa53 100644 --- a/packages/core/test/render3/object_literal_spec.ts +++ b/packages/core/test/render3/object_literal_spec.ts @@ -283,13 +283,17 @@ describe('array literals', () => { */ function Template(ctx: any, cm: boolean) { if (cm) { - E(0, NestedComp); - e(); + elementStart(0, NestedComp); + elementEnd(); } - p(0, 'config', o2(2, e0_literal_2, 'animation', ctx.name, 'actions', - o1(1, e0_literal_1, 1, o1(0, e0_literal, 'duration', ctx.duration)))); + elementProperty( + 0, 'config', + objectLiteral2( + 2, e0_literal_2, 'animation', ctx.name, 'actions', + objectLiteral1( + 1, e0_literal_1, 1, objectLiteral1(0, e0_literal, 'duration', ctx.duration)))); NestedComp.ngComponentDef.h(1, 0); - r(1, 0); + componentRefresh(1, 0); } const e0_literal = {opacity: 1, duration: null};