diff --git a/packages/core/src/render3/context_discovery.ts b/packages/core/src/render3/context_discovery.ts index fa2af9e6a3..30701f9f21 100644 --- a/packages/core/src/render3/context_discovery.ts +++ b/packages/core/src/render3/context_discovery.ts @@ -99,7 +99,7 @@ export function getContext(target: any): LContext|null { if (nodeIndex == -1) { throw new Error('The provided directive was not found in the application'); } - directives = discoverDirectives(nodeIndex, lViewData); + directives = discoverDirectives(nodeIndex, lViewData, false); } else { nodeIndex = findViaNativeElement(lViewData, target as RElement); if (nodeIndex == -1) { @@ -344,15 +344,18 @@ function getLNodeFromViewData(lViewData: LViewData, lElementIndex: number): LEle * Returns a list of directives extracted from the given view. Does not contain * the component. * + * @param nodeIndex Index of node to search * @param lViewData The target view data + * @param includeComponents Whether or not to include components in returned directives */ -export function discoverDirectives(nodeIndex: number, lViewData: LViewData): any[]|null { +export function discoverDirectives( + nodeIndex: number, lViewData: LViewData, includeComponents: boolean): any[]|null { const directivesAcrossView = lViewData[DIRECTIVES]; if (directivesAcrossView != null) { const tNode = lViewData[TVIEW].data[nodeIndex] as TNode; let directiveStartIndex = getDirectiveStartIndex(tNode); const directiveEndIndex = getDirectiveEndIndex(tNode, directiveStartIndex); - if (tNode.flags & TNodeFlags.isComponent) directiveStartIndex++; + if (!includeComponents && tNode.flags & TNodeFlags.isComponent) directiveStartIndex++; return directivesAcrossView.slice(directiveStartIndex, directiveEndIndex); } return null; diff --git a/packages/core/src/render3/discovery_utils.ts b/packages/core/src/render3/discovery_utils.ts index 42e3e8b8cb..8fd4e4bb86 100644 --- a/packages/core/src/render3/discovery_utils.ts +++ b/packages/core/src/render3/discovery_utils.ts @@ -104,7 +104,7 @@ export function getDirectives(target: {}): Array<{}> { const context = loadContext(target) !; if (context.directives === undefined) { - context.directives = discoverDirectives(context.nodeIndex, context.lViewData); + context.directives = discoverDirectives(context.nodeIndex, context.lViewData, false); } return context.directives || []; diff --git a/packages/core/test/render3/compiler_canonical/query_spec.ts b/packages/core/test/render3/compiler_canonical/query_spec.ts index 8a4df8eb63..92065e04e5 100644 --- a/packages/core/test/render3/compiler_canonical/query_spec.ts +++ b/packages/core/test/render3/compiler_canonical/query_spec.ts @@ -9,7 +9,7 @@ import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ContentChildren, Directive, HostBinding, HostListener, Injectable, Input, NgModule, OnDestroy, Optional, Pipe, PipeTransform, QueryList, SimpleChanges, TemplateRef, ViewChild, ViewChildren, ViewContainerRef} from '../../../src/core'; import * as $r3$ from '../../../src/core_render3_private_export'; import {ComponentDef} from '../../../src/render3/interfaces/definition'; -import {renderComponent, toHtml} from '../render_util'; +import {getDirectiveOnNode, renderComponent, toHtml} from '../render_util'; /// See: `normative.md` @@ -161,7 +161,7 @@ describe('queries', () => { template: function MyApp_Template(rf: $RenderFlags$, ctx: $MyApp$) { if (rf & 1) { $r3$.ɵelementStart(0, 'content-query-component'); - contentQueryComp = $r3$.ɵloadDirective(0); + contentQueryComp = getDirectiveOnNode(0); $r3$.ɵelement(1, 'div', $e2_attrs$); $r3$.ɵelementEnd(); } diff --git a/packages/core/test/render3/content_spec.ts b/packages/core/test/render3/content_spec.ts index fe162f833e..0ebee9870a 100644 --- a/packages/core/test/render3/content_spec.ts +++ b/packages/core/test/render3/content_spec.ts @@ -9,11 +9,11 @@ import {SelectorFlags} from '@angular/core/src/render3/interfaces/projection'; import {AttributeMarker, detectChanges} from '../../src/render3/index'; -import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, loadDirective, projection, projectionDef, template, text} from '../../src/render3/instructions'; +import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementContainerEnd, elementContainerStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, projection, projectionDef, template, text} from '../../src/render3/instructions'; import {RenderFlags} from '../../src/render3/interfaces/definition'; import {NgIf} from './common_with_def'; -import {ComponentFixture, createComponent, renderComponent, toHtml} from './render_util'; +import {ComponentFixture, createComponent, getDirectiveOnNode, renderComponent, toHtml} from './render_util'; describe('content projection', () => { it('should project content', () => { @@ -452,7 +452,7 @@ describe('content projection', () => { elementEnd(); // testing - childCmptInstance = loadDirective(0); + childCmptInstance = getDirectiveOnNode(0); } }, 4, 0, [Child]); @@ -504,7 +504,7 @@ describe('content projection', () => { element(0, 'child'); // testing - childCmptInstance = loadDirective(0); + childCmptInstance = getDirectiveOnNode(0); } }, 1, 0, [Child]); @@ -556,7 +556,7 @@ describe('content projection', () => { if (rf & RenderFlags.Create) { elementStart(0, 'child'); { - childCmptInstance = loadDirective(0); + childCmptInstance = getDirectiveOnNode(0); text(1, 'content'); } elementEnd(); @@ -730,7 +730,7 @@ describe('content projection', () => { } elementEnd(); // testing - parent = loadDirective(0); + parent = getDirectiveOnNode(0); } }, 3, 0, [Parent]); @@ -786,7 +786,7 @@ describe('content projection', () => { if (rf & RenderFlags.Create) { elementStart(0, 'child'); { - childCmptInstance = loadDirective(0); + childCmptInstance = getDirectiveOnNode(0); text(1, 'content'); } elementEnd(); @@ -848,7 +848,7 @@ describe('content projection', () => { elementEnd(); // testing - child = loadDirective(0); + child = getDirectiveOnNode(0); } }, 4, 0, [Child]); @@ -913,7 +913,7 @@ describe('content projection', () => { elementEnd(); // testing - child = loadDirective(0); + child = getDirectiveOnNode(0); } }, 4, 0, [Child]); @@ -1012,7 +1012,7 @@ describe('content projection', () => { if (rf & RenderFlags.Create) { elementStart(0, 'child'); { - childCmptInstance = loadDirective(0); + childCmptInstance = getDirectiveOnNode(0); text(1, 'content'); } elementEnd(); diff --git a/packages/core/test/render3/di_spec.ts b/packages/core/test/render3/di_spec.ts index 77280629af..98f4d293d8 100644 --- a/packages/core/test/render3/di_spec.ts +++ b/packages/core/test/render3/di_spec.ts @@ -21,7 +21,7 @@ import {LViewFlags} from '../../src/render3/interfaces/view'; import {ViewRef} from '../../src/render3/view_ref'; import {getRendererFactory2} from './imported_renderer2'; -import {ComponentFixture, createComponent, createDirective, renderComponent, toHtml} from './render_util'; +import {ComponentFixture, createComponent, createDirective, getDirectiveOnNode, renderComponent, toHtml} from './render_util'; import {NgIf} from './common_with_def'; import {TNODE} from '../../src/render3/interfaces/injector'; @@ -1610,7 +1610,7 @@ describe('di', () => { ['myDirective', 'initial', 'exist', 'existValue', 'other', 'ignore']); } if (rf & RenderFlags.Update) { - myDirectiveInstance = loadDirective(0); + myDirectiveInstance = getDirectiveOnNode(0); } }, 1, 0, [MyDirective]); @@ -1631,7 +1631,7 @@ describe('di', () => { elementContainerEnd(); } if (rf & RenderFlags.Update) { - myDirectiveInstance = loadDirective(0); + myDirectiveInstance = getDirectiveOnNode(0); } }, 1, 0, [MyDirective]); diff --git a/packages/core/test/render3/pipe_spec.ts b/packages/core/test/render3/pipe_spec.ts index 360af2a2ef..19b95489dd 100644 --- a/packages/core/test/render3/pipe_spec.ts +++ b/packages/core/test/render3/pipe_spec.ts @@ -10,12 +10,12 @@ import {Directive, OnChanges, OnDestroy, Pipe, PipeTransform} from '@angular/cor import {expect} from '@angular/platform-browser/testing/src/matchers'; import {defineDirective, definePipe} from '../../src/render3/definition'; -import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, load, loadDirective, text, textBinding} from '../../src/render3/instructions'; +import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, interpolation1, load, text, textBinding} from '../../src/render3/instructions'; import {RenderFlags} from '../../src/render3/interfaces/definition'; import {pipe, pipeBind1, pipeBind3, pipeBind4, pipeBindV} from '../../src/render3/pipe'; import {RenderLog, getRendererFactory2, patchLoggingRenderer2} from './imported_renderer2'; -import {ComponentFixture, createComponent, renderToHtml} from './render_util'; +import {ComponentFixture, createComponent, getDirectiveOnNode, renderToHtml} from './render_util'; let log: string[] = []; @@ -100,7 +100,7 @@ describe('pipe', () => { } if (rf & RenderFlags.Update) { elementProperty(0, 'elprop', bind(pipeBind1(1, 1, ctx))); - directive = loadDirective(0); + directive = getDirectiveOnNode(0); } } renderToHtml(Template, 'a', 2, 3, [MyDir], [DoublePipe]); diff --git a/packages/core/test/render3/pure_function_spec.ts b/packages/core/test/render3/pure_function_spec.ts index f01c0f3548..e8851f8e4d 100644 --- a/packages/core/test/render3/pure_function_spec.ts +++ b/packages/core/test/render3/pure_function_spec.ts @@ -6,10 +6,10 @@ * found in the LICENSE file at https://angular.io/license */ import {AttributeMarker, defineComponent, template} from '../../src/render3/index'; -import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, loadDirective, nextContext} from '../../src/render3/instructions'; +import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, nextContext} from '../../src/render3/instructions'; import {RenderFlags} from '../../src/render3/interfaces/definition'; import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunction5, pureFunction6, pureFunction7, pureFunction8, pureFunctionV} from '../../src/render3/pure_function'; -import {ComponentFixture, createComponent, renderToHtml} from '../../test/render3/render_util'; +import {ComponentFixture, createComponent, getDirectiveOnNode, renderToHtml} from '../../test/render3/render_util'; import {NgIf} from './common_with_def'; describe('array literals', () => { @@ -176,7 +176,7 @@ describe('array literals', () => { template: function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'my-comp'); - myComps.push(loadDirective(0)); + myComps.push(getDirectiveOnNode(0)); elementEnd(); } if (rf & RenderFlags.Update) { @@ -275,22 +275,22 @@ describe('array literals', () => { function Template(rf: RenderFlags, c: any) { if (rf & RenderFlags.Create) { elementStart(0, 'my-comp'); - f3Comp = loadDirective(0); + f3Comp = getDirectiveOnNode(0); elementEnd(); elementStart(1, 'my-comp'); - f4Comp = loadDirective(1); + f4Comp = getDirectiveOnNode(1); elementEnd(); elementStart(2, 'my-comp'); - f5Comp = loadDirective(2); + f5Comp = getDirectiveOnNode(2); elementEnd(); elementStart(3, 'my-comp'); - f6Comp = loadDirective(3); + f6Comp = getDirectiveOnNode(3); elementEnd(); elementStart(4, 'my-comp'); - f7Comp = loadDirective(4); + f7Comp = getDirectiveOnNode(4); elementEnd(); elementStart(5, 'my-comp'); - f8Comp = loadDirective(5); + f8Comp = getDirectiveOnNode(5); elementEnd(); } if (rf & RenderFlags.Update) { @@ -513,7 +513,7 @@ describe('object literals', () => { let rf1 = embeddedViewStart(0, 1, 4); if (rf1 & RenderFlags.Create) { elementStart(0, 'object-comp'); - objectComps.push(loadDirective(0)); + objectComps.push(getDirectiveOnNode(0)); elementEnd(); } if (rf1 & RenderFlags.Update) { diff --git a/packages/core/test/render3/query_spec.ts b/packages/core/test/render3/query_spec.ts index 3e0f529400..9c15697b88 100644 --- a/packages/core/test/render3/query_spec.ts +++ b/packages/core/test/render3/query_spec.ts @@ -20,7 +20,7 @@ import {query, queryRefresh} from '../../src/render3/query'; import {templateRefExtractor} from '../../src/render3/view_engine_compatibility_prebound'; import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def'; -import {ComponentFixture, TemplateFixture, createComponent, createDirective, renderComponent} from './render_util'; +import {ComponentFixture, TemplateFixture, createComponent, createDirective, renderComponent, getDirectiveOnNode} from './render_util'; @@ -76,8 +76,8 @@ describe('query', () => { elementEnd(); } if (rf & RenderFlags.Update) { - child1 = loadDirective(0); - child2 = loadDirective(1); + child1 = getDirectiveOnNode(2); + child2 = getDirectiveOnNode(3); } }, 4, 0, [Child], [], @@ -151,7 +151,7 @@ describe('query', () => { function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(1, 'div', ['child', '', 'otherChild', '']); - { otherChildInstance = loadDirective(1); } + { otherChildInstance = getDirectiveOnNode(1, 1); } elementEnd(); } }, @@ -684,7 +684,7 @@ describe('query', () => { element(1, 'child', null, ['foo', '']); } if (rf & RenderFlags.Update) { - childInstance = loadDirective(0); + childInstance = getDirectiveOnNode(1); } }, 3, 0, [Child], [], @@ -767,7 +767,7 @@ describe('query', () => { element(1, 'div', ['child', ''], ['foo', 'child']); } if (rf & RenderFlags.Update) { - childInstance = loadDirective(0); + childInstance = getDirectiveOnNode(1); } }, 3, 0, [Child], [], @@ -806,8 +806,8 @@ describe('query', () => { element(1, 'div', ['child1', '', 'child2', ''], ['foo', 'child1', 'bar', 'child2']); } if (rf & RenderFlags.Update) { - child1Instance = loadDirective(0); - child2Instance = loadDirective(1); + child1Instance = getDirectiveOnNode(1, 0); + child2Instance = getDirectiveOnNode(1, 1); } }, 4, 0, [Child1, Child2], [], @@ -846,7 +846,7 @@ describe('query', () => { element(2, 'div', ['child', ''], ['foo', 'child', 'bar', 'child']); } if (rf & RenderFlags.Update) { - childInstance = loadDirective(0); + childInstance = getDirectiveOnNode(2); } }, 5, 0, [Child], [], @@ -928,7 +928,7 @@ describe('query', () => { div = loadElement(1).native; } if (rf & RenderFlags.Update) { - childInstance = loadDirective(0); + childInstance = getDirectiveOnNode(1); } }, 4, 0, [Child], [], diff --git a/packages/core/test/render3/render_util.ts b/packages/core/test/render3/render_util.ts index c251c69ce7..01370565e8 100644 --- a/packages/core/test/render3/render_util.ts +++ b/packages/core/test/render3/render_util.ts @@ -15,15 +15,16 @@ import {stringifyElement} from '@angular/platform-browser/testing/src/browser_ut import {Injector} from '../../src/di/injector'; import {R3_CHANGE_DETECTOR_REF_FACTORY, R3_ELEMENT_REF_FACTORY, R3_TEMPLATE_REF_FACTORY, R3_VIEW_CONTAINER_REF_FACTORY} from '../../src/ivy_switch/runtime/ivy_switch_on'; import {CreateComponentOptions} from '../../src/render3/component'; -import {getContext, isComponentInstance} from '../../src/render3/context_discovery'; +import {discoverDirectives, getContext, isComponentInstance} from '../../src/render3/context_discovery'; import {extractDirectiveDef, extractPipeDef} from '../../src/render3/definition'; import {NG_ELEMENT_ID} from '../../src/render3/fields'; import {ComponentTemplate, ComponentType, DirectiveDef, DirectiveType, PublicFeature, RenderFlags, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index'; -import {renderTemplate} from '../../src/render3/instructions'; +import {_getViewData, renderTemplate} from '../../src/render3/instructions'; import {DirectiveDefList, DirectiveTypesOrFactory, PipeDef, PipeDefList, PipeTypesOrFactory} from '../../src/render3/interfaces/definition'; import {LElementNode} from '../../src/render3/interfaces/node'; import {PlayerHandler} from '../../src/render3/interfaces/player'; import {RElement, RText, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer'; +import {HEADER_OFFSET} from '../../src/render3/interfaces/view'; import {Sanitizer} from '../../src/sanitization/security'; import {Type} from '../../src/type'; @@ -290,6 +291,15 @@ export function createDirective( }; } +/** Gets the directive on the given node at the given index */ +export function getDirectiveOnNode(nodeIndex: number, dirIndex: number = 0) { + const directives = discoverDirectives(nodeIndex + HEADER_OFFSET, _getViewData(), true); + if (directives == null) { + throw new Error(`No directives exist on node in slot ${nodeIndex}`); + } + return directives[dirIndex]; +} + // Verify that DOM is a type of render. This is here for error checking only and has no use. export const renderer: Renderer3 = null as any as Document; diff --git a/packages/core/test/render3/view_container_ref_spec.ts b/packages/core/test/render3/view_container_ref_spec.ts index 3049ef9a4c..99114210f0 100644 --- a/packages/core/test/render3/view_container_ref_spec.ts +++ b/packages/core/test/render3/view_container_ref_spec.ts @@ -19,7 +19,7 @@ import {pipe, pipeBind1} from '../../src/render3/pipe'; import {NgForOf} from '../../test/render3/common_with_def'; import {getRendererFactory2} from './imported_renderer2'; -import {ComponentFixture, TemplateFixture, createComponent} from './render_util'; +import {ComponentFixture, TemplateFixture, createComponent, getDirectiveOnNode} from './render_util'; describe('ViewContainerRef', () => { let directiveInstance: DirectiveWithVCRef|null; @@ -161,8 +161,8 @@ describe('ViewContainerRef', () => { element(3, 'div', ['vcref', '']); // for testing only: - firstDir = loadDirective(0); - secondDir = loadDirective(1); + firstDir = getDirectiveOnNode(2); + secondDir = getDirectiveOnNode(3); } function update() {