refactor(ivy): clean up TNode not depending on LView (#28354)
PR Close #28354
This commit is contained in:
parent
ef6728207b
commit
3d5a919ac5
@ -25,11 +25,11 @@ import {assertComponentType} from './assert';
|
|||||||
import {LifecycleHooksFeature, createRootComponent, createRootComponentView, createRootContext} from './component';
|
import {LifecycleHooksFeature, createRootComponent, createRootComponentView, createRootContext} from './component';
|
||||||
import {getComponentDef} from './definition';
|
import {getComponentDef} from './definition';
|
||||||
import {NodeInjector} from './di';
|
import {NodeInjector} from './di';
|
||||||
import {addToViewTree, createLView, createTView, createViewNode, elementCreate, locateHostElement, refreshDescendantViews} from './instructions';
|
import {addToViewTree, assignTViewNodeToLView, createLView, createTView, elementCreate, locateHostElement, refreshDescendantViews} from './instructions';
|
||||||
import {ComponentDef} from './interfaces/definition';
|
import {ComponentDef} from './interfaces/definition';
|
||||||
import {TContainerNode, TElementContainerNode, TElementNode} from './interfaces/node';
|
import {TContainerNode, TElementContainerNode, TElementNode} from './interfaces/node';
|
||||||
import {RNode, RendererFactory3, domRendererFactory3, isProceduralRenderer} from './interfaces/renderer';
|
import {RNode, RendererFactory3, domRendererFactory3, isProceduralRenderer} from './interfaces/renderer';
|
||||||
import {HEADER_OFFSET, LView, LViewFlags, RootContext} from './interfaces/view';
|
import {HEADER_OFFSET, LView, LViewFlags, RootContext, TVIEW} from './interfaces/view';
|
||||||
import {enterView, leaveView} from './state';
|
import {enterView, leaveView} from './state';
|
||||||
import {defaultScheduler, getTNode} from './util';
|
import {defaultScheduler, getTNode} from './util';
|
||||||
import {createElementRef} from './view_engine_compatibility';
|
import {createElementRef} from './view_engine_compatibility';
|
||||||
@ -242,7 +242,7 @@ export class ComponentRef<T> extends viewEngine_ComponentRef<T> {
|
|||||||
super();
|
super();
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.hostView = this.changeDetectorRef = new RootViewRef<T>(_rootLView);
|
this.hostView = this.changeDetectorRef = new RootViewRef<T>(_rootLView);
|
||||||
this.hostView._tViewNode = createViewNode(-1, _rootLView);
|
this.hostView._tViewNode = assignTViewNodeToLView(_rootLView[TVIEW], null, -1, _rootLView);
|
||||||
this.componentType = componentType;
|
this.componentType = componentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,17 +205,24 @@ export function createNodeAtIndex(
|
|||||||
assertLessThan(adjustedIndex, lView.length, `Slot should have been initialized with null`);
|
assertLessThan(adjustedIndex, lView.length, `Slot should have been initialized with null`);
|
||||||
lView[adjustedIndex] = native;
|
lView[adjustedIndex] = native;
|
||||||
|
|
||||||
|
const previousOrParentTNode = getPreviousOrParentTNode();
|
||||||
|
const isParent = getIsParent();
|
||||||
let tNode = tView.data[adjustedIndex] as TNode;
|
let tNode = tView.data[adjustedIndex] as TNode;
|
||||||
if (tNode == null) {
|
if (tNode == null) {
|
||||||
// TODO(misko): Refactor createTNode so that it does not depend on LView.
|
const parent =
|
||||||
tNode = tView.data[adjustedIndex] = createTNode(lView, type, adjustedIndex, name, attrs, null);
|
isParent ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent;
|
||||||
|
|
||||||
|
// Parents cannot cross component boundaries because components will be used in multiple places,
|
||||||
|
// so it's only set if the view is the same.
|
||||||
|
const parentInSameView = parent && parent !== lView[HOST_NODE];
|
||||||
|
const tParentNode = parentInSameView ? parent as TElementNode | TContainerNode : null;
|
||||||
|
|
||||||
|
tNode = tView.data[adjustedIndex] = createTNode(tParentNode, type, adjustedIndex, name, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now link ourselves into the tree.
|
// Now link ourselves into the tree.
|
||||||
// We need this even if tNode exists, otherwise we might end up pointing to unexisting tNodes when
|
// We need this even if tNode exists, otherwise we might end up pointing to unexisting tNodes when
|
||||||
// we use i18n (especially with ICU expressions that update the DOM during the update phase).
|
// we use i18n (especially with ICU expressions that update the DOM during the update phase).
|
||||||
const previousOrParentTNode = getPreviousOrParentTNode();
|
|
||||||
const isParent = getIsParent();
|
|
||||||
if (previousOrParentTNode) {
|
if (previousOrParentTNode) {
|
||||||
if (isParent && previousOrParentTNode.child == null &&
|
if (isParent && previousOrParentTNode.child == null &&
|
||||||
(tNode.parent !== null || previousOrParentTNode.type === TNodeType.View)) {
|
(tNode.parent !== null || previousOrParentTNode.type === TNodeType.View)) {
|
||||||
@ -236,14 +243,20 @@ export function createNodeAtIndex(
|
|||||||
TProjectionNode & TIcuContainerNode;
|
TProjectionNode & TIcuContainerNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createViewNode(index: number, view: LView) {
|
export function assignTViewNodeToLView(
|
||||||
|
tView: TView, tParentNode: TNode | null, index: number, lView: LView): TViewNode {
|
||||||
// View nodes are not stored in data because they can be added / removed at runtime (which
|
// View nodes are not stored in data because they can be added / removed at runtime (which
|
||||||
// would cause indices to change). Their TNodes are instead stored in tView.node.
|
// would cause indices to change). Their TNodes are instead stored in tView.node.
|
||||||
if (view[TVIEW].node == null) {
|
let tNode = tView.node;
|
||||||
view[TVIEW].node = createTNode(view, TNodeType.View, index, null, null, null) as TViewNode;
|
if (tNode == null) {
|
||||||
|
ngDevMode && tParentNode &&
|
||||||
|
assertNodeOfPossibleTypes(tParentNode, TNodeType.Element, TNodeType.Container);
|
||||||
|
tView.node = tNode = createTNode(
|
||||||
|
tParentNode as TElementNode | TContainerNode | null, //
|
||||||
|
TNodeType.View, index, null, null) as TViewNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
return view[HOST_NODE] = view[TVIEW].node as TViewNode;
|
return lView[HOST_NODE] = tNode as TViewNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -323,7 +336,7 @@ export function createEmbeddedViewAndNode<T>(
|
|||||||
if (queries) {
|
if (queries) {
|
||||||
lView[QUERIES] = queries.createView();
|
lView[QUERIES] = queries.createView();
|
||||||
}
|
}
|
||||||
createViewNode(-1, lView);
|
assignTViewNodeToLView(tView, null, -1, lView);
|
||||||
|
|
||||||
if (tView.firstTemplatePass) {
|
if (tView.firstTemplatePass) {
|
||||||
tView.node !.injectorIndex = injectorIndex;
|
tView.node !.injectorIndex = injectorIndex;
|
||||||
@ -1221,18 +1234,9 @@ function savePropertyDebugData(
|
|||||||
* @returns the TNode object
|
* @returns the TNode object
|
||||||
*/
|
*/
|
||||||
export function createTNode(
|
export function createTNode(
|
||||||
lView: LView, type: TNodeType, adjustedIndex: number, tagName: string | null,
|
tParent: TElementNode | TContainerNode | null, type: TNodeType, adjustedIndex: number,
|
||||||
attrs: TAttributes | null, tViews: TView[] | null): TNode {
|
tagName: string | null, attrs: TAttributes | null): TNode {
|
||||||
const previousOrParentTNode = getPreviousOrParentTNode();
|
|
||||||
ngDevMode && ngDevMode.tNode++;
|
ngDevMode && ngDevMode.tNode++;
|
||||||
const parent =
|
|
||||||
getIsParent() ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent;
|
|
||||||
|
|
||||||
// Parents cannot cross component boundaries because components will be used in multiple places,
|
|
||||||
// so it's only set if the view is the same.
|
|
||||||
const parentInSameView = parent && lView && parent !== lView[HOST_NODE];
|
|
||||||
const tParent = parentInSameView ? parent as TElementNode | TContainerNode : null;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: type,
|
type: type,
|
||||||
index: adjustedIndex,
|
index: adjustedIndex,
|
||||||
@ -1249,7 +1253,7 @@ export function createTNode(
|
|||||||
initialInputs: undefined,
|
initialInputs: undefined,
|
||||||
inputs: undefined,
|
inputs: undefined,
|
||||||
outputs: undefined,
|
outputs: undefined,
|
||||||
tViews: tViews,
|
tViews: null,
|
||||||
next: null,
|
next: null,
|
||||||
child: null,
|
child: null,
|
||||||
parent: tParent,
|
parent: tParent,
|
||||||
@ -2286,7 +2290,9 @@ export function embeddedViewStart(viewBlockId: number, consts: number, vars: num
|
|||||||
viewToRender[QUERIES] = lContainer[QUERIES] !.createView();
|
viewToRender[QUERIES] = lContainer[QUERIES] !.createView();
|
||||||
}
|
}
|
||||||
|
|
||||||
createViewNode(viewBlockId, viewToRender);
|
const tParentNode = getIsParent() ? previousOrParentTNode :
|
||||||
|
previousOrParentTNode && previousOrParentTNode.parent;
|
||||||
|
assignTViewNodeToLView(viewToRender[TVIEW], tParentNode, viewBlockId, viewToRender);
|
||||||
enterView(viewToRender, viewToRender[TVIEW].node);
|
enterView(viewToRender, viewToRender[TVIEW].node);
|
||||||
}
|
}
|
||||||
if (lContainer) {
|
if (lContainer) {
|
||||||
|
@ -380,6 +380,9 @@
|
|||||||
{
|
{
|
||||||
"name": "assertTemplate"
|
"name": "assertTemplate"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "assignTViewNodeToLView"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "attachPatchData"
|
"name": "attachPatchData"
|
||||||
},
|
},
|
||||||
@ -482,9 +485,6 @@
|
|||||||
{
|
{
|
||||||
"name": "createViewBlueprint"
|
"name": "createViewBlueprint"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "createViewNode"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "decreaseElementDepthCount"
|
"name": "decreaseElementDepthCount"
|
||||||
},
|
},
|
||||||
|
@ -12,17 +12,16 @@ import {CssSelector, CssSelectorList, NG_PROJECT_AS_ATTR_NAME, SelectorFlags,} f
|
|||||||
import {getProjectAsAttrValue, isNodeMatchingSelectorList, isNodeMatchingSelector} from '../../src/render3/node_selector_matcher';
|
import {getProjectAsAttrValue, isNodeMatchingSelectorList, isNodeMatchingSelector} from '../../src/render3/node_selector_matcher';
|
||||||
import {initializeStaticContext} from '../../src/render3/styling/class_and_style_bindings';
|
import {initializeStaticContext} from '../../src/render3/styling/class_and_style_bindings';
|
||||||
import {createTNode} from '@angular/core/src/render3/instructions';
|
import {createTNode} from '@angular/core/src/render3/instructions';
|
||||||
import {getLView} from '@angular/core/src/render3/state';
|
|
||||||
|
|
||||||
function testLStaticData(tagName: string, attrs: TAttributes | null): TNode {
|
function testLStaticData(tagName: string, attrs: TAttributes | null): TNode {
|
||||||
return createTNode(getLView(), TNodeType.Element, 0, tagName, attrs, null);
|
return createTNode(null, TNodeType.Element, 0, tagName, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('css selector matching', () => {
|
describe('css selector matching', () => {
|
||||||
function isMatching(
|
function isMatching(
|
||||||
tagName: string, attrsOrTNode: TAttributes | TNode | null, selector: CssSelector): boolean {
|
tagName: string, attrsOrTNode: TAttributes | TNode | null, selector: CssSelector): boolean {
|
||||||
const tNode = (!attrsOrTNode || Array.isArray(attrsOrTNode)) ?
|
const tNode = (!attrsOrTNode || Array.isArray(attrsOrTNode)) ?
|
||||||
createTNode(getLView(), TNodeType.Element, 0, tagName, attrsOrTNode as TAttributes, null) :
|
createTNode(null, TNodeType.Element, 0, tagName, attrsOrTNode as TAttributes) :
|
||||||
(attrsOrTNode as TNode);
|
(attrsOrTNode as TNode);
|
||||||
return isNodeMatchingSelector(tNode, selector, false);
|
return isNodeMatchingSelector(tNode, selector, false);
|
||||||
}
|
}
|
||||||
@ -307,7 +306,7 @@ describe('css selector matching', () => {
|
|||||||
() => {
|
() => {
|
||||||
// selector: 'div.abc'
|
// selector: 'div.abc'
|
||||||
const selector = ['div', SelectorFlags.CLASS, 'abc'];
|
const selector = ['div', SelectorFlags.CLASS, 'abc'];
|
||||||
const tNode = createTNode(getLView(), TNodeType.Element, 0, 'div', [], null);
|
const tNode = createTNode(null, TNodeType.Element, 0, 'div', []);
|
||||||
|
|
||||||
// <div> (without attrs or styling context)
|
// <div> (without attrs or styling context)
|
||||||
expect(isMatching('div', tNode, selector)).toBeFalsy();
|
expect(isMatching('div', tNode, selector)).toBeFalsy();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user