Skip to content

Commit 70f1e2e

Browse files
mheveryalxhub
authored andcommitted
refactor(core): Create TNodeType.Text to display full template in TView debug (angular#39233)
When looking at `TView` debug template only Element nodes were displayed as `TNode.Element` was used for both `RElement` and `RText`. Additionally no text was stored in `TNode.value`. The result was that the whole template could not be reconstructed. This refactoring creates `TNodeType.Text` and store the text value in `TNode.value`. The refactoring also changes `TNodeType` into flag-like structure make it more efficient to check many different types at once. PR Close angular#39233
1 parent d50df92 commit 70f1e2e

26 files changed

+261
-245
lines changed

packages/core/src/debug/debug_node.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ function _queryNodeChildrenR3(
529529
ngDevMode && assertTNodeForLView(tNode, lView);
530530
const nativeNode = getNativeByTNodeOrNull(tNode, lView);
531531
// For each type of TNode, specific logic is executed.
532-
if (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) {
532+
if (tNode.type & (TNodeType.AnyRNode | TNodeType.ElementContainer)) {
533533
// Case 1: the TNode is an element
534534
// The native node has to be checked.
535535
_addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode);
@@ -565,14 +565,14 @@ function _queryNodeChildrenR3(
565565
_queryNodeChildrenInContainerR3(
566566
nodeOrContainer, predicate, matches, elementsOnly, rootNativeNode);
567567
}
568-
} else if (tNode.type === TNodeType.Container) {
568+
} else if (tNode.type & TNodeType.Container) {
569569
// Case 2: the TNode is a container
570570
// The native node has to be checked.
571571
const lContainer = lView[tNode.index];
572572
_addQueryMatchR3(lContainer[NATIVE], predicate, matches, elementsOnly, rootNativeNode);
573573
// Each view inside the container has to be processed.
574574
_queryNodeChildrenInContainerR3(lContainer, predicate, matches, elementsOnly, rootNativeNode);
575-
} else if (tNode.type === TNodeType.Projection) {
575+
} else if (tNode.type & TNodeType.Projection) {
576576
// Case 3: the TNode is a projection insertion point (i.e. a <ng-content>).
577577
// The nodes projected at this location all need to be processed.
578578
const componentView = lView![DECLARATION_COMPONENT_VIEW];

packages/core/src/render3/di.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {injectRootLimpMode, setInjectImplementation} from '../di/injector_compat
1313
import {getInjectorDef} from '../di/interface/defs';
1414
import {InjectFlags} from '../di/interface/injector';
1515
import {Type} from '../interface/type';
16-
import {assertDefined, assertEqual, assertIndexInRange, throwError} from '../util/assert';
16+
import {assertDefined, assertEqual, assertIndexInRange} from '../util/assert';
1717
import {noSideEffects} from '../util/closure';
1818

1919
import {assertDirectiveDef, assertNodeInjector, assertTNodeForLView} from './assert';
@@ -25,7 +25,7 @@ import {isFactory, NO_PARENT_INJECTOR, NodeInjectorFactory, NodeInjectorOffset,
2525
import {AttributeMarker, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TNode, TNodeProviderIndexes, TNodeType} from './interfaces/node';
2626
import {isComponentDef, isComponentHost} from './interfaces/type_checks';
2727
import {DECLARATION_COMPONENT_VIEW, DECLARATION_VIEW, INJECTOR, LView, T_HOST, TData, TVIEW, TView, TViewType} from './interfaces/view';
28-
import {assertNodeOfPossibleTypes} from './node_assert';
28+
import {assertTNodeType} from './node_assert';
2929
import {enterDI, leaveDI} from './state';
3030
import {isNameOnlyAttributeMarker} from './util/attrs_utils';
3131
import {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_utils';
@@ -301,9 +301,7 @@ export function diPublicInInjector(
301301
* @publicApi
302302
*/
303303
export function injectAttributeImpl(tNode: TNode, attrNameToInject: string): string|null {
304-
ngDevMode &&
305-
assertNodeOfPossibleTypes(
306-
tNode, [TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer]);
304+
ngDevMode && assertTNodeType(tNode, TNodeType.AnyContainer | TNodeType.AnyRNode);
307305
ngDevMode && assertDefined(tNode, 'expecting tNode');
308306
if (attrNameToInject === 'class') {
309307
return tNode.classes;
@@ -506,7 +504,7 @@ function searchTokensOnInjector<T>(
506504
// - AND the parent TNode is an Element.
507505
// This means that we just came from the Component's View and therefore are allowed to see
508506
// into the ViewProviders.
509-
(previousTView != currentTView && (tNode.type === TNodeType.Element));
507+
(previousTView != currentTView && ((tNode.type & TNodeType.AnyRNode) !== 0));
510508

511509
// This special case happens when there is a @host on the inject and when we are searching
512510
// on the host element node.

packages/core/src/render3/i18n/i18n_apply.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {getPluralCase} from '../../i18n/localization';
1010
import {assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertIndexInRange, throwError} from '../../util/assert';
1111
import {assertIndexInExpandoRange, assertTIcu} from '../assert';
1212
import {attachPatchData} from '../context_discovery';
13-
import {elementPropertyInternal, setElementAttribute, textBindingInternal} from '../instructions/shared';
13+
import {elementPropertyInternal, setElementAttribute} from '../instructions/shared';
1414
import {COMMENT_MARKER, ELEMENT_MARKER, getCurrentICUCaseIndex, getParentFromI18nMutateOpCode, getRefFromI18nMutateOpCode, I18nCreateOpCode, I18nCreateOpCodes, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuType, TI18n, TIcu} from '../interfaces/i18n';
1515
import {TNode} from '../interfaces/node';
1616
import {RElement, RNode, RText} from '../interfaces/renderer';

packages/core/src/render3/i18n/i18n_insert_before_index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export function addTNodeAndUpdateInsertBeforeIndex(previousTNodes: TNode[], newT
6363
}
6464

6565
function isI18nText(tNode: TNode): boolean {
66-
return tNode.type !== TNodeType.Placeholder;
66+
return !(tNode.type & TNodeType.Placeholder);
6767
}
6868

6969
function isNewTNodeCreatedBefore(existingTNode: TNode, newTNode: TNode): boolean {

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {loadIcuContainerVisitor} from '../instructions/i18n_icu_container_visito
1717
import {allocExpando, createTNodeAtIndex, elementAttributeInternal, setInputsForProperty, setNgReflectProperties} from '../instructions/shared';
1818
import {getDocument} from '../interfaces/document';
1919
import {COMMENT_MARKER, ELEMENT_MARKER, ensureIcuContainerVisitorLoaded, I18nCreateOpCode, I18nCreateOpCodes, I18nMutateOpCode, i18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuExpression, IcuType, TI18n, TIcu} from '../interfaces/i18n';
20-
import {TIcuContainerNode, TNode, TNodeType} from '../interfaces/node';
20+
import {TNode, TNodeType} from '../interfaces/node';
2121
import {RComment, RElement} from '../interfaces/renderer';
2222
import {SanitizerFn} from '../interfaces/sanitization';
2323
import {HEADER_OFFSET, LView, TView} from '../interfaces/view';
@@ -152,7 +152,7 @@ export function i18nStartFirstCreatePass(
152152
*/
153153
function createTNodeAndAddOpCode(
154154
tView: TView, rootTNode: TNode|null, existingTNodes: TNode[], lView: LView,
155-
createOpCodes: I18nCreateOpCodes, text: string, isICU: boolean): TNode {
155+
createOpCodes: I18nCreateOpCodes, text: string|null, isICU: boolean): TNode {
156156
const i18nNodeIdx = allocExpando(tView, lView, 1);
157157
let opCode = i18nNodeIdx << I18nCreateOpCode.SHIFT;
158158
let parentTNode = getCurrentParentTNode();
@@ -174,9 +174,12 @@ function createTNodeAndAddOpCode(
174174
opCode |= I18nCreateOpCode.COMMENT;
175175
ensureIcuContainerVisitorLoaded(loadIcuContainerVisitor);
176176
}
177-
createOpCodes.push(opCode, text);
177+
createOpCodes.push(opCode, text === null ? '' : text);
178+
// We store `{{?}}` so that when looking at debug `TNodeType.template` we can see where the
179+
// bindings are.
178180
const tNode = createTNodeAtIndex(
179-
tView, i18nNodeIdx, isICU ? TNodeType.IcuContainer : TNodeType.Element, null, null);
181+
tView, i18nNodeIdx, isICU ? TNodeType.Icu : TNodeType.Text,
182+
text === null ? (ngDevMode ? '{{?}}' : '') : text, null);
180183
addTNodeAndUpdateInsertBeforeIndex(existingTNodes, tNode);
181184
const tNodeIdx = tNode.index;
182185
setCurrentTNode(tNode, false /* Text nodes are self closing */);
@@ -212,7 +215,7 @@ function i18nStartFirstCreatePassProcessTextNode(
212215
updateOpCodes: I18nUpdateOpCodes, lView: LView, text: string): void {
213216
const hasBinding = text.match(BINDING_REGEXP);
214217
const tNode = createTNodeAndAddOpCode(
215-
tView, rootTNode, existingTNodes, lView, createOpCodes, hasBinding ? '' : text, false);
218+
tView, rootTNode, existingTNodes, lView, createOpCodes, hasBinding ? null : text, false);
216219
if (hasBinding) {
217220
generateBindingUpdateOpCodes(updateOpCodes, text, tNode.index);
218221
}
@@ -251,7 +254,7 @@ export function i18nAttributesFirstPass(
251254
const tNode = getTNode(tView, previousElementIndex - HEADER_OFFSET);
252255
// Set attributes for Elements only, for other types (like ElementContainer),
253256
// only set inputs below
254-
if (tNode.type === TNodeType.Element) {
257+
if (tNode.type & TNodeType.AnyRNode) {
255258
elementAttributeInternal(tNode, lView, attrName, value, null, null);
256259
}
257260
// Check if that attribute is a directive input

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {createTNodeAtIndex} from '../instructions/shared';
1212
import {TIcu} from '../interfaces/i18n';
1313
import {TIcuContainerNode, TNode, TNodeType} from '../interfaces/node';
1414
import {TView} from '../interfaces/view';
15-
import {assertNodeType} from '../node_assert';
15+
import {assertTNodeType} from '../node_assert';
1616
import {addTNodeAndUpdateInsertBeforeIndex} from './i18n_insert_before_index';
1717

1818

@@ -69,7 +69,7 @@ export function setTIcu(tView: TView, index: number, tIcu: TIcu): void {
6969
if (tNode === null) {
7070
tView.data[index] = tIcu;
7171
} else {
72-
ngDevMode && assertNodeType(tNode, TNodeType.IcuContainer);
72+
ngDevMode && assertTNodeType(tNode, TNodeType.Icu);
7373
tNode.value = tIcu;
7474
}
7575
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {hasClassInput, hasStyleInput, TAttributes, TElementNode, TNode, TNodeFla
1414
import {RElement} from '../interfaces/renderer';
1515
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
1616
import {HEADER_OFFSET, LView, RENDERER, TView} from '../interfaces/view';
17-
import {assertNodeType} from '../node_assert';
17+
import {assertTNodeType} from '../node_assert';
1818
import {appendChild, createElementNode, writeDirectClass, writeDirectStyle} from '../node_manipulation';
1919
import {decreaseElementDepthCount, getBindingIndex, getCurrentTNode, getElementDepthCount, getLView, getNamespace, getTView, increaseElementDepthCount, isCurrentTNodeParent, setCurrentTNode, setCurrentTNodeAsNotParent} from '../state';
2020
import {computeStaticStyling} from '../styling/static_styling';
@@ -24,6 +24,7 @@ import {setDirectiveInputsWhichShadowsStyling} from './property';
2424
import {createDirectivesInstances, executeContentQueries, getOrCreateTNode, matchingSchemas, resolveDirectives, saveResolvedLocalsInData} from './shared';
2525

2626

27+
2728
function elementStartFirstCreatePass(
2829
index: number, tView: TView, lView: LView, native: RElement, name: string,
2930
attrsIndex?: number|null, localRefsIndex?: number): TElementNode {
@@ -140,7 +141,7 @@ export function ɵɵelementEnd(): void {
140141
}
141142

142143
const tNode = currentTNode;
143-
ngDevMode && assertNodeType(tNode, TNodeType.Element);
144+
ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode);
144145

145146

146147
decreaseElementDepthCount();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {registerPostOrderHooks} from '../hooks';
1212
import {TAttributes, TElementContainerNode, TNodeType} from '../interfaces/node';
1313
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
1414
import {HEADER_OFFSET, LView, RENDERER, T_HOST, TView} from '../interfaces/view';
15-
import {assertNodeType} from '../node_assert';
15+
import {assertTNodeType} from '../node_assert';
1616
import {appendChild} from '../node_manipulation';
1717
import {getBindingIndex, getCurrentTNode, getLView, getTView, isCurrentTNodeParent, setCurrentTNode, setCurrentTNodeAsNotParent} from '../state';
1818
import {computeStaticStyling} from '../styling/static_styling';
@@ -108,7 +108,7 @@ export function ɵɵelementContainerEnd(): void {
108108
setCurrentTNode(currentTNode, false);
109109
}
110110

111-
ngDevMode && assertNodeType(currentTNode, TNodeType.ElementContainer);
111+
ngDevMode && assertTNodeType(currentTNode, TNodeType.ElementContainer);
112112

113113
if (tView.firstCreatePass) {
114114
registerPostOrderHooks(tView, currentTNode);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export function ɵɵi18nStart(
6262
const parentRNode = getClosestRElement(tView, sameViewParentTNode, lView);
6363
// If `parentTNode` is an `ElementContainer` than it has `<!--ng-container--->`.
6464
// When we do inserts we have to make sure to insert in front of `<!--ng-container--->`.
65-
const insertInFrontOf = parentTNode && parentTNode.type === TNodeType.ElementContainer ?
65+
const insertInFrontOf = parentTNode && (parentTNode.type & TNodeType.ElementContainer) ?
6666
lView[parentTNode.index] :
6767
null;
6868
applyCreateOpCodes(lView, tI18n.create, parentRNode, insertInFrontOf);

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {PropertyAliasValue, TNode, TNodeFlags, TNodeType} from '../interfaces/no
1414
import {GlobalTargetResolver, isProceduralRenderer, RElement, Renderer3} from '../interfaces/renderer';
1515
import {isDirectiveHost} from '../interfaces/type_checks';
1616
import {CLEANUP, FLAGS, LView, LViewFlags, RENDERER, TView} from '../interfaces/view';
17-
import {assertNodeOfPossibleTypes} from '../node_assert';
17+
import {assertTNodeType} from '../node_assert';
1818
import {getCurrentDirectiveDef, getCurrentTNode, getLView, getTView} from '../state';
1919
import {getComponentLViewByIndex, getNativeByTNode, unwrapRNode} from '../util/view_utils';
2020

@@ -126,14 +126,12 @@ function listenerInternal(
126126
// register a listener and store its cleanup function on LView.
127127
const lCleanup = getLCleanup(lView);
128128

129-
ngDevMode &&
130-
assertNodeOfPossibleTypes(
131-
tNode, [TNodeType.Element, TNodeType.Container, TNodeType.ElementContainer]);
129+
ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode | TNodeType.AnyContainer);
132130

133131
let processOutputs = true;
134132

135133
// add native event listener - applicable to elements only
136-
if (tNode.type === TNodeType.Element) {
134+
if (tNode.type & TNodeType.AnyRNode) {
137135
const native = getNativeByTNode(tNode, lView) as RElement;
138136
const resolved = eventTargetResolver ? eventTargetResolver(native) : EMPTY_OBJ as any;
139137
const target = resolved.target || native;

0 commit comments

Comments
 (0)