Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0de5049

Browse files
refactor(core): move TNode manipulation logic to its own file (#59601)
Move TNode manipulation logic to its own file and update existing refereces. PR Close #59601
1 parent 78af7a5 commit 0de5049

23 files changed

+427
-388
lines changed

‎packages/core/src/render3/component_ref.ts

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ import {
4545
createTView,
4646
getInitialLViewFlagsFromDef,
4747
getOrCreateComponentTView,
48-
getOrCreateTNode,
4948
initializeDirectives,
5049
invokeDirectivesHostBindings,
5150
locateHostElement,
@@ -76,8 +75,7 @@ import {
7675
} from './interfaces/view';
7776
import {MATH_ML_NAMESPACE, SVG_NAMESPACE} from './namespaces';
7877

79-
import {createElementNode} from './dom_node_manipulation';
80-
import {setupStaticAttributes} from './node_manipulation';
78+
import {createElementNode, setupStaticAttributes} from './dom_node_manipulation';
8179
import {
8280
extractAttrsAndClassesFromSelector,
8381
stringifyCSSSelectorList,
@@ -93,6 +91,7 @@ import {unregisterLView} from './interfaces/lview_tracking';
9391
import {executeContentQueries} from './queries/query_execution';
9492
import {AttributeMarker} from './interfaces/attribute_marker';
9593
import {CssSelector} from './interfaces/projection';
94+
import {getOrCreateTNode} from './tnode_manipulation';
9695

9796
export class ComponentFactoryResolver extends AbstractComponentFactoryResolver {
9897
/**
@@ -339,6 +338,8 @@ export class ComponentFactory<T> extends AbstractComponentFactory<T> {
339338
hydrationInfo,
340339
);
341340

341+
rootLView[HEADER_OFFSET] = hostRNode;
342+
342343
// rootView is the parent when bootstrapping
343344
// TODO(misko): it looks like we are entering view here but we don't really need to as
344345
// `renderView` does that. However as the code is written it is needed because
@@ -347,7 +348,6 @@ export class ComponentFactory<T> extends AbstractComponentFactory<T> {
347348
enterView(rootLView);
348349

349350
let component: T;
350-
let tElementNode: TElementNode;
351351
let componentView: LView | null = null;
352352

353353
try {
@@ -369,13 +369,21 @@ export class ComponentFactory<T> extends AbstractComponentFactory<T> {
369369
rootDirectives = [rootComponentDef];
370370
}
371371

372-
const hostTNode = createRootComponentTNode(rootLView, hostRNode);
373372
// If host dom element is created (instead of being provided as part of the dynamic component creation), also apply attributes and classes extracted from component selector.
374373
const tAttributes = rootSelectorOrNode
375374
? ['ng-version', '0.0.0-PLACEHOLDER']
376375
: // Extract attributes and classes from the first selector only to match VE behavior.
377376
getRootTAttributesFromSelector(this.componentDef.selectors[0]);
378377

378+
// TODO: this logic is shared with the element instruction first create pass
379+
const hostTNode = getOrCreateTNode(
380+
rootTView,
381+
HEADER_OFFSET,
382+
TNodeType.Element,
383+
'#host',
384+
tAttributes,
385+
);
386+
379387
for (const def of rootDirectives) {
380388
hostTNode.mergedAttrs = mergeHostAttrs(hostTNode.mergedAttrs, def.hostAttrs);
381389
}
@@ -399,8 +407,6 @@ export class ComponentFactory<T> extends AbstractComponentFactory<T> {
399407
environment,
400408
);
401409

402-
tElementNode = getTNode(rootTView, HEADER_OFFSET) as TElementNode;
403-
404410
if (projectableNodes !== undefined) {
405411
projectNodes(hostTNode, this.ngContentSelectors, projectableNodes);
406412
}
@@ -428,12 +434,13 @@ export class ComponentFactory<T> extends AbstractComponentFactory<T> {
428434
leaveView();
429435
}
430436

437+
const hostTNode = getTNode(rootTView, HEADER_OFFSET) as TElementNode;
431438
return new ComponentRef(
432439
this.componentType,
433440
component,
434-
createElementRef(tElementNode, rootLView),
441+
createElementRef(hostTNode, rootLView),
435442
rootLView,
436-
tElementNode,
443+
hostTNode,
437444
);
438445
} finally {
439446
setActiveConsumer(prevConsumer);
@@ -518,19 +525,6 @@ export class ComponentRef<T> extends AbstractComponentRef<T> {
518525
/** Represents a HostFeature function. */
519526
type HostFeature = <T>(component: T, componentDef: ComponentDef<T>) => void;
520527

521-
/** Creates a TNode that can be used to instantiate a root component. */
522-
function createRootComponentTNode(lView: LView, rNode: RNode): TElementNode {
523-
const tView = lView[TVIEW];
524-
const index = HEADER_OFFSET;
525-
ngDevMode && assertIndexInRange(lView, index);
526-
lView[index] = rNode;
527-
528-
// '#host' is added here as we don't know the real host DOM name (we don't want to read it) and at
529-
// the same time we want to communicate the debug `TNode` that this is a special `TNode`
530-
// representing a host element.
531-
return getOrCreateTNode(tView, index, TNodeType.Element, '#host', null);
532-
}
533-
534528
/**
535529
* Creates the root component view and the root component node.
536530
*

‎packages/core/src/render3/dom_node_manipulation.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import {Renderer} from './interfaces/renderer';
1010
import {RComment, RElement, RNode, RText} from './interfaces/renderer_dom';
1111
import {escapeCommentText} from '../util/dom';
12-
import {assertDefined} from '../util/assert';
12+
import {assertDefined, assertString} from '../util/assert';
13+
import {setUpAttributes} from './util/attrs_utils';
14+
import {TNode} from './interfaces/node';
1315

1416
export function createTextNode(renderer: Renderer, value: string): RText {
1517
ngDevMode && ngDevMode.rendererCreateTextNode++;
@@ -100,3 +102,57 @@ export function nativeRemoveNode(renderer: Renderer, rNode: RNode, isHostElement
100102
export function clearElementContents(rElement: RElement): void {
101103
rElement.textContent = '';
102104
}
105+
106+
/**
107+
* Write `cssText` to `RElement`.
108+
*
109+
* This function does direct write without any reconciliation. Used for writing initial values, so
110+
* that static styling values do not pull in the style parser.
111+
*
112+
* @param renderer Renderer to use
113+
* @param element The element which needs to be updated.
114+
* @param newValue The new class list to write.
115+
*/
116+
function writeDirectStyle(renderer: Renderer, element: RElement, newValue: string) {
117+
ngDevMode && assertString(newValue, "'newValue' should be a string");
118+
renderer.setAttribute(element, 'style', newValue);
119+
ngDevMode && ngDevMode.rendererSetStyle++;
120+
}
121+
122+
/**
123+
* Write `className` to `RElement`.
124+
*
125+
* This function does direct write without any reconciliation. Used for writing initial values, so
126+
* that static styling values do not pull in the style parser.
127+
*
128+
* @param renderer Renderer to use
129+
* @param element The element which needs to be updated.
130+
* @param newValue The new class list to write.
131+
*/
132+
function writeDirectClass(renderer: Renderer, element: RElement, newValue: string) {
133+
ngDevMode && assertString(newValue, "'newValue' should be a string");
134+
if (newValue === '') {
135+
// There are tests in `google3` which expect `element.getAttribute('class')` to be `null`.
136+
renderer.removeAttribute(element, 'class');
137+
} else {
138+
renderer.setAttribute(element, 'class', newValue);
139+
}
140+
ngDevMode && ngDevMode.rendererSetClassName++;
141+
}
142+
143+
/** Sets up the static DOM attributes on an `RNode`. */
144+
export function setupStaticAttributes(renderer: Renderer, element: RElement, tNode: TNode) {
145+
const {mergedAttrs, classes, styles} = tNode;
146+
147+
if (mergedAttrs !== null) {
148+
setUpAttributes(renderer, element, mergedAttrs);
149+
}
150+
151+
if (classes !== null) {
152+
writeDirectClass(renderer, element, classes);
153+
}
154+
155+
if (styles !== null) {
156+
writeDirectStyle(renderer, element, styles);
157+
}
158+
}

‎packages/core/src/render3/i18n/i18n_parse.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
} from '../../util/assert';
2727
import {CharCode} from '../../util/char_code';
2828
import {loadIcuContainerVisitor} from '../instructions/i18n_icu_container_visitor';
29-
import {allocExpando, createTNodeAtIndex} from '../instructions/shared';
29+
import {allocExpando} from '../instructions/shared';
3030
import {getDocument} from '../interfaces/document';
3131
import {
3232
ELEMENT_MARKER,
@@ -68,6 +68,7 @@ import {
6868
setTIcu,
6969
setTNodeInsertBeforeIndex,
7070
} from './i18n_util';
71+
import {createTNodeAtIndex} from '../tnode_manipulation';
7172

7273
const BINDING_REGEXP = /�(\d+):?\d*�/gi;
7374
const ICU_REGEXP = /({\s*�\d+:?\d*�\s*,\s*\S{6}\s*,[\s\S]*})/gi;

‎packages/core/src/render3/i18n/i18n_util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ import {
1313
throwError,
1414
} from '../../util/assert';
1515
import {assertTIcu, assertTNode} from '../assert';
16-
import {createTNodeAtIndex} from '../instructions/shared';
1716
import {IcuCreateOpCode, TIcu} from '../interfaces/i18n';
1817
import {TIcuContainerNode, TNode, TNodeType} from '../interfaces/node';
1918
import {LView, TView} from '../interfaces/view';
2019
import {assertTNodeType} from '../node_assert';
2120
import {setI18nHandling} from '../node_manipulation';
2221
import {getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore} from '../node_manipulation_i18n';
22+
import {createTNodeAtIndex} from '../tnode_manipulation';
2323

2424
import {addTNodeAndUpdateInsertBeforeIndex} from './i18n_insert_before_index';
2525

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,12 @@ import {isComponentHost, isContentQueryHost, isDirectiveHost} from '../interface
4242
import {HEADER_OFFSET, HYDRATION, LView, RENDERER, TView} from '../interfaces/view';
4343
import {assertTNodeType} from '../node_assert';
4444
import {executeContentQueries} from '../queries/query_execution';
45-
import {appendChild, setupStaticAttributes} from '../node_manipulation';
46-
import {clearElementContents, createElementNode} from '../dom_node_manipulation';
45+
import {appendChild} from '../node_manipulation';
46+
import {
47+
clearElementContents,
48+
createElementNode,
49+
setupStaticAttributes,
50+
} from '../dom_node_manipulation';
4751
import {
4852
decreaseElementDepthCount,
4953
enterSkipHydrationBlock,
@@ -68,12 +72,8 @@ import {getConstant} from '../util/view_utils';
6872

6973
import {validateElementIsKnown} from './element_validation';
7074
import {setDirectiveInputsWhichShadowsStyling} from './property';
71-
import {
72-
createDirectivesInstances,
73-
getOrCreateTNode,
74-
resolveDirectives,
75-
saveResolvedLocalsInData,
76-
} from './shared';
75+
import {createDirectivesInstances, resolveDirectives, saveResolvedLocalsInData} from './shared';
76+
import {getOrCreateTNode} from '../tnode_manipulation';
7777

7878
function elementStartFirstCreatePass(
7979
index: number,

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,8 @@ import {
4141
import {computeStaticStyling} from '../styling/static_styling';
4242
import {getConstant} from '../util/view_utils';
4343

44-
import {
45-
createDirectivesInstances,
46-
getOrCreateTNode,
47-
resolveDirectives,
48-
saveResolvedLocalsInData,
49-
} from './shared';
44+
import {createDirectivesInstances, resolveDirectives, saveResolvedLocalsInData} from './shared';
45+
import {getOrCreateTNode} from '../tnode_manipulation';
5046

5147
function elementContainerStartFirstCreatePass(
5248
index: number,

‎packages/core/src/render3/instructions/let_declaration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import {performanceMarkFeature} from '../../util/performance';
1111
import {TNodeType} from '../interfaces/node';
1212
import {HEADER_OFFSET} from '../interfaces/view';
1313
import {getContextLView, getLView, getSelectedIndex, getTView, setCurrentTNode} from '../state';
14+
import {getOrCreateTNode} from '../tnode_manipulation';
1415
import {load} from '../util/view_utils';
15-
import {getOrCreateTNode} from './shared';
1616
import {store} from './storage';
1717

1818
/** Object that indicates the value of a `@let` declaration that hasn't been initialized yet. */

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ import {
2626
isSelectorInSelectorList,
2727
} from '../node_selector_matcher';
2828
import {getLView, getTView, isInSkipHydrationBlock, setCurrentTNodeAsNotParent} from '../state';
29+
import {getOrCreateTNode} from '../tnode_manipulation';
2930
import {
3031
addLViewToLContainer,
3132
createAndRenderEmbeddedLView,
3233
shouldAddViewToDom,
3334
} from '../view_manipulation';
3435

35-
import {getOrCreateTNode} from './shared';
3636
import {declareTemplate} from './template';
3737

3838
/**

0 commit comments

Comments
 (0)