refactor(ivy): simplify walkTNodeTree method for readability (#31182)

PR Close #31182
This commit is contained in:
Misko Hevery
2019-06-25 17:03:51 -07:00
committed by Kara Erickson
parent 7186f9c016
commit 29a9909232
7 changed files with 342 additions and 195 deletions
+1 -1
View File
@@ -438,7 +438,7 @@ export interface TNode {
* - This would return the first head node to project:
* `getHost(currentTNode).projection[currentTNode.projection]`.
* - When projecting nodes the parent node retrieved may be a `<ng-content>` node, in which case
* the process is recursive in nature (not implementation).
* the process is recursive in nature.
*
* If `projection` is of type `RNode[][]` than we have a collection of native nodes passed as
* projectable nodes during dynamic component creation.
+1 -1
View File
@@ -357,7 +357,7 @@ export interface TView {
viewQuery: ViewQueriesFunction<{}>|null;
/**
* Pointer to the `TNode` that represents the root of the view.
* Pointer to the host `TNode` (not part of this TView).
*
* If this is a `TViewNode` for an `LViewNode`, this is an embedded view of a container.
* We need this pointer to be able to efficiently find this node when inserting the view
File diff suppressed because it is too large Load Diff
@@ -42,7 +42,12 @@ export function getRootView(componentOrLView: LView | {}): LView {
}
/**
* Given a current view, finds the nearest component's host (LElement).
* Given an `LView`, find the closest declaration view which is not an embedded view.
*
* This method searches for the `LView` associated with the component which declared the `LView`.
*
* This function may return itself if the `LView` passed in is not an embedded `LView`. Otherwise
* it walks the declaration parents until it finds a component view (non-embedded-view.)
*
* @param lView LView for which we want a host element node
* @returns The host node
+3 -1
View File
@@ -10,6 +10,8 @@
// about state in an instruction are correct before implementing any logic.
// They are meant only to be called in dev mode as sanity checks.
import {stringify} from './stringify';
export function assertNumber(actual: any, msg: string) {
if (typeof actual != 'number') {
throwError(msg);
@@ -75,7 +77,7 @@ export function assertDomNode(node: any) {
assertEqual(
(typeof Node !== 'undefined' && node instanceof Node) ||
(typeof node === 'object' && node.constructor.name === 'WebWorkerRenderNode'),
true, 'The provided value must be an instance of a DOM Node');
true, `The provided value must be an instance of a DOM Node but got ${stringify(node)}`);
}
@@ -346,6 +346,101 @@ describe('projection', () => {
expect(fixture.nativeElement.querySelectorAll('div').length).toBe(3);
});
it('should handle projection into element containers at the view root', () => {
@Component({
selector: 'root-comp',
template: `
<ng-template [ngIf]="show">
<ng-container>
<ng-content></ng-content>
</ng-container>
</ng-template>`,
})
class RootComp {
@Input() show: boolean = true;
}
@Component({
selector: 'my-app',
template: `<root-comp [show]="show"><div></div></root-comp>
`
})
class MyApp {
show = true;
}
TestBed.configureTestingModule({declarations: [MyApp, RootComp]});
const fixture = TestBed.createComponent(MyApp);
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('div').length).toBe(1);
fixture.componentInstance.show = false;
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('div').length).toBe(0);
});
it('should handle projection of views with element containers at the root', () => {
@Component({
selector: 'root-comp',
template: `<ng-template [ngIf]="show"><ng-content></ng-content></ng-template>`,
})
class RootComp {
@Input() show: boolean = true;
}
@Component({
selector: 'my-app',
template: `<root-comp [show]="show"><ng-container><div></div></ng-container></root-comp>`
})
class MyApp {
show = true;
}
TestBed.configureTestingModule({declarations: [MyApp, RootComp]});
const fixture = TestBed.createComponent(MyApp);
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('div').length).toBe(1);
fixture.componentInstance.show = false;
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('div').length).toBe(0);
});
it('should handle re-projection at the root of an embedded view', () => {
@Component({
selector: 'child-comp',
template: `<ng-template [ngIf]="show"><ng-content></ng-content></ng-template>`,
})
class ChildComp {
@Input() show: boolean = true;
}
@Component({
selector: 'parent-comp',
template: `<child-comp [show]="show"><ng-content></ng-content></child-comp>`
})
class ParentComp {
@Input() show: boolean = true;
}
@Component(
{selector: 'my-app', template: `<parent-comp [show]="show"><div></div></parent-comp>`})
class MyApp {
show = true;
}
TestBed.configureTestingModule({declarations: [MyApp, ParentComp, ChildComp]});
const fixture = TestBed.createComponent(MyApp);
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('div').length).toBe(1);
fixture.componentInstance.show = false;
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('div').length).toBe(0);
});
describe('with selectors', () => {
// https://stackblitz.com/edit/angular-psokum?file=src%2Fapp%2Fapp.module.ts
it('should project nodes where attribute selector matches a binding', () => {
@@ -485,15 +485,27 @@
{
"name": "applyClasses"
},
{
"name": "applyContainer"
},
{
"name": "applyElementContainer"
},
{
"name": "applyOnCreateInstructions"
},
{
"name": "applyProjection"
},
{
"name": "applyStyles"
},
{
"name": "applyStyling"
},
{
"name": "applyView"
},
{
"name": "assertTemplate"
},
@@ -1280,9 +1292,6 @@
{
"name": "prepareInitialFlag"
},
{
"name": "projectionNodeStack"
},
{
"name": "queueComponentIndexForCheck"
},
@@ -1571,9 +1580,6 @@
{
"name": "viewAttachedToContainer"
},
{
"name": "walkTNodeTree"
},
{
"name": "walkUpViews"
},