refactor(core): Add injector debug information to LViewDebug (#38707)

Extended the `LViewDebug` to display node-injector information for each
node.

PR Close #38707
This commit is contained in:
Misko Hevery
2020-09-04 16:55:51 -07:00
parent bc6ff7745e
commit b613639e8a
7 changed files with 316 additions and 37 deletions

View File

@ -6,6 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdirectiveInject, ɵɵProvidersFeature} from '@angular/core/src/core';
import {ɵɵelement, ɵɵelementEnd, ɵɵelementStart} from '@angular/core/src/render3/instructions/element';
import {TNodeDebug} from '@angular/core/src/render3/instructions/lview_debug';
import {createTNode, createTView} from '@angular/core/src/render3/instructions/shared';
import {TNodeType} from '@angular/core/src/render3/interfaces/node';
@ -13,7 +15,7 @@ import {LView, TView, TViewType} from '@angular/core/src/render3/interfaces/view
import {enterView, leaveView} from '@angular/core/src/render3/state';
import {insertTStylingBinding} from '@angular/core/src/render3/styling/style_binding_list';
import {KeyValueArray} from '@angular/core/src/util/array_utils';
import {TemplateFixture} from '../render_util';
describe('lView_debug', () => {
const mockFirstUpdatePassLView: LView = [null, {firstUpdatePass: true}] as any;
@ -151,4 +153,88 @@ describe('lView_debug', () => {
});
});
});
describe('di', () => {
it('should show basic information', () => {
class DepA {
static ɵfac = () => new DepA();
}
class DepB {
static ɵfac = () => new DepB();
}
const instances: any[] = [];
class MyComponent {
constructor(public depA: DepA, public depB: DepB) {
instances.push(this);
}
static ɵfac = () => new MyComponent(ɵɵdirectiveInject(DepA), ɵɵdirectiveInject(DepB));
static ɵcmp = ɵɵdefineComponent({
type: MyComponent,
selectors: [['my-comp']],
decls: 1,
vars: 0,
template: function() {},
features: [ɵɵProvidersFeature(
[DepA, {provide: String, useValue: 'String'}],
[DepB, {provide: Number, useValue: 123}])]
});
}
let myChild!: MyChild;
class MyChild {
constructor() {
myChild = this;
}
static ɵfac = () => new MyChild();
static ɵdir = ɵɵdefineDirective({
type: MyChild,
selectors: [['my-child']],
});
}
class MyDirective {
constructor(public myComp: MyComponent) {
instances.push(this);
}
static ɵfac = () => new MyDirective(ɵɵdirectiveInject(MyComponent));
static ɵdir = ɵɵdefineDirective({
type: MyDirective,
selectors: [['', 'my-dir', '']],
});
}
const fixture = new TemplateFixture(
() => {
ɵɵelementStart(0, 'my-comp', 0);
ɵɵelement(1, 'my-child');
ɵɵelementEnd();
},
() => null, 2, 0, [MyComponent, MyDirective, MyChild], null, null, undefined,
[['my-dir', '']]);
const lView = fixture.hostView;
const lViewDebug = lView.debug!;
const myCompNode = lViewDebug.nodes[0];
expect(myCompNode.factories).toEqual([MyComponent, MyDirective]);
expect(myCompNode.instances).toEqual(instances);
expect(myCompNode.injector).toEqual({
bloom: jasmine.anything(),
cumulativeBloom: jasmine.anything(),
providers: [DepA, String, MyComponent.ɵcmp, MyDirective.ɵdir],
viewProviders: [DepB, Number],
parentInjectorIndex: -1,
});
const myChildNode = myCompNode.children[0];
expect(myChildNode.factories).toEqual([MyChild]);
expect(myChildNode.instances).toEqual([myChild]);
expect(myChildNode.injector).toEqual({
bloom: jasmine.anything(),
cumulativeBloom: jasmine.anything(),
providers: [MyChild.ɵdir],
viewProviders: [],
parentInjectorIndex: 22,
});
});
});
});