Skip to content

Commit 994264c

Browse files
mheveryAndrewKushnir
authored andcommitted
refactor(ivy): simplify walkTNodeTree method for readability (angular#31065)
PR Close angular#31065
1 parent 4bbf16e commit 994264c

File tree

11 files changed

+301
-324
lines changed

11 files changed

+301
-324
lines changed

integration/_payload-limits.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"master": {
1313
"uncompressed": {
1414
"runtime": 1440,
15-
"main": 13498,
15+
"main": 13164,
1616
"polyfills": 45340
1717
}
1818
}
@@ -34,4 +34,4 @@
3434
}
3535
}
3636
}
37-
}
37+
}

packages/core/src/render3/i18n.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@ import {RComment, RElement, RText} from './interfaces/renderer';
2424
import {SanitizerFn} from './interfaces/sanitization';
2525
import {isLContainer} from './interfaces/type_checks';
2626
import {BINDING_INDEX, HEADER_OFFSET, LView, RENDERER, TVIEW, TView, T_HOST} from './interfaces/view';
27-
import {appendChild, appendProjectedNodes, createTextNode, nativeRemoveNode} from './node_manipulation';
27+
import {appendChild, applyProjection, createTextNode, nativeRemoveNode} from './node_manipulation';
2828
import {getIsParent, getLView, getPreviousOrParentTNode, setIsNotParent, setPreviousOrParentTNode} from './state';
2929
import {NO_CHANGE} from './tokens';
3030
import {renderStringify} from './util/misc_utils';
31-
import {findComponentView} from './util/view_traversal_utils';
3231
import {getNativeByIndex, getNativeByTNode, getTNode, load} from './util/view_utils';
3332

3433

@@ -490,7 +489,7 @@ function i18nStartFirstPass(
490489
}
491490

492491
function appendI18nNode(
493-
tNode: TNode, parentTNode: TNode, previousTNode: TNode | null, viewData: LView): TNode {
492+
tNode: TNode, parentTNode: TNode, previousTNode: TNode | null, lView: LView): TNode {
494493
ngDevMode && ngDevMode.rendererMoveNode++;
495494
const nextNode = tNode.next;
496495
if (!previousTNode) {
@@ -508,7 +507,7 @@ function appendI18nNode(
508507
tNode.next = null;
509508
}
510509

511-
if (parentTNode !== viewData[T_HOST]) {
510+
if (parentTNode !== lView[T_HOST]) {
512511
tNode.parent = parentTNode as TElementNode;
513512
}
514513

@@ -523,18 +522,16 @@ function appendI18nNode(
523522

524523
// If the placeholder to append is a projection, we need to move the projected nodes instead
525524
if (tNode.type === TNodeType.Projection) {
526-
const tProjectionNode = tNode as TProjectionNode;
527-
appendProjectedNodes(
528-
viewData, tProjectionNode, tProjectionNode.projection, findComponentView(viewData));
525+
applyProjection(lView, tNode as TProjectionNode);
529526
return tNode;
530527
}
531528

532-
appendChild(getNativeByTNode(tNode, viewData), tNode, viewData);
529+
appendChild(getNativeByTNode(tNode, lView), tNode, lView);
533530

534-
const slotValue = viewData[tNode.index];
531+
const slotValue = lView[tNode.index];
535532
if (tNode.type !== TNodeType.Container && isLContainer(slotValue)) {
536533
// Nodes that inject ViewContainerRef also have a comment node that should be moved
537-
appendChild(slotValue[NATIVE], tNode, viewData);
534+
appendChild(slotValue[NATIVE], tNode, lView);
538535
}
539536
return tNode;
540537
}
@@ -687,7 +684,7 @@ function i18nEndFirstPass(tView: TView) {
687684
// Remove deleted nodes
688685
for (let i = rootIndex + 1; i <= lastCreatedNode.index - HEADER_OFFSET; i++) {
689686
if (visitedNodes.indexOf(i) === -1) {
690-
removeNode(i, viewData);
687+
removeNode(i, viewData, /* markAsDetached */ true);
691688
}
692689
}
693690
}
@@ -862,7 +859,10 @@ function readUpdateOpCodes(
862859
switch (removeOpCode & I18nMutateOpCode.MASK_OPCODE) {
863860
case I18nMutateOpCode.Remove:
864861
const nodeIndex = removeOpCode >>> I18nMutateOpCode.SHIFT_REF;
865-
removeNode(nodeIndex, viewData);
862+
// Remove DOM element, but do *not* mark TNode as detached, since we are
863+
// just switching ICU cases (while keeping the same TNode), so a DOM element
864+
// representing a new ICU case will be re-created.
865+
removeNode(nodeIndex, viewData, /* markAsDetached */ false);
866866
break;
867867
case I18nMutateOpCode.RemoveNestedIcu:
868868
const nestedIcuNodeIndex =
@@ -905,7 +905,7 @@ function readUpdateOpCodes(
905905
}
906906
}
907907

908-
function removeNode(index: number, viewData: LView) {
908+
function removeNode(index: number, viewData: LView, markAsDetached: boolean) {
909909
const removedPhTNode = getTNode(index, viewData);
910910
const removedPhRNode = getNativeByIndex(index, viewData);
911911
if (removedPhRNode) {
@@ -920,8 +920,10 @@ function removeNode(index: number, viewData: LView) {
920920
}
921921
}
922922

923-
// Define this node as detached so that we don't risk projecting it
924-
removedPhTNode.flags |= TNodeFlags.isDetached;
923+
if (markAsDetached) {
924+
// Define this node as detached to avoid projecting it later
925+
removedPhTNode.flags |= TNodeFlags.isDetached;
926+
}
925927
ngDevMode && ngDevMode.rendererRemoveNode++;
926928
}
927929

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

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ export const TViewConstructor = class TView implements ITView {
102102
public firstChild: TNode|null, //
103103
public schemas: SchemaMetadata[]|null, //
104104
) {}
105+
106+
get template_(): string {
107+
const buf: string[] = [];
108+
processTNodeChildren(this.firstChild, buf);
109+
return buf.join('');
110+
}
105111
};
106112

107113
export const TNodeConstructor = class TNode implements ITNode {
@@ -161,8 +167,34 @@ export const TNodeConstructor = class TNode implements ITNode {
161167
if (this.flags & TNodeFlags.isProjected) flags.push('TNodeFlags.isProjected');
162168
return flags.join('|');
163169
}
170+
171+
get template_(): string {
172+
const buf: string[] = [];
173+
buf.push('<', this.tagName || this.type_);
174+
if (this.attrs) {
175+
for (let i = 0; i < this.attrs.length;) {
176+
const attrName = this.attrs[i++];
177+
if (typeof attrName == 'number') {
178+
break;
179+
}
180+
const attrValue = this.attrs[i++];
181+
buf.push(' ', attrName as string, '="', attrValue as string, '"');
182+
}
183+
}
184+
buf.push('>');
185+
processTNodeChildren(this.child, buf);
186+
buf.push('</', this.tagName || this.type_, '>');
187+
return buf.join('');
188+
}
164189
};
165190

191+
function processTNodeChildren(tNode: TNode | null, buf: string[]) {
192+
while (tNode) {
193+
buf.push((tNode as any as{template_: string}).template_);
194+
tNode = tNode.next;
195+
}
196+
}
197+
166198
const TViewData = ngDevMode && createNamedArrayType('TViewData');
167199
let TVIEWDATA_EMPTY:
168200
unknown[]; // can't initialize here or it will not be tree shaken, because `LView`
@@ -226,8 +258,8 @@ function toHtml(value: any, includeChildren: boolean = false): string|null {
226258
if (includeChildren || isTextNode) {
227259
return outerHTML;
228260
} else {
229-
const innerHTML = node.innerHTML;
230-
return outerHTML.split(innerHTML)[0] || null;
261+
const innerHTML = '>' + node.innerHTML + '<';
262+
return (outerHTML.split(innerHTML)[0]) + '>';
231263
}
232264
} else {
233265
return null;
@@ -257,6 +289,7 @@ export class LViewDebug {
257289
}
258290
get parent(): LViewDebug|LContainerDebug|null { return toDebug(this._raw_lView[PARENT]); }
259291
get host(): string|null { return toHtml(this._raw_lView[HOST], true); }
292+
get html(): string { return (this.nodes || []).map(node => toHtml(node.native, true)).join(''); }
260293
get context(): {}|null { return this._raw_lView[CONTEXT]; }
261294
/**
262295
* The tree of nodes associated with the current `LView`. The nodes have been normalized into a
@@ -267,38 +300,30 @@ export class LViewDebug {
267300
const tNode = lView[TVIEW].firstChild;
268301
return toDebugNodes(tNode, lView);
269302
}
270-
/**
271-
* Additional information which is hidden behind a property. The extra level of indirection is
272-
* done so that the debug view would not be cluttered with properties which are only rarely
273-
* relevant to the developer.
274-
*/
275-
get __other__() {
276-
return {
277-
tView: this._raw_lView[TVIEW],
278-
cleanup: this._raw_lView[CLEANUP],
279-
injector: this._raw_lView[INJECTOR],
280-
rendererFactory: this._raw_lView[RENDERER_FACTORY],
281-
renderer: this._raw_lView[RENDERER],
282-
sanitizer: this._raw_lView[SANITIZER],
283-
childHead: toDebug(this._raw_lView[CHILD_HEAD]),
284-
next: toDebug(this._raw_lView[NEXT]),
285-
childTail: toDebug(this._raw_lView[CHILD_TAIL]),
286-
declarationView: toDebug(this._raw_lView[DECLARATION_VIEW]),
287-
queries: null,
288-
tHost: this._raw_lView[T_HOST],
289-
bindingIndex: this._raw_lView[BINDING_INDEX],
290-
};
291-
}
303+
304+
get tView() { return this._raw_lView[TVIEW]; }
305+
get cleanup() { return this._raw_lView[CLEANUP]; }
306+
get injector() { return this._raw_lView[INJECTOR]; }
307+
get rendererFactory() { return this._raw_lView[RENDERER_FACTORY]; }
308+
get renderer() { return this._raw_lView[RENDERER]; }
309+
get sanitizer() { return this._raw_lView[SANITIZER]; }
310+
get childHead() { return toDebug(this._raw_lView[CHILD_HEAD]); }
311+
get next() { return toDebug(this._raw_lView[NEXT]); }
312+
get childTail() { return toDebug(this._raw_lView[CHILD_TAIL]); }
313+
get declarationView() { return toDebug(this._raw_lView[DECLARATION_VIEW]); }
314+
get queries() { return this._raw_lView[QUERIES]; }
315+
get tHost() { return this._raw_lView[T_HOST]; }
316+
get bindingIndex() { return this._raw_lView[BINDING_INDEX]; }
292317

293318
/**
294319
* Normalized view of child views (and containers) attached at this location.
295320
*/
296321
get childViews(): Array<LViewDebug|LContainerDebug> {
297322
const childViews: Array<LViewDebug|LContainerDebug> = [];
298-
let child = this.__other__.childHead;
323+
let child = this.childHead;
299324
while (child) {
300325
childViews.push(child);
301-
child = child.__other__.next;
326+
child = child.next;
302327
}
303328
return childViews;
304329
}
@@ -359,11 +384,7 @@ export class LContainerDebug {
359384
get movedViews(): LView[]|null { return this._raw_lContainer[MOVED_VIEWS]; }
360385
get host(): RElement|RComment|LView { return this._raw_lContainer[HOST]; }
361386
get native(): RComment { return this._raw_lContainer[NATIVE]; }
362-
get __other__() {
363-
return {
364-
next: toDebug(this._raw_lContainer[NEXT]),
365-
};
366-
}
387+
get next() { return toDebug(this._raw_lContainer[NEXT]); }
367388
}
368389

369390
/**

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88
import {TAttributes, TElementNode, TNode, TNodeType} from '../interfaces/node';
99
import {ProjectionSlots} from '../interfaces/projection';
1010
import {TVIEW, T_HOST} from '../interfaces/view';
11-
import {appendProjectedNodes} from '../node_manipulation';
11+
import {applyProjection} from '../node_manipulation';
1212
import {getProjectAsAttrValue, isNodeMatchingSelectorList, isSelectorInSelectorList} from '../node_selector_matcher';
1313
import {getLView, setIsNotParent} from '../state';
1414
import {findComponentView} from '../util/view_traversal_utils';
15+
1516
import {getOrCreateTNode} from './shared';
1617

1718

19+
1820
/**
1921
* Checks a given node against matching projection slots and returns the
2022
* determined slot index. Returns "null" if no slot matched the given node.
@@ -134,6 +136,6 @@ export function ɵɵprojection(
134136
// We might need to delay the projection of nodes if they are in the middle of an i18n block
135137
if (!delayProjection) {
136138
// re-distribution of projectable nodes is stored on a component's view level
137-
appendProjectedNodes(lView, tProjectionNode, selectorIndex, findComponentView(lView));
139+
applyProjection(lView, tProjectionNode);
138140
}
139141
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ function createTNodeAtIndex(
235235
if (index === 0 || !tView.firstChild) {
236236
tView.firstChild = tNode;
237237
}
238-
// Now link ourselves into the tree.
239238
if (previousOrParentTNode) {
240239
if (isParent && previousOrParentTNode.child == null &&
241240
(tNode.parent !== null || previousOrParentTNode.type === TNodeType.View)) {

packages/core/src/render3/node_assert.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export function assertNodeOfPossibleTypes(tNode: TNode, ...types: TNodeType[]) {
2525
function typeName(type: TNodeType): string {
2626
if (type == TNodeType.Projection) return 'Projection';
2727
if (type == TNodeType.Container) return 'Container';
28+
if (type == TNodeType.IcuContainer) return 'IcuContainer';
2829
if (type == TNodeType.View) return 'View';
2930
if (type == TNodeType.Element) return 'Element';
3031
if (type == TNodeType.ElementContainer) return 'ElementContainer';

0 commit comments

Comments
 (0)