refactor(ivy): simplify walkTNodeTree method for readability (#31182)
PR Close #31182
This commit is contained in:
committed by
Kara Erickson
parent
7186f9c016
commit
29a9909232
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user