Skip to content

Commit 21e8ac1

Browse files
mheveryjasonaden
authored andcommitted
refactor(ivy): createNodeAtIndex no longer depends on L* (angular#30453)
PR Close angular#30453
1 parent 01cf04c commit 21e8ac1

File tree

13 files changed

+111
-83
lines changed

13 files changed

+111
-83
lines changed

packages/core/src/render3/component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {assertComponentType} from './assert';
1717
import {getComponentDef} from './definition';
1818
import {diPublicInInjector, getOrCreateNodeInjectorForNode} from './di';
1919
import {registerPostOrderHooks, registerPreOrderHooks} from './hooks';
20-
import {CLEAN_PROMISE, addToViewTree, createLView, createNodeAtIndex, createTView, getOrCreateTView, initNodeFlags, instantiateRootComponent, invokeHostBindingsInCreationMode, locateHostElement, queueComponentIndexForCheck, refreshDescendantViews} from './instructions/shared';
20+
import {CLEAN_PROMISE, addToViewTree, createLView, createTView, getOrCreateTNode, getOrCreateTView, initNodeFlags, instantiateRootComponent, invokeHostBindingsInCreationMode, locateHostElement, queueComponentIndexForCheck, refreshDescendantViews} from './instructions/shared';
2121
import {ComponentDef, ComponentType, RenderFlags} from './interfaces/definition';
2222
import {TElementNode, TNode, TNodeFlags, TNodeType} from './interfaces/node';
2323
import {PlayerHandler} from './interfaces/player';
@@ -175,7 +175,7 @@ export function createRootComponentView(
175175
const tView = rootView[TVIEW];
176176
ngDevMode && assertDataInRange(rootView, 0 + HEADER_OFFSET);
177177
rootView[0 + HEADER_OFFSET] = rNode;
178-
const tNode: TElementNode = createNodeAtIndex(0, TNodeType.Element, null, null);
178+
const tNode: TElementNode = getOrCreateTNode(tView, null, 0, TNodeType.Element, null, null);
179179
const componentView = createLView(
180180
rootView, getOrCreateTView(def), null, def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways,
181181
rootView[HEADER_OFFSET], tNode, rendererFactory, renderer, sanitizer);

packages/core/src/render3/i18n.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {assertDataInRange, assertDefined, assertEqual, assertGreaterThan} from '
1717
import {attachPatchData} from './context_discovery';
1818
import {attachI18nOpCodesDebug} from './debug';
1919
import {ɵɵelementAttribute, ɵɵload, ɵɵtextBinding} from './instructions/all';
20-
import {allocExpando, createNodeAtIndex} from './instructions/shared';
20+
import {allocExpando, getOrCreateTNode} from './instructions/shared';
2121
import {LContainer, NATIVE} from './interfaces/container';
2222
import {COMMENT_MARKER, ELEMENT_MARKER, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuType, TI18n, TIcu} from './interfaces/i18n';
2323
import {TElementNode, TIcuContainerNode, TNode, TNodeType} from './interfaces/node';
@@ -676,7 +676,7 @@ function createDynamicNodeAtIndex(
676676
const previousOrParentTNode = getPreviousOrParentTNode();
677677
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
678678
lView[index + HEADER_OFFSET] = native;
679-
const tNode = createNodeAtIndex(index, type as any, name, null);
679+
const tNode = getOrCreateTNode(lView[TVIEW], lView[T_HOST], index, type as any, name, null);
680680

681681
// We are creating a dynamic node, the previous tNode might not be pointing at this node.
682682
// We will link ourselves into the tree later with `appendI18nNode`.

packages/core/src/render3/instructions/container.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import {executePreOrderHooks, registerPostOrderHooks} from '../hooks';
1212
import {ACTIVE_INDEX, CONTAINER_HEADER_OFFSET, LContainer} from '../interfaces/container';
1313
import {ComponentTemplate} from '../interfaces/definition';
1414
import {LocalRefExtractor, TAttributes, TContainerNode, TNode, TNodeType} from '../interfaces/node';
15-
import {BINDING_INDEX, HEADER_OFFSET, LView, QUERIES, RENDERER, TVIEW} from '../interfaces/view';
15+
import {BINDING_INDEX, HEADER_OFFSET, LView, QUERIES, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
1616
import {assertNodeType} from '../node_assert';
1717
import {appendChild, removeView} from '../node_manipulation';
1818
import {getCheckNoChangesMode, getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
1919
import {getNativeByTNode, loadInternal} from '../util/view_utils';
20-
import {addToViewTree, createDirectivesAndLocals, createLContainer, createNodeAtIndex, createTView} from './shared';
20+
21+
import {addToViewTree, createDirectivesAndLocals, createLContainer, createTView, getOrCreateTNode} from './shared';
22+
2123

2224
/**
2325
* Creates an LContainer for inline views, e.g.
@@ -168,7 +170,8 @@ function containerInternal(
168170
ngDevMode && ngDevMode.rendererCreateComment++;
169171
const comment = lView[index + HEADER_OFFSET] =
170172
lView[RENDERER].createComment(ngDevMode ? 'container' : '');
171-
const tNode = createNodeAtIndex(index, TNodeType.Container, tagName, attrs);
173+
const tNode =
174+
getOrCreateTNode(lView[TVIEW], lView[T_HOST], index, TNodeType.Container, tagName, attrs);
172175
const lContainer = lView[adjustedIndex] =
173176
createLContainer(lView[adjustedIndex], lView, comment, tNode);
174177

packages/core/src/render3/instructions/element.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {TAttributes, TNodeFlags, TNodeType} from '../interfaces/node';
1414
import {RElement, isProceduralRenderer} from '../interfaces/renderer';
1515
import {SanitizerFn} from '../interfaces/sanitization';
1616
import {StylingContext} from '../interfaces/styling';
17-
import {BINDING_INDEX, HEADER_OFFSET, QUERIES, RENDERER, TVIEW} from '../interfaces/view';
17+
import {BINDING_INDEX, HEADER_OFFSET, QUERIES, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
1818
import {assertNodeType} from '../node_assert';
1919
import {appendChild} from '../node_manipulation';
2020
import {applyOnCreateInstructions} from '../node_util';
@@ -27,10 +27,12 @@ import {NO_CHANGE} from '../tokens';
2727
import {attrsStylingIndexOf, setUpAttributes} from '../util/attrs_utils';
2828
import {renderStringify} from '../util/misc_utils';
2929
import {getNativeByIndex, getNativeByTNode, getTNode} from '../util/view_utils';
30-
import {createDirectivesAndLocals, createNodeAtIndex, elementCreate, executeContentQueries, initializeTNodeInputs, setInputsForProperty, setNodeStylingTemplate} from './shared';
30+
31+
import {createDirectivesAndLocals, elementCreate, executeContentQueries, getOrCreateTNode, initializeTNodeInputs, setInputsForProperty, setNodeStylingTemplate} from './shared';
3132
import {getActiveDirectiveStylingIndex} from './styling';
3233

3334

35+
3436
/**
3537
* Create DOM element. The instruction must later be followed by `elementEnd()` call.
3638
*
@@ -58,7 +60,8 @@ export function ɵɵelementStart(
5860
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
5961
const native = lView[index + HEADER_OFFSET] = elementCreate(name);
6062
const renderer = lView[RENDERER];
61-
const tNode = createNodeAtIndex(index, TNodeType.Element, name, attrs || null);
63+
const tNode =
64+
getOrCreateTNode(tView, lView[T_HOST], index, TNodeType.Element, name, attrs || null);
6265
let initialStylesIndex = 0;
6366
let initialClassesIndex = 0;
6467

packages/core/src/render3/instructions/element_container.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import {assertHasParent} from '../assert';
1010
import {attachPatchData} from '../context_discovery';
1111
import {registerPostOrderHooks} from '../hooks';
1212
import {TAttributes, TNodeType} from '../interfaces/node';
13-
import {BINDING_INDEX, HEADER_OFFSET, QUERIES, RENDERER, TVIEW} from '../interfaces/view';
13+
import {BINDING_INDEX, HEADER_OFFSET, QUERIES, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
1414
import {assertNodeType} from '../node_assert';
1515
import {appendChild} from '../node_manipulation';
1616
import {applyOnCreateInstructions} from '../node_util';
1717
import {getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from '../state';
1818

19-
import {createDirectivesAndLocals, createNodeAtIndex, executeContentQueries, setNodeStylingTemplate} from './shared';
19+
import {createDirectivesAndLocals, executeContentQueries, getOrCreateTNode, setNodeStylingTemplate} from './shared';
20+
2021

2122
/**
2223
* Creates a logical container for other nodes (<ng-container>) backed by a comment node in the DOM.
@@ -47,7 +48,8 @@ export function ɵɵelementContainerStart(
4748
const native = lView[index + HEADER_OFFSET] = renderer.createComment(ngDevMode ? tagName : '');
4849

4950
ngDevMode && assertDataInRange(lView, index - 1);
50-
const tNode = createNodeAtIndex(index, TNodeType.ElementContainer, tagName, attrs || null);
51+
const tNode = getOrCreateTNode(
52+
tView, lView[T_HOST], index, TNodeType.ElementContainer, tagName, attrs || null);
5153

5254

5355
if (attrs) {

packages/core/src/render3/instructions/projection.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
import {assertDataInRange} from '../../util/assert';
99
import {TAttributes, TElementNode, TNode, TNodeType} from '../interfaces/node';
1010
import {CssSelectorList} from '../interfaces/projection';
11-
import {HEADER_OFFSET, T_HOST} from '../interfaces/view';
11+
import {HEADER_OFFSET, TVIEW, T_HOST} from '../interfaces/view';
1212
import {appendProjectedNodes} from '../node_manipulation';
1313
import {matchingProjectionSelectorIndex} from '../node_selector_matcher';
1414
import {getLView, setIsNotParent} from '../state';
1515
import {findComponentView} from '../util/view_traversal_utils';
1616

17-
import {createNodeAtIndex} from './shared';
17+
import {getOrCreateTNode} from './shared';
18+
1819

1920

2021
/**
@@ -82,7 +83,8 @@ export function ɵɵprojectionDef(selectors?: CssSelectorList[]): void {
8283
export function ɵɵprojection(
8384
nodeIndex: number, selectorIndex: number = 0, attrs?: TAttributes): void {
8485
const lView = getLView();
85-
const tProjectionNode = createNodeAtIndex(nodeIndex, TNodeType.Projection, null, attrs || null);
86+
const tProjectionNode = getOrCreateTNode(
87+
lView[TVIEW], lView[T_HOST], nodeIndex, TNodeType.Projection, null, attrs || null);
8688

8789
// We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views.
8890
if (tProjectionNode.projection === null) tProjectionNode.projection = selectorIndex;

packages/core/src/render3/instructions/shared.ts

Lines changed: 53 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -225,68 +225,74 @@ export function createLView<T>(
225225
/**
226226
* Create and stores the TNode, and hooks it up to the tree.
227227
*
228+
* @param tView The current `TView`.
229+
* @param tHostNode This is a hack and we should not have to pass this value in. It is only used to
230+
* determine if the parent belongs to a different tView. Instead we should not have parentTView
231+
* point to TView other the current one.
228232
* @param index The index at which the TNode should be saved (null if view, since they are not
229233
* saved).
230234
* @param type The type of TNode to create
231235
* @param native The native element for this node, if applicable
232236
* @param name The tag name of the associated native element, if applicable
233237
* @param attrs Any attrs for the native element, if applicable
234238
*/
235-
export function createNodeAtIndex(
236-
index: number, type: TNodeType.Element, name: string | null,
237-
attrs: TAttributes | null): TElementNode;
238-
export function createNodeAtIndex(
239-
index: number, type: TNodeType.Container, name: string | null,
240-
attrs: TAttributes | null): TContainerNode;
241-
export function createNodeAtIndex(
242-
index: number, type: TNodeType.Projection, name: null,
239+
export function getOrCreateTNode(
240+
tView: TView, tHostNode: TNode | null, index: number, type: TNodeType.Element,
241+
name: string | null, attrs: TAttributes | null): TElementNode;
242+
export function getOrCreateTNode(
243+
tView: TView, tHostNode: TNode | null, index: number, type: TNodeType.Container,
244+
name: string | null, attrs: TAttributes | null): TContainerNode;
245+
export function getOrCreateTNode(
246+
tView: TView, tHostNode: TNode | null, index: number, type: TNodeType.Projection, name: null,
243247
attrs: TAttributes | null): TProjectionNode;
244-
export function createNodeAtIndex(
245-
index: number, type: TNodeType.ElementContainer, name: string | null,
248+
export function getOrCreateTNode(
249+
tView: TView, tHostNode: TNode | null, index: number, type: TNodeType.ElementContainer,
250+
name: string | null, attrs: TAttributes | null): TElementContainerNode;
251+
export function getOrCreateTNode(
252+
tView: TView, tHostNode: TNode | null, index: number, type: TNodeType.IcuContainer, name: null,
246253
attrs: TAttributes | null): TElementContainerNode;
247-
export function createNodeAtIndex(
248-
index: number, type: TNodeType.IcuContainer, name: null,
249-
attrs: TAttributes | null): TElementContainerNode;
250-
export function createNodeAtIndex(
251-
index: number, type: TNodeType, name: string | null, attrs: TAttributes | null): TElementNode&
252-
TContainerNode&TElementContainerNode&TProjectionNode&TIcuContainerNode {
253-
const lView = getLView();
254-
const tView = lView[TVIEW];
254+
export function getOrCreateTNode(
255+
tView: TView, tHostNode: TNode | null, index: number, type: TNodeType, name: string | null,
256+
attrs: TAttributes | null): TElementNode&TContainerNode&TElementContainerNode&TProjectionNode&
257+
TIcuContainerNode {
258+
// Keep this function short, so that the VM will inline it.
255259
const adjustedIndex = index + HEADER_OFFSET;
256-
let tNode = tView.data[adjustedIndex] as TNode;
257-
if (tNode == null) {
258-
const previousOrParentTNode = getPreviousOrParentTNode();
259-
const isParent = getIsParent();
260-
const parent =
261-
isParent ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent;
262-
263-
// Parents cannot cross component boundaries because components will be used in multiple places,
264-
// so it's only set if the view is the same.
265-
const parentInSameView = parent && parent !== lView[T_HOST];
266-
const tParentNode = parentInSameView ? parent as TElementNode | TContainerNode : null;
267-
268-
tNode = tView.data[adjustedIndex] = createTNode(tParentNode, type, adjustedIndex, name, attrs);
269-
270-
// Now link ourselves into the tree.
271-
if (previousOrParentTNode) {
272-
if (isParent && previousOrParentTNode.child == null &&
273-
(tNode.parent !== null || previousOrParentTNode.type === TNodeType.View)) {
274-
// We are in the same view, which means we are adding content node to the parent view.
275-
previousOrParentTNode.child = tNode;
276-
} else if (!isParent) {
277-
previousOrParentTNode.next = tNode;
278-
}
279-
}
280-
if (index === 0) {
281-
tView.firstChild = tNode;
282-
}
283-
}
284-
260+
const tNode = tView.data[adjustedIndex] as TNode ||
261+
createTNodeAtIndex(tView, tHostNode, adjustedIndex, type, name, attrs, index);
285262
setPreviousOrParentTNode(tNode, true);
286263
return tNode as TElementNode & TViewNode & TContainerNode & TElementContainerNode &
287264
TProjectionNode & TIcuContainerNode;
288265
}
289266

267+
function createTNodeAtIndex(
268+
tView: TView, tHostNode: TNode | null, adjustedIndex: number, type: TNodeType,
269+
name: string | null, attrs: TAttributes | null, index: number) {
270+
const previousOrParentTNode = getPreviousOrParentTNode();
271+
const isParent = getIsParent();
272+
const parent =
273+
isParent ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent;
274+
// Parents cannot cross component boundaries because components will be used in multiple places,
275+
// so it's only set if the view is the same.
276+
const parentInSameView = parent && parent !== tHostNode;
277+
const tParentNode = parentInSameView ? parent as TElementNode | TContainerNode : null;
278+
const tNode = tView.data[adjustedIndex] =
279+
createTNode(tParentNode, type, adjustedIndex, name, attrs);
280+
if (index === 0) {
281+
tView.firstChild = tNode;
282+
}
283+
// Now link ourselves into the tree.
284+
if (previousOrParentTNode) {
285+
if (isParent && previousOrParentTNode.child == null &&
286+
(tNode.parent !== null || previousOrParentTNode.type === TNodeType.View)) {
287+
// We are in the same view, which means we are adding content node to the parent view.
288+
previousOrParentTNode.child = tNode;
289+
} else if (!isParent) {
290+
previousOrParentTNode.next = tNode;
291+
}
292+
}
293+
return tNode;
294+
}
295+
290296
export function assignTViewNodeToLView(
291297
tView: TView, tParentNode: TNode | null, index: number, lView: LView): TViewNode {
292298
// View nodes are not stored in data because they can be added / removed at runtime (which

packages/core/src/render3/instructions/text.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
import {assertDataInRange, assertDefined, assertEqual} from '../../util/assert';
99
import {TNodeType} from '../interfaces/node';
1010
import {RText, isProceduralRenderer} from '../interfaces/renderer';
11-
import {BINDING_INDEX, HEADER_OFFSET, RENDERER, TVIEW} from '../interfaces/view';
11+
import {BINDING_INDEX, HEADER_OFFSET, RENDERER, TVIEW, T_HOST} from '../interfaces/view';
1212
import {appendChild, createTextNode} from '../node_manipulation';
1313
import {getLView, setIsNotParent} from '../state';
1414
import {NO_CHANGE} from '../tokens';
1515
import {renderStringify} from '../util/misc_utils';
1616
import {getNativeByIndex} from '../util/view_utils';
17-
import {createNodeAtIndex} from './shared';
17+
import {getOrCreateTNode} from './shared';
1818

1919
/**
2020
* Create static text node
@@ -32,7 +32,7 @@ export function ɵɵtext(index: number, value?: any): void {
3232
ngDevMode && ngDevMode.rendererCreateTextNode++;
3333
ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
3434
const textNative = lView[index + HEADER_OFFSET] = createTextNode(value, lView[RENDERER]);
35-
const tNode = createNodeAtIndex(index, TNodeType.Element, null, null);
35+
const tNode = getOrCreateTNode(lView[TVIEW], lView[T_HOST], index, TNodeType.Element, null, null);
3636

3737
// Text nodes are self closing.
3838
setIsNotParent();

packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,6 @@
245245
{
246246
"name": "createLView"
247247
},
248-
{
249-
"name": "createNodeAtIndex"
250-
},
251248
{
252249
"name": "createRootComponent"
253250
},
@@ -260,6 +257,9 @@
260257
{
261258
"name": "createTNode"
262259
},
260+
{
261+
"name": "createTNodeAtIndex"
262+
},
263263
{
264264
"name": "createTView"
265265
},
@@ -404,6 +404,9 @@
404404
{
405405
"name": "getOrCreateNodeInjectorForNode"
406406
},
407+
{
408+
"name": "getOrCreateTNode"
409+
},
407410
{
408411
"name": "getOrCreateTView"
409412
},

packages/core/test/bundling/hello_world/bundle.golden_symbols.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,6 @@
173173
{
174174
"name": "createLView"
175175
},
176-
{
177-
"name": "createNodeAtIndex"
178-
},
179176
{
180177
"name": "createRootComponent"
181178
},
@@ -188,6 +185,9 @@
188185
{
189186
"name": "createTNode"
190187
},
188+
{
189+
"name": "createTNodeAtIndex"
190+
},
191191
{
192192
"name": "createTView"
193193
},
@@ -287,6 +287,9 @@
287287
{
288288
"name": "getOrCreateNodeInjectorForNode"
289289
},
290+
{
291+
"name": "getOrCreateTNode"
292+
},
290293
{
291294
"name": "getOrCreateTView"
292295
},

packages/core/test/bundling/todo/bundle.golden_symbols.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -560,9 +560,6 @@
560560
{
561561
"name": "createLView"
562562
},
563-
{
564-
"name": "createNodeAtIndex"
565-
},
566563
{
567564
"name": "createRootComponent"
568565
},
@@ -575,6 +572,9 @@
575572
{
576573
"name": "createTNode"
577574
},
575+
{
576+
"name": "createTNodeAtIndex"
577+
},
578578
{
579579
"name": "createTView"
580580
},
@@ -866,6 +866,9 @@
866866
{
867867
"name": "getOrCreateNodeInjectorForNode"
868868
},
869+
{
870+
"name": "getOrCreateTNode"
871+
},
869872
{
870873
"name": "getOrCreateTView"
871874
},

0 commit comments

Comments
 (0)