From fdaf573073d20d6b19f1bebcdef8eb2f854a4f12 Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Tue, 2 Oct 2018 14:42:34 +0200 Subject: [PATCH] feat(ivy): expose node injector as part of debug context (#26210) PR Close #26210 --- packages/core/src/render3/discovery_utils.ts | 14 ++-- packages/core/src/render3/instructions.ts | 3 +- packages/core/src/render3/util.ts | 2 +- .../bundle.golden_symbols.json | 4 +- .../core/test/render3/discovery_utils_spec.ts | 67 ++++++++++--------- 5 files changed, 46 insertions(+), 44 deletions(-) diff --git a/packages/core/src/render3/discovery_utils.ts b/packages/core/src/render3/discovery_utils.ts index 38f57d1381..0952d7f4ce 100644 --- a/packages/core/src/render3/discovery_utils.ts +++ b/packages/core/src/render3/discovery_utils.ts @@ -9,9 +9,9 @@ import {Injector} from '../di/injector'; import {assertDefined} from './assert'; import {LContext, discoverDirectiveIndices, discoverDirectives, discoverLocalRefs, getContext, isComponentInstance, readPatchedLViewData} from './context_discovery'; -import {LElementNode, TNode, TNodeFlags} from './interfaces/node'; -import {CONTEXT, FLAGS, INJECTOR, LViewData, LViewFlags, PARENT, RootContext, TVIEW} from './interfaces/view'; - +import {NodeInjector} from './di'; +import {LElementNode, TElementNode, TNode, TNodeFlags} from './interfaces/node'; +import {CONTEXT, FLAGS, LViewData, LViewFlags, PARENT, RootContext, TVIEW} from './interfaces/view'; /** * NOTE: The following functions might not be ideal for core usage in Angular... @@ -89,9 +89,11 @@ export function getRootComponents(target: {}): any[] { * Returns the injector instance that is associated with * the element, component or directive. */ -export function getInjector(target: {}): Injector|null { - const context = loadContext(target) !; - return context.lViewData[INJECTOR] || null; +export function getInjector(target: {}): Injector { + const context = loadContext(target); + const tNode = context.lViewData[TVIEW].data[context.lNodeIndex] as TElementNode; + + return new NodeInjector(tNode, context.lViewData); } /** diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts index dd2a835f38..e98db205ee 100644 --- a/packages/core/src/render3/instructions.ts +++ b/packages/core/src/render3/instructions.ts @@ -14,7 +14,6 @@ import {StyleSanitizeFn} from '../sanitization/style_sanitizer'; import {assertDefined, assertEqual, assertLessThan, assertNotEqual} from './assert'; import {attachPatchData, getLElementFromComponent, readElementValue, readPatchedLViewData} from './context_discovery'; -import {getRootView} from './discovery_utils'; import {throwCyclicDependencyError, throwErrorIfNoChangesMode, throwMultipleComponentError} from './errors'; import {executeHooks, executeInitHooks, queueInitHooks, queueLifecycleHooks} from './hooks'; import {ACTIVE_INDEX, LContainer, RENDER_PARENT, VIEWS} from './interfaces/container'; @@ -29,7 +28,7 @@ import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert'; import {appendChild, appendProjectedNode, createTextNode, findComponentView, getHostElementNode, getLViewChild, getRenderParent, insertView, removeView} from './node_manipulation'; import {isNodeMatchingSelectorList, matchingSelectorIndex} from './node_selector_matcher'; import {allocStylingContext, createStylingContextTemplate, renderStyling as renderElementStyles, updateClassProp as updateElementClassProp, updateStyleProp as updateElementStyleProp, updateStylingMap} from './styling/class_and_style_bindings'; -import {assertDataInRangeInternal, getLNode, isContentQueryHost, isDifferent, loadElementInternal, loadInternal, stringify} from './util'; +import {assertDataInRangeInternal, getLNode, getRootView, isContentQueryHost, isDifferent, loadElementInternal, loadInternal, stringify} from './util'; /** diff --git a/packages/core/src/render3/util.ts b/packages/core/src/render3/util.ts index daea22df88..1036ed829c 100644 --- a/packages/core/src/render3/util.ts +++ b/packages/core/src/render3/util.ts @@ -11,7 +11,7 @@ import {devModeEqual} from '../change_detection/change_detection_util'; import {assertDefined, assertLessThan} from './assert'; import {readElementValue, readPatchedLViewData} from './context_discovery'; import {LContainerNode, LElementContainerNode, LElementNode, TNode, TNodeFlags} from './interfaces/node'; -import {CONTEXT, FLAGS, HEADER_OFFSET, LViewData, LViewFlags, PARENT, RootContext, TData} from './interfaces/view'; +import {CONTEXT, FLAGS, HEADER_OFFSET, LViewData, LViewFlags, PARENT, RootContext, TData, TVIEW} from './interfaces/view'; diff --git a/packages/core/test/bundling/animation_world/bundle.golden_symbols.json b/packages/core/test/bundling/animation_world/bundle.golden_symbols.json index 4008c148b1..0bb9a92705 100644 --- a/packages/core/test/bundling/animation_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/animation_world/bundle.golden_symbols.json @@ -666,10 +666,10 @@ "name": "getRendererFactory" }, { - "name": "getRootContext$1" + "name": "getRootContext" }, { - "name": "getRootView$1" + "name": "getRootView" }, { "name": "getStyleSanitizer" diff --git a/packages/core/test/render3/discovery_utils_spec.ts b/packages/core/test/render3/discovery_utils_spec.ts index d8203603bb..c9061d9fe3 100644 --- a/packages/core/test/render3/discovery_utils_spec.ts +++ b/packages/core/test/render3/discovery_utils_spec.ts @@ -7,7 +7,7 @@ */ import {StaticInjector} from '../../src/di/injector'; import {getComponent, getDirectives, getHostComponent, getInjector, getLocalRefs, getRootComponents} from '../../src/render3/discovery_utils'; -import {RenderFlags, defineComponent, defineDirective} from '../../src/render3/index'; +import {PublicFeature, RenderFlags, defineComponent, defineDirective} from '../../src/render3/index'; import {element, elementEnd, elementStart, elementStyling, elementStylingApply} from '../../src/render3/instructions'; import {ComponentFixture} from './render_util'; @@ -220,50 +220,51 @@ describe('discovery utils', () => { }); }); - describe('getInjector()', () => { - it('should return the instance of the injector that was passed into the component', () => { + describe('getInjector', () => { + + it('should return an injector that can return directive instances', () => { + class Comp { static ngComponentDef = defineComponent({ type: Comp, selectors: [['comp']], factory: () => new Comp(), - consts: 1, + consts: 0, vars: 0, - template: (rf: RenderFlags, ctx: Comp) => { - if (rf & RenderFlags.Create) { - element(0, 'div'); - } - } - }); - } - - const injector = new StaticInjector([]); - const fixture = new ComponentFixture(Comp, {injector}); - fixture.update(); - - expect(getInjector(fixture.hostElement) !).toBe(injector); - }); - - it('should return null when there is no injector passed into a component', () => { - class Comp { - static ngComponentDef = defineComponent({ - type: Comp, - selectors: [['comp']], - factory: () => new Comp(), - consts: 1, - vars: 0, - template: (rf: RenderFlags, ctx: Comp) => { - if (rf & RenderFlags.Create) { - element(0, 'div'); - } - } + template: (rf: RenderFlags, ctx: Comp) => {}, + features: [PublicFeature] }); } const fixture = new ComponentFixture(Comp); fixture.update(); - expect(getInjector(fixture.hostElement)).toEqual(null); + const nodeInjector = getInjector(fixture.hostElement); + expect(nodeInjector.get(Comp)).toEqual(jasmine.any(Comp)); + }); + + it('should return an injector that falls-back to a module injector', () => { + + class Comp { + static ngComponentDef = defineComponent({ + type: Comp, + selectors: [['comp']], + factory: () => new Comp(), + consts: 0, + vars: 0, + template: (rf: RenderFlags, ctx: Comp) => {}, + features: [PublicFeature] + }); + } + + class TestToken {} + + const staticInjector = new StaticInjector([{provide: TestToken, useValue: new TestToken()}]); + const fixture = new ComponentFixture(Comp, {injector: staticInjector}); + fixture.update(); + + const nodeInjector = getInjector(fixture.hostElement); + expect(nodeInjector.get(TestToken)).toEqual(jasmine.any(TestToken)); }); });