refactor(core): Create `TNodeType.Text` to display full template in `TView` debug (#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 #39233
This commit is contained in:
parent
d50df92568
commit
70f1e2e04a
|
@ -529,7 +529,7 @@ function _queryNodeChildrenR3(
|
||||||
ngDevMode && assertTNodeForLView(tNode, lView);
|
ngDevMode && assertTNodeForLView(tNode, lView);
|
||||||
const nativeNode = getNativeByTNodeOrNull(tNode, lView);
|
const nativeNode = getNativeByTNodeOrNull(tNode, lView);
|
||||||
// For each type of TNode, specific logic is executed.
|
// For each type of TNode, specific logic is executed.
|
||||||
if (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) {
|
if (tNode.type & (TNodeType.AnyRNode | TNodeType.ElementContainer)) {
|
||||||
// Case 1: the TNode is an element
|
// Case 1: the TNode is an element
|
||||||
// The native node has to be checked.
|
// The native node has to be checked.
|
||||||
_addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode);
|
_addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode);
|
||||||
|
@ -565,14 +565,14 @@ function _queryNodeChildrenR3(
|
||||||
_queryNodeChildrenInContainerR3(
|
_queryNodeChildrenInContainerR3(
|
||||||
nodeOrContainer, predicate, matches, elementsOnly, rootNativeNode);
|
nodeOrContainer, predicate, matches, elementsOnly, rootNativeNode);
|
||||||
}
|
}
|
||||||
} else if (tNode.type === TNodeType.Container) {
|
} else if (tNode.type & TNodeType.Container) {
|
||||||
// Case 2: the TNode is a container
|
// Case 2: the TNode is a container
|
||||||
// The native node has to be checked.
|
// The native node has to be checked.
|
||||||
const lContainer = lView[tNode.index];
|
const lContainer = lView[tNode.index];
|
||||||
_addQueryMatchR3(lContainer[NATIVE], predicate, matches, elementsOnly, rootNativeNode);
|
_addQueryMatchR3(lContainer[NATIVE], predicate, matches, elementsOnly, rootNativeNode);
|
||||||
// Each view inside the container has to be processed.
|
// Each view inside the container has to be processed.
|
||||||
_queryNodeChildrenInContainerR3(lContainer, predicate, matches, elementsOnly, rootNativeNode);
|
_queryNodeChildrenInContainerR3(lContainer, predicate, matches, elementsOnly, rootNativeNode);
|
||||||
} else if (tNode.type === TNodeType.Projection) {
|
} else if (tNode.type & TNodeType.Projection) {
|
||||||
// Case 3: the TNode is a projection insertion point (i.e. a <ng-content>).
|
// Case 3: the TNode is a projection insertion point (i.e. a <ng-content>).
|
||||||
// The nodes projected at this location all need to be processed.
|
// The nodes projected at this location all need to be processed.
|
||||||
const componentView = lView![DECLARATION_COMPONENT_VIEW];
|
const componentView = lView![DECLARATION_COMPONENT_VIEW];
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {injectRootLimpMode, setInjectImplementation} from '../di/injector_compat
|
||||||
import {getInjectorDef} from '../di/interface/defs';
|
import {getInjectorDef} from '../di/interface/defs';
|
||||||
import {InjectFlags} from '../di/interface/injector';
|
import {InjectFlags} from '../di/interface/injector';
|
||||||
import {Type} from '../interface/type';
|
import {Type} from '../interface/type';
|
||||||
import {assertDefined, assertEqual, assertIndexInRange, throwError} from '../util/assert';
|
import {assertDefined, assertEqual, assertIndexInRange} from '../util/assert';
|
||||||
import {noSideEffects} from '../util/closure';
|
import {noSideEffects} from '../util/closure';
|
||||||
|
|
||||||
import {assertDirectiveDef, assertNodeInjector, assertTNodeForLView} from './assert';
|
import {assertDirectiveDef, assertNodeInjector, assertTNodeForLView} from './assert';
|
||||||
|
@ -25,7 +25,7 @@ import {isFactory, NO_PARENT_INJECTOR, NodeInjectorFactory, NodeInjectorOffset,
|
||||||
import {AttributeMarker, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TNode, TNodeProviderIndexes, TNodeType} from './interfaces/node';
|
import {AttributeMarker, TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode, TNode, TNodeProviderIndexes, TNodeType} from './interfaces/node';
|
||||||
import {isComponentDef, isComponentHost} from './interfaces/type_checks';
|
import {isComponentDef, isComponentHost} from './interfaces/type_checks';
|
||||||
import {DECLARATION_COMPONENT_VIEW, DECLARATION_VIEW, INJECTOR, LView, T_HOST, TData, TVIEW, TView, TViewType} from './interfaces/view';
|
import {DECLARATION_COMPONENT_VIEW, DECLARATION_VIEW, INJECTOR, LView, T_HOST, TData, TVIEW, TView, TViewType} from './interfaces/view';
|
||||||
import {assertNodeOfPossibleTypes} from './node_assert';
|
import {assertTNodeType} from './node_assert';
|
||||||
import {enterDI, leaveDI} from './state';
|
import {enterDI, leaveDI} from './state';
|
||||||
import {isNameOnlyAttributeMarker} from './util/attrs_utils';
|
import {isNameOnlyAttributeMarker} from './util/attrs_utils';
|
||||||
import {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_utils';
|
import {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_utils';
|
||||||
|
@ -301,9 +301,7 @@ export function diPublicInInjector(
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
export function injectAttributeImpl(tNode: TNode, attrNameToInject: string): string|null {
|
export function injectAttributeImpl(tNode: TNode, attrNameToInject: string): string|null {
|
||||||
ngDevMode &&
|
ngDevMode && assertTNodeType(tNode, TNodeType.AnyContainer | TNodeType.AnyRNode);
|
||||||
assertNodeOfPossibleTypes(
|
|
||||||
tNode, [TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer]);
|
|
||||||
ngDevMode && assertDefined(tNode, 'expecting tNode');
|
ngDevMode && assertDefined(tNode, 'expecting tNode');
|
||||||
if (attrNameToInject === 'class') {
|
if (attrNameToInject === 'class') {
|
||||||
return tNode.classes;
|
return tNode.classes;
|
||||||
|
@ -506,7 +504,7 @@ function searchTokensOnInjector<T>(
|
||||||
// - AND the parent TNode is an Element.
|
// - AND the parent TNode is an Element.
|
||||||
// This means that we just came from the Component's View and therefore are allowed to see
|
// This means that we just came from the Component's View and therefore are allowed to see
|
||||||
// into the ViewProviders.
|
// into the ViewProviders.
|
||||||
(previousTView != currentTView && (tNode.type === TNodeType.Element));
|
(previousTView != currentTView && ((tNode.type & TNodeType.AnyRNode) !== 0));
|
||||||
|
|
||||||
// This special case happens when there is a @host on the inject and when we are searching
|
// This special case happens when there is a @host on the inject and when we are searching
|
||||||
// on the host element node.
|
// on the host element node.
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {getPluralCase} from '../../i18n/localization';
|
||||||
import {assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertIndexInRange, throwError} from '../../util/assert';
|
import {assertDefined, assertDomNode, assertEqual, assertGreaterThan, assertIndexInRange, throwError} from '../../util/assert';
|
||||||
import {assertIndexInExpandoRange, assertTIcu} from '../assert';
|
import {assertIndexInExpandoRange, assertTIcu} from '../assert';
|
||||||
import {attachPatchData} from '../context_discovery';
|
import {attachPatchData} from '../context_discovery';
|
||||||
import {elementPropertyInternal, setElementAttribute, textBindingInternal} from '../instructions/shared';
|
import {elementPropertyInternal, setElementAttribute} from '../instructions/shared';
|
||||||
import {COMMENT_MARKER, ELEMENT_MARKER, getCurrentICUCaseIndex, getParentFromI18nMutateOpCode, getRefFromI18nMutateOpCode, I18nCreateOpCode, I18nCreateOpCodes, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuType, TI18n, TIcu} from '../interfaces/i18n';
|
import {COMMENT_MARKER, ELEMENT_MARKER, getCurrentICUCaseIndex, getParentFromI18nMutateOpCode, getRefFromI18nMutateOpCode, I18nCreateOpCode, I18nCreateOpCodes, I18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuType, TI18n, TIcu} from '../interfaces/i18n';
|
||||||
import {TNode} from '../interfaces/node';
|
import {TNode} from '../interfaces/node';
|
||||||
import {RElement, RNode, RText} from '../interfaces/renderer';
|
import {RElement, RNode, RText} from '../interfaces/renderer';
|
||||||
|
|
|
@ -63,7 +63,7 @@ export function addTNodeAndUpdateInsertBeforeIndex(previousTNodes: TNode[], newT
|
||||||
}
|
}
|
||||||
|
|
||||||
function isI18nText(tNode: TNode): boolean {
|
function isI18nText(tNode: TNode): boolean {
|
||||||
return tNode.type !== TNodeType.Placeholder;
|
return !(tNode.type & TNodeType.Placeholder);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isNewTNodeCreatedBefore(existingTNode: TNode, newTNode: TNode): boolean {
|
function isNewTNodeCreatedBefore(existingTNode: TNode, newTNode: TNode): boolean {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {loadIcuContainerVisitor} from '../instructions/i18n_icu_container_visito
|
||||||
import {allocExpando, createTNodeAtIndex, elementAttributeInternal, setInputsForProperty, setNgReflectProperties} from '../instructions/shared';
|
import {allocExpando, createTNodeAtIndex, elementAttributeInternal, setInputsForProperty, setNgReflectProperties} from '../instructions/shared';
|
||||||
import {getDocument} from '../interfaces/document';
|
import {getDocument} from '../interfaces/document';
|
||||||
import {COMMENT_MARKER, ELEMENT_MARKER, ensureIcuContainerVisitorLoaded, I18nCreateOpCode, I18nCreateOpCodes, I18nMutateOpCode, i18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuExpression, IcuType, TI18n, TIcu} from '../interfaces/i18n';
|
import {COMMENT_MARKER, ELEMENT_MARKER, ensureIcuContainerVisitorLoaded, I18nCreateOpCode, I18nCreateOpCodes, I18nMutateOpCode, i18nMutateOpCode, I18nMutateOpCodes, I18nUpdateOpCode, I18nUpdateOpCodes, IcuExpression, IcuType, TI18n, TIcu} from '../interfaces/i18n';
|
||||||
import {TIcuContainerNode, TNode, TNodeType} from '../interfaces/node';
|
import {TNode, TNodeType} from '../interfaces/node';
|
||||||
import {RComment, RElement} from '../interfaces/renderer';
|
import {RComment, RElement} from '../interfaces/renderer';
|
||||||
import {SanitizerFn} from '../interfaces/sanitization';
|
import {SanitizerFn} from '../interfaces/sanitization';
|
||||||
import {HEADER_OFFSET, LView, TView} from '../interfaces/view';
|
import {HEADER_OFFSET, LView, TView} from '../interfaces/view';
|
||||||
|
@ -152,7 +152,7 @@ export function i18nStartFirstCreatePass(
|
||||||
*/
|
*/
|
||||||
function createTNodeAndAddOpCode(
|
function createTNodeAndAddOpCode(
|
||||||
tView: TView, rootTNode: TNode|null, existingTNodes: TNode[], lView: LView,
|
tView: TView, rootTNode: TNode|null, existingTNodes: TNode[], lView: LView,
|
||||||
createOpCodes: I18nCreateOpCodes, text: string, isICU: boolean): TNode {
|
createOpCodes: I18nCreateOpCodes, text: string|null, isICU: boolean): TNode {
|
||||||
const i18nNodeIdx = allocExpando(tView, lView, 1);
|
const i18nNodeIdx = allocExpando(tView, lView, 1);
|
||||||
let opCode = i18nNodeIdx << I18nCreateOpCode.SHIFT;
|
let opCode = i18nNodeIdx << I18nCreateOpCode.SHIFT;
|
||||||
let parentTNode = getCurrentParentTNode();
|
let parentTNode = getCurrentParentTNode();
|
||||||
|
@ -174,9 +174,12 @@ function createTNodeAndAddOpCode(
|
||||||
opCode |= I18nCreateOpCode.COMMENT;
|
opCode |= I18nCreateOpCode.COMMENT;
|
||||||
ensureIcuContainerVisitorLoaded(loadIcuContainerVisitor);
|
ensureIcuContainerVisitorLoaded(loadIcuContainerVisitor);
|
||||||
}
|
}
|
||||||
createOpCodes.push(opCode, text);
|
createOpCodes.push(opCode, text === null ? '' : text);
|
||||||
|
// We store `{{?}}` so that when looking at debug `TNodeType.template` we can see where the
|
||||||
|
// bindings are.
|
||||||
const tNode = createTNodeAtIndex(
|
const tNode = createTNodeAtIndex(
|
||||||
tView, i18nNodeIdx, isICU ? TNodeType.IcuContainer : TNodeType.Element, null, null);
|
tView, i18nNodeIdx, isICU ? TNodeType.Icu : TNodeType.Text,
|
||||||
|
text === null ? (ngDevMode ? '{{?}}' : '') : text, null);
|
||||||
addTNodeAndUpdateInsertBeforeIndex(existingTNodes, tNode);
|
addTNodeAndUpdateInsertBeforeIndex(existingTNodes, tNode);
|
||||||
const tNodeIdx = tNode.index;
|
const tNodeIdx = tNode.index;
|
||||||
setCurrentTNode(tNode, false /* Text nodes are self closing */);
|
setCurrentTNode(tNode, false /* Text nodes are self closing */);
|
||||||
|
@ -212,7 +215,7 @@ function i18nStartFirstCreatePassProcessTextNode(
|
||||||
updateOpCodes: I18nUpdateOpCodes, lView: LView, text: string): void {
|
updateOpCodes: I18nUpdateOpCodes, lView: LView, text: string): void {
|
||||||
const hasBinding = text.match(BINDING_REGEXP);
|
const hasBinding = text.match(BINDING_REGEXP);
|
||||||
const tNode = createTNodeAndAddOpCode(
|
const tNode = createTNodeAndAddOpCode(
|
||||||
tView, rootTNode, existingTNodes, lView, createOpCodes, hasBinding ? '' : text, false);
|
tView, rootTNode, existingTNodes, lView, createOpCodes, hasBinding ? null : text, false);
|
||||||
if (hasBinding) {
|
if (hasBinding) {
|
||||||
generateBindingUpdateOpCodes(updateOpCodes, text, tNode.index);
|
generateBindingUpdateOpCodes(updateOpCodes, text, tNode.index);
|
||||||
}
|
}
|
||||||
|
@ -251,7 +254,7 @@ export function i18nAttributesFirstPass(
|
||||||
const tNode = getTNode(tView, previousElementIndex - HEADER_OFFSET);
|
const tNode = getTNode(tView, previousElementIndex - HEADER_OFFSET);
|
||||||
// Set attributes for Elements only, for other types (like ElementContainer),
|
// Set attributes for Elements only, for other types (like ElementContainer),
|
||||||
// only set inputs below
|
// only set inputs below
|
||||||
if (tNode.type === TNodeType.Element) {
|
if (tNode.type & TNodeType.AnyRNode) {
|
||||||
elementAttributeInternal(tNode, lView, attrName, value, null, null);
|
elementAttributeInternal(tNode, lView, attrName, value, null, null);
|
||||||
}
|
}
|
||||||
// Check if that attribute is a directive input
|
// Check if that attribute is a directive input
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {createTNodeAtIndex} from '../instructions/shared';
|
||||||
import {TIcu} from '../interfaces/i18n';
|
import {TIcu} from '../interfaces/i18n';
|
||||||
import {TIcuContainerNode, TNode, TNodeType} from '../interfaces/node';
|
import {TIcuContainerNode, TNode, TNodeType} from '../interfaces/node';
|
||||||
import {TView} from '../interfaces/view';
|
import {TView} from '../interfaces/view';
|
||||||
import {assertNodeType} from '../node_assert';
|
import {assertTNodeType} from '../node_assert';
|
||||||
import {addTNodeAndUpdateInsertBeforeIndex} from './i18n_insert_before_index';
|
import {addTNodeAndUpdateInsertBeforeIndex} from './i18n_insert_before_index';
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ export function setTIcu(tView: TView, index: number, tIcu: TIcu): void {
|
||||||
if (tNode === null) {
|
if (tNode === null) {
|
||||||
tView.data[index] = tIcu;
|
tView.data[index] = tIcu;
|
||||||
} else {
|
} else {
|
||||||
ngDevMode && assertNodeType(tNode, TNodeType.IcuContainer);
|
ngDevMode && assertTNodeType(tNode, TNodeType.Icu);
|
||||||
tNode.value = tIcu;
|
tNode.value = tIcu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {hasClassInput, hasStyleInput, TAttributes, TElementNode, TNode, TNodeFla
|
||||||
import {RElement} from '../interfaces/renderer';
|
import {RElement} from '../interfaces/renderer';
|
||||||
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
|
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
|
||||||
import {HEADER_OFFSET, LView, RENDERER, TView} from '../interfaces/view';
|
import {HEADER_OFFSET, LView, RENDERER, TView} from '../interfaces/view';
|
||||||
import {assertNodeType} from '../node_assert';
|
import {assertTNodeType} from '../node_assert';
|
||||||
import {appendChild, createElementNode, writeDirectClass, writeDirectStyle} from '../node_manipulation';
|
import {appendChild, createElementNode, writeDirectClass, writeDirectStyle} from '../node_manipulation';
|
||||||
import {decreaseElementDepthCount, getBindingIndex, getCurrentTNode, getElementDepthCount, getLView, getNamespace, getTView, increaseElementDepthCount, isCurrentTNodeParent, setCurrentTNode, setCurrentTNodeAsNotParent} from '../state';
|
import {decreaseElementDepthCount, getBindingIndex, getCurrentTNode, getElementDepthCount, getLView, getNamespace, getTView, increaseElementDepthCount, isCurrentTNodeParent, setCurrentTNode, setCurrentTNodeAsNotParent} from '../state';
|
||||||
import {computeStaticStyling} from '../styling/static_styling';
|
import {computeStaticStyling} from '../styling/static_styling';
|
||||||
|
@ -24,6 +24,7 @@ import {setDirectiveInputsWhichShadowsStyling} from './property';
|
||||||
import {createDirectivesInstances, executeContentQueries, getOrCreateTNode, matchingSchemas, resolveDirectives, saveResolvedLocalsInData} from './shared';
|
import {createDirectivesInstances, executeContentQueries, getOrCreateTNode, matchingSchemas, resolveDirectives, saveResolvedLocalsInData} from './shared';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function elementStartFirstCreatePass(
|
function elementStartFirstCreatePass(
|
||||||
index: number, tView: TView, lView: LView, native: RElement, name: string,
|
index: number, tView: TView, lView: LView, native: RElement, name: string,
|
||||||
attrsIndex?: number|null, localRefsIndex?: number): TElementNode {
|
attrsIndex?: number|null, localRefsIndex?: number): TElementNode {
|
||||||
|
@ -140,7 +141,7 @@ export function ɵɵelementEnd(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
const tNode = currentTNode;
|
const tNode = currentTNode;
|
||||||
ngDevMode && assertNodeType(tNode, TNodeType.Element);
|
ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode);
|
||||||
|
|
||||||
|
|
||||||
decreaseElementDepthCount();
|
decreaseElementDepthCount();
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {registerPostOrderHooks} from '../hooks';
|
||||||
import {TAttributes, TElementContainerNode, TNodeType} from '../interfaces/node';
|
import {TAttributes, TElementContainerNode, TNodeType} from '../interfaces/node';
|
||||||
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
|
import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks';
|
||||||
import {HEADER_OFFSET, LView, RENDERER, T_HOST, TView} from '../interfaces/view';
|
import {HEADER_OFFSET, LView, RENDERER, T_HOST, TView} from '../interfaces/view';
|
||||||
import {assertNodeType} from '../node_assert';
|
import {assertTNodeType} from '../node_assert';
|
||||||
import {appendChild} from '../node_manipulation';
|
import {appendChild} from '../node_manipulation';
|
||||||
import {getBindingIndex, getCurrentTNode, getLView, getTView, isCurrentTNodeParent, setCurrentTNode, setCurrentTNodeAsNotParent} from '../state';
|
import {getBindingIndex, getCurrentTNode, getLView, getTView, isCurrentTNodeParent, setCurrentTNode, setCurrentTNodeAsNotParent} from '../state';
|
||||||
import {computeStaticStyling} from '../styling/static_styling';
|
import {computeStaticStyling} from '../styling/static_styling';
|
||||||
|
@ -108,7 +108,7 @@ export function ɵɵelementContainerEnd(): void {
|
||||||
setCurrentTNode(currentTNode, false);
|
setCurrentTNode(currentTNode, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDevMode && assertNodeType(currentTNode, TNodeType.ElementContainer);
|
ngDevMode && assertTNodeType(currentTNode, TNodeType.ElementContainer);
|
||||||
|
|
||||||
if (tView.firstCreatePass) {
|
if (tView.firstCreatePass) {
|
||||||
registerPostOrderHooks(tView, currentTNode);
|
registerPostOrderHooks(tView, currentTNode);
|
||||||
|
|
|
@ -62,7 +62,7 @@ export function ɵɵi18nStart(
|
||||||
const parentRNode = getClosestRElement(tView, sameViewParentTNode, lView);
|
const parentRNode = getClosestRElement(tView, sameViewParentTNode, lView);
|
||||||
// If `parentTNode` is an `ElementContainer` than it has `<!--ng-container--->`.
|
// If `parentTNode` is an `ElementContainer` than it has `<!--ng-container--->`.
|
||||||
// When we do inserts we have to make sure to insert in front of `<!--ng-container--->`.
|
// When we do inserts we have to make sure to insert in front of `<!--ng-container--->`.
|
||||||
const insertInFrontOf = parentTNode && parentTNode.type === TNodeType.ElementContainer ?
|
const insertInFrontOf = parentTNode && (parentTNode.type & TNodeType.ElementContainer) ?
|
||||||
lView[parentTNode.index] :
|
lView[parentTNode.index] :
|
||||||
null;
|
null;
|
||||||
applyCreateOpCodes(lView, tI18n.create, parentRNode, insertInFrontOf);
|
applyCreateOpCodes(lView, tI18n.create, parentRNode, insertInFrontOf);
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {PropertyAliasValue, TNode, TNodeFlags, TNodeType} from '../interfaces/no
|
||||||
import {GlobalTargetResolver, isProceduralRenderer, RElement, Renderer3} from '../interfaces/renderer';
|
import {GlobalTargetResolver, isProceduralRenderer, RElement, Renderer3} from '../interfaces/renderer';
|
||||||
import {isDirectiveHost} from '../interfaces/type_checks';
|
import {isDirectiveHost} from '../interfaces/type_checks';
|
||||||
import {CLEANUP, FLAGS, LView, LViewFlags, RENDERER, TView} from '../interfaces/view';
|
import {CLEANUP, FLAGS, LView, LViewFlags, RENDERER, TView} from '../interfaces/view';
|
||||||
import {assertNodeOfPossibleTypes} from '../node_assert';
|
import {assertTNodeType} from '../node_assert';
|
||||||
import {getCurrentDirectiveDef, getCurrentTNode, getLView, getTView} from '../state';
|
import {getCurrentDirectiveDef, getCurrentTNode, getLView, getTView} from '../state';
|
||||||
import {getComponentLViewByIndex, getNativeByTNode, unwrapRNode} from '../util/view_utils';
|
import {getComponentLViewByIndex, getNativeByTNode, unwrapRNode} from '../util/view_utils';
|
||||||
|
|
||||||
|
@ -126,14 +126,12 @@ function listenerInternal(
|
||||||
// register a listener and store its cleanup function on LView.
|
// register a listener and store its cleanup function on LView.
|
||||||
const lCleanup = getLCleanup(lView);
|
const lCleanup = getLCleanup(lView);
|
||||||
|
|
||||||
ngDevMode &&
|
ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode | TNodeType.AnyContainer);
|
||||||
assertNodeOfPossibleTypes(
|
|
||||||
tNode, [TNodeType.Element, TNodeType.Container, TNodeType.ElementContainer]);
|
|
||||||
|
|
||||||
let processOutputs = true;
|
let processOutputs = true;
|
||||||
|
|
||||||
// add native event listener - applicable to elements only
|
// add native event listener - applicable to elements only
|
||||||
if (tNode.type === TNodeType.Element) {
|
if (tNode.type & TNodeType.AnyRNode) {
|
||||||
const native = getNativeByTNode(tNode, lView) as RElement;
|
const native = getNativeByTNode(tNode, lView) as RElement;
|
||||||
const resolved = eventTargetResolver ? eventTargetResolver(native) : EMPTY_OBJ as any;
|
const resolved = eventTargetResolver ? eventTargetResolver(native) : EMPTY_OBJ as any;
|
||||||
const target = resolved.target || native;
|
const target = resolved.target || native;
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {getInjectorIndex} from '../di';
|
||||||
import {CONTAINER_HEADER_OFFSET, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS, NATIVE} from '../interfaces/container';
|
import {CONTAINER_HEADER_OFFSET, HAS_TRANSPLANTED_VIEWS, LContainer, MOVED_VIEWS, NATIVE} from '../interfaces/container';
|
||||||
import {ComponentTemplate, DirectiveDef, DirectiveDefList, PipeDefList, ViewQueriesFunction} from '../interfaces/definition';
|
import {ComponentTemplate, DirectiveDef, DirectiveDefList, PipeDefList, ViewQueriesFunction} from '../interfaces/definition';
|
||||||
import {NO_PARENT_INJECTOR, NodeInjectorOffset} from '../interfaces/injector';
|
import {NO_PARENT_INJECTOR, NodeInjectorOffset} from '../interfaces/injector';
|
||||||
import {AttributeMarker, InsertBeforeIndex, PropertyAliases, TConstants, TContainerNode, TElementNode, TNode as ITNode, TNodeFlags, TNodeProviderIndexes, TNodeType, TNodeTypeAsString} from '../interfaces/node';
|
import {AttributeMarker, InsertBeforeIndex, PropertyAliases, TConstants, TContainerNode, TElementNode, TNode as ITNode, TNodeFlags, TNodeProviderIndexes, TNodeType, toTNodeTypeAsString} from '../interfaces/node';
|
||||||
import {SelectorFlags} from '../interfaces/projection';
|
import {SelectorFlags} from '../interfaces/projection';
|
||||||
import {LQueries, TQueries} from '../interfaces/query';
|
import {LQueries, TQueries} from '../interfaces/query';
|
||||||
import {RComment, RElement, Renderer3, RendererFactory3, RNode} from '../interfaces/renderer';
|
import {RComment, RElement, Renderer3, RendererFactory3, RNode} from '../interfaces/renderer';
|
||||||
|
@ -239,7 +239,7 @@ class TNode implements ITNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
get type_(): string {
|
get type_(): string {
|
||||||
return TNodeTypeAsString[this.type] || `TNodeType.?${this.type}?`;
|
return toTNodeTypeAsString(this.type) || `TNodeType.?${this.type}?`;
|
||||||
}
|
}
|
||||||
|
|
||||||
get flags_(): string {
|
get flags_(): string {
|
||||||
|
@ -256,7 +256,7 @@ class TNode implements ITNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
get template_(): string {
|
get template_(): string {
|
||||||
if (this.value === null && this.type === TNodeType.Element) return '#text';
|
if (this.type & TNodeType.Text) return this.value!;
|
||||||
const buf: string[] = [];
|
const buf: string[] = [];
|
||||||
const tagName = typeof this.value === 'string' && this.value || this.type_;
|
const tagName = typeof this.value === 'string' && this.value || this.type_;
|
||||||
buf.push('<', tagName);
|
buf.push('<', tagName);
|
||||||
|
@ -594,7 +594,7 @@ export function buildDebugNode(tNode: ITNode, lView: LView): DebugNode {
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
html: toHtml(native),
|
html: toHtml(native),
|
||||||
type: TNodeTypeAsString[tNode.type],
|
type: toTNodeTypeAsString(tNode.type),
|
||||||
native: native as any,
|
native: native as any,
|
||||||
children: toDebugNodes(tNode.child, lView),
|
children: toDebugNodes(tNode.child, lView),
|
||||||
factories,
|
factories,
|
||||||
|
|
|
@ -30,8 +30,8 @@ import { AttributeMarker, InitialInputData, InitialInputs, LocalRefExtractor, Pr
|
||||||
import {isProceduralRenderer, RComment, RElement, Renderer3, RendererFactory3, RNode, RText} from '../interfaces/renderer';
|
import {isProceduralRenderer, RComment, RElement, Renderer3, RendererFactory3, RNode, RText} from '../interfaces/renderer';
|
||||||
import {SanitizerFn} from '../interfaces/sanitization';
|
import {SanitizerFn} from '../interfaces/sanitization';
|
||||||
import {isComponentDef, isComponentHost, isContentQueryHost, isRootView} from '../interfaces/type_checks';
|
import {isComponentDef, isComponentHost, isContentQueryHost, isRootView} from '../interfaces/type_checks';
|
||||||
import { CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_COMPONENT_VIEW, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, InitPhaseState, INJECTOR, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, TData, TRANSPLANTED_VIEWS_TO_REFRESH, TVIEW, TView, TViewType, T_HOST } from '../interfaces/view';
|
import {CHILD_HEAD, CHILD_TAIL, CLEANUP, CONTEXT, DECLARATION_COMPONENT_VIEW, DECLARATION_VIEW, FLAGS, HEADER_OFFSET, HOST, InitPhaseState, INJECTOR, LView, LViewFlags, NEXT, PARENT, RENDERER, RENDERER_FACTORY, RootContext, RootContextFlags, SANITIZER, T_HOST, TData, TRANSPLANTED_VIEWS_TO_REFRESH, TVIEW, TView, TViewType} from '../interfaces/view';
|
||||||
import { assertNodeNotOfTypes, assertNodeOfPossibleTypes } from '../node_assert';
|
import {assertPureTNodeType, assertTNodeType} from '../node_assert';
|
||||||
import {updateTextNode} from '../node_manipulation';
|
import {updateTextNode} from '../node_manipulation';
|
||||||
import {isInlineTemplate, isNodeMatchingSelectorList} from '../node_selector_matcher';
|
import {isInlineTemplate, isNodeMatchingSelectorList} from '../node_selector_matcher';
|
||||||
import {enterView, getBindingsEnabled, getCurrentDirectiveIndex, getCurrentParentTNode, getCurrentTNode, getCurrentTNodePlaceholderOk, getSelectedIndex, isCurrentTNodeParent, isInCheckNoChangesMode, isInI18nBlock, leaveView, setBindingIndex, setBindingRootForHostBindings, setCurrentDirectiveIndex, setCurrentQueryIndex, setCurrentTNode, setIsInCheckNoChangesMode, setSelectedIndex} from '../state';
|
import {enterView, getBindingsEnabled, getCurrentDirectiveIndex, getCurrentParentTNode, getCurrentTNode, getCurrentTNodePlaceholderOk, getSelectedIndex, isCurrentTNodeParent, isInCheckNoChangesMode, isInI18nBlock, leaveView, setBindingIndex, setBindingRootForHostBindings, setCurrentDirectiveIndex, setCurrentQueryIndex, setCurrentTNode, setIsInCheckNoChangesMode, setSelectedIndex} from '../state';
|
||||||
|
@ -40,6 +40,7 @@ import { isAnimationProp, mergeHostAttrs } from '../util/attrs_utils';
|
||||||
import {INTERPOLATION_DELIMITER, renderStringify, stringifyForError} from '../util/misc_utils';
|
import {INTERPOLATION_DELIMITER, renderStringify, stringifyForError} from '../util/misc_utils';
|
||||||
import {getFirstLContainer, getLViewParent, getNextLContainer} from '../util/view_traversal_utils';
|
import {getFirstLContainer, getLViewParent, getNextLContainer} from '../util/view_traversal_utils';
|
||||||
import {getComponentLViewByIndex, getNativeByIndex, getNativeByTNode, isCreationMode, readPatchedLView, resetPreOrderHookFlags, unwrapLView, updateTransplantedViewCount, viewAttachedToChangeDetector} from '../util/view_utils';
|
import {getComponentLViewByIndex, getNativeByIndex, getNativeByTNode, isCreationMode, readPatchedLView, resetPreOrderHookFlags, unwrapLView, updateTransplantedViewCount, viewAttachedToChangeDetector} from '../util/view_utils';
|
||||||
|
|
||||||
import {selectIndexInternal} from './advance';
|
import {selectIndexInternal} from './advance';
|
||||||
import {attachLContainerDebug, attachLViewDebug, cloneToLViewFromTViewBlueprint, cloneToTViewData, LCleanup, LViewBlueprint, MatchesArray, TCleanup, TNodeDebug, TNodeInitialInputs, TNodeLocalNames, TViewComponents, TViewConstructor} from './lview_debug';
|
import {attachLContainerDebug, attachLViewDebug, cloneToLViewFromTViewBlueprint, cloneToTViewData, LCleanup, LViewBlueprint, MatchesArray, TCleanup, TNodeDebug, TNodeInitialInputs, TNodeLocalNames, TViewComponents, TViewConstructor} from './lview_debug';
|
||||||
|
|
||||||
|
@ -196,7 +197,7 @@ export function createLView<T>(
|
||||||
* @param attrs Any attrs for the native element, if applicable
|
* @param attrs Any attrs for the native element, if applicable
|
||||||
*/
|
*/
|
||||||
export function getOrCreateTNode(
|
export function getOrCreateTNode(
|
||||||
tView: TView, index: number, type: TNodeType.Element, name: string|null,
|
tView: TView, index: number, type: TNodeType.Element|TNodeType.Text, name: string|null,
|
||||||
attrs: TAttributes|null): TElementNode;
|
attrs: TAttributes|null): TElementNode;
|
||||||
export function getOrCreateTNode(
|
export function getOrCreateTNode(
|
||||||
tView: TView, index: number, type: TNodeType.Container, name: string|null,
|
tView: TView, index: number, type: TNodeType.Container, name: string|null,
|
||||||
|
@ -208,12 +209,13 @@ export function getOrCreateTNode(
|
||||||
tView: TView, index: number, type: TNodeType.ElementContainer, name: string|null,
|
tView: TView, index: number, type: TNodeType.ElementContainer, name: string|null,
|
||||||
attrs: TAttributes|null): TElementContainerNode;
|
attrs: TAttributes|null): TElementContainerNode;
|
||||||
export function getOrCreateTNode(
|
export function getOrCreateTNode(
|
||||||
tView: TView, index: number, type: TNodeType.IcuContainer, name: null,
|
tView: TView, index: number, type: TNodeType.Icu, name: null,
|
||||||
attrs: TAttributes|null): TElementContainerNode;
|
attrs: TAttributes|null): TElementContainerNode;
|
||||||
export function getOrCreateTNode(
|
export function getOrCreateTNode(
|
||||||
tView: TView, index: number, type: TNodeType, name: string|null, attrs: TAttributes|null):
|
tView: TView, index: number, type: TNodeType, name: string|null, attrs: TAttributes|null):
|
||||||
TElementNode&TContainerNode&TElementContainerNode&TProjectionNode&TIcuContainerNode {
|
TElementNode&TContainerNode&TElementContainerNode&TProjectionNode&TIcuContainerNode {
|
||||||
// Keep this function short, so that the VM will inline it.
|
// Keep this function short, so that the VM will inline it.
|
||||||
|
ngDevMode && assertPureTNodeType(type);
|
||||||
const adjustedIndex = index + HEADER_OFFSET;
|
const adjustedIndex = index + HEADER_OFFSET;
|
||||||
let tNode = tView.data[adjustedIndex] as TNode;
|
let tNode = tView.data[adjustedIndex] as TNode;
|
||||||
if (tNode === null) {
|
if (tNode === null) {
|
||||||
|
@ -225,7 +227,7 @@ export function getOrCreateTNode(
|
||||||
// removed, so we mark it as detached.
|
// removed, so we mark it as detached.
|
||||||
tNode.flags |= TNodeFlags.isDetached;
|
tNode.flags |= TNodeFlags.isDetached;
|
||||||
}
|
}
|
||||||
} else if (tNode.type == TNodeType.Placeholder) {
|
} else if (tNode.type & TNodeType.Placeholder) {
|
||||||
tNode.type = type;
|
tNode.type = type;
|
||||||
tNode.value = name;
|
tNode.value = name;
|
||||||
tNode.attrs = attrs;
|
tNode.attrs = attrs;
|
||||||
|
@ -818,13 +820,13 @@ export function createTNode(
|
||||||
tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Container,
|
tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Container,
|
||||||
adjustedIndex: number, tagName: string|null, attrs: TAttributes|null): TContainerNode;
|
adjustedIndex: number, tagName: string|null, attrs: TAttributes|null): TContainerNode;
|
||||||
export function createTNode(
|
export function createTNode(
|
||||||
tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Element,
|
tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Element|TNodeType.Text,
|
||||||
adjustedIndex: number, tagName: string|null, attrs: TAttributes|null): TElementNode;
|
adjustedIndex: number, tagName: string|null, attrs: TAttributes|null): TElementNode;
|
||||||
export function createTNode(
|
export function createTNode(
|
||||||
tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.ElementContainer,
|
tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.ElementContainer,
|
||||||
adjustedIndex: number, tagName: string|null, attrs: TAttributes|null): TElementContainerNode;
|
adjustedIndex: number, tagName: string|null, attrs: TAttributes|null): TElementContainerNode;
|
||||||
export function createTNode(
|
export function createTNode(
|
||||||
tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.IcuContainer,
|
tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Icu,
|
||||||
adjustedIndex: number, tagName: string|null, attrs: TAttributes|null): TIcuContainerNode;
|
adjustedIndex: number, tagName: string|null, attrs: TAttributes|null): TIcuContainerNode;
|
||||||
export function createTNode(
|
export function createTNode(
|
||||||
tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Projection,
|
tView: TView, tParent: TElementNode|TContainerNode|null, type: TNodeType.Projection,
|
||||||
|
@ -1012,7 +1014,7 @@ export function elementPropertyInternal<T>(
|
||||||
if (ngDevMode) {
|
if (ngDevMode) {
|
||||||
setNgReflectProperties(lView, element, tNode.type, dataValue, value);
|
setNgReflectProperties(lView, element, tNode.type, dataValue, value);
|
||||||
}
|
}
|
||||||
} else if (tNode.type === TNodeType.Element) {
|
} else if (tNode.type & TNodeType.AnyRNode) {
|
||||||
propName = mapPropName(propName);
|
propName = mapPropName(propName);
|
||||||
|
|
||||||
if (ngDevMode) {
|
if (ngDevMode) {
|
||||||
|
@ -1034,7 +1036,7 @@ export function elementPropertyInternal<T>(
|
||||||
(element as RElement).setProperty ? (element as any).setProperty(propName, value) :
|
(element as RElement).setProperty ? (element as any).setProperty(propName, value) :
|
||||||
(element as any)[propName] = value;
|
(element as any)[propName] = value;
|
||||||
}
|
}
|
||||||
} else if (tNode.type === TNodeType.Container || tNode.type === TNodeType.ElementContainer) {
|
} else if (tNode.type & TNodeType.AnyContainer) {
|
||||||
// If the node is a container and the property didn't
|
// If the node is a container and the property didn't
|
||||||
// match any of the inputs or schemas we should throw.
|
// match any of the inputs or schemas we should throw.
|
||||||
if (ngDevMode && !matchingSchemas(tView, tNode.value)) {
|
if (ngDevMode && !matchingSchemas(tView, tNode.value)) {
|
||||||
|
@ -1057,7 +1059,7 @@ function setNgReflectProperty(
|
||||||
const renderer = lView[RENDERER];
|
const renderer = lView[RENDERER];
|
||||||
attrName = normalizeDebugBindingName(attrName);
|
attrName = normalizeDebugBindingName(attrName);
|
||||||
const debugValue = normalizeDebugBindingValue(value);
|
const debugValue = normalizeDebugBindingValue(value);
|
||||||
if (type === TNodeType.Element) {
|
if (type & TNodeType.AnyRNode) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
isProceduralRenderer(renderer) ? renderer.removeAttribute((element as RElement), attrName) :
|
isProceduralRenderer(renderer) ? renderer.removeAttribute((element as RElement), attrName) :
|
||||||
(element as RElement).removeAttribute(attrName);
|
(element as RElement).removeAttribute(attrName);
|
||||||
|
@ -1079,7 +1081,7 @@ function setNgReflectProperty(
|
||||||
export function setNgReflectProperties(
|
export function setNgReflectProperties(
|
||||||
lView: LView, element: RElement|RComment, type: TNodeType, dataValue: PropertyAliasValue,
|
lView: LView, element: RElement|RComment, type: TNodeType, dataValue: PropertyAliasValue,
|
||||||
value: any) {
|
value: any) {
|
||||||
if (type === TNodeType.Element || type === TNodeType.Container) {
|
if (type & (TNodeType.AnyRNode | TNodeType.Container)) {
|
||||||
/**
|
/**
|
||||||
* dataValue is an array containing runtime input or output names for the directives:
|
* dataValue is an array containing runtime input or output names for the directives:
|
||||||
* i+0: directive instance index
|
* i+0: directive instance index
|
||||||
|
@ -1300,7 +1302,7 @@ function instantiateAllDirectives(
|
||||||
const isComponent = isComponentDef(def);
|
const isComponent = isComponentDef(def);
|
||||||
|
|
||||||
if (isComponent) {
|
if (isComponent) {
|
||||||
ngDevMode && assertNodeOfPossibleTypes(tNode, [TNodeType.Element]);
|
ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode);
|
||||||
addComponentLogic(lView, tNode as TElementNode, def as ComponentDef<any>);
|
addComponentLogic(lView, tNode as TElementNode, def as ComponentDef<any>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1386,9 +1388,7 @@ function findDirectiveDefMatches(
|
||||||
tView: TView, viewData: LView,
|
tView: TView, viewData: LView,
|
||||||
tNode: TElementNode|TContainerNode|TElementContainerNode): DirectiveDef<any>[]|null {
|
tNode: TElementNode|TContainerNode|TElementContainerNode): DirectiveDef<any>[]|null {
|
||||||
ngDevMode && assertFirstCreatePass(tView);
|
ngDevMode && assertFirstCreatePass(tView);
|
||||||
ngDevMode &&
|
ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode | TNodeType.AnyContainer);
|
||||||
assertNodeOfPossibleTypes(
|
|
||||||
tNode, [TNodeType.Element, TNodeType.ElementContainer, TNodeType.Container]);
|
|
||||||
|
|
||||||
const registry = tView.directiveRegistry;
|
const registry = tView.directiveRegistry;
|
||||||
let matches: any[]|null = null;
|
let matches: any[]|null = null;
|
||||||
|
@ -1401,8 +1401,8 @@ function findDirectiveDefMatches(
|
||||||
|
|
||||||
if (isComponentDef(def)) {
|
if (isComponentDef(def)) {
|
||||||
if (ngDevMode) {
|
if (ngDevMode) {
|
||||||
assertNodeOfPossibleTypes(
|
assertTNodeType(
|
||||||
tNode, [TNodeType.Element],
|
tNode, TNodeType.Element,
|
||||||
`"${tNode.value}" tags cannot be used as component hosts. ` +
|
`"${tNode.value}" tags cannot be used as component hosts. ` +
|
||||||
`Please use a different tag to activate the ${stringify(def.type)} component.`);
|
`Please use a different tag to activate the ${stringify(def.type)} component.`);
|
||||||
|
|
||||||
|
@ -1518,8 +1518,8 @@ export function elementAttributeInternal(
|
||||||
if (ngDevMode) {
|
if (ngDevMode) {
|
||||||
assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.');
|
assertNotSame(value, NO_CHANGE as any, 'Incoming value should never be NO_CHANGE.');
|
||||||
validateAgainstEventAttributes(name);
|
validateAgainstEventAttributes(name);
|
||||||
assertNodeNotOfTypes(
|
assertTNodeType(
|
||||||
tNode, [TNodeType.Container, TNodeType.ElementContainer],
|
tNode, TNodeType.Element,
|
||||||
`Attempted to set attribute \`${name}\` on a container node. ` +
|
`Attempted to set attribute \`${name}\` on a container node. ` +
|
||||||
`Host bindings are not valid on ng-container or ng-template.`);
|
`Host bindings are not valid on ng-container or ng-template.`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -705,7 +705,7 @@ function updateStylingMap(
|
||||||
function updateStyling(
|
function updateStyling(
|
||||||
tView: TView, tNode: TNode, lView: LView, renderer: Renderer3, prop: string,
|
tView: TView, tNode: TNode, lView: LView, renderer: Renderer3, prop: string,
|
||||||
value: string|undefined|null|boolean, isClassBased: boolean, bindingIndex: number) {
|
value: string|undefined|null|boolean, isClassBased: boolean, bindingIndex: number) {
|
||||||
if (tNode.type !== TNodeType.Element) {
|
if (!(tNode.type & TNodeType.AnyRNode)) {
|
||||||
// It is possible to have styling on non-elements (such as ng-container).
|
// It is possible to have styling on non-elements (such as ng-container).
|
||||||
// This is rare, but it does happen. In such a case, just ignore the binding.
|
// This is rare, but it does happen. In such a case, just ignore the binding.
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -35,7 +35,7 @@ export function ɵɵtext(index: number, value: string = ''): void {
|
||||||
ngDevMode && assertIndexInRange(lView, adjustedIndex);
|
ngDevMode && assertIndexInRange(lView, adjustedIndex);
|
||||||
|
|
||||||
const tNode = tView.firstCreatePass ?
|
const tNode = tView.firstCreatePass ?
|
||||||
getOrCreateTNode(tView, index, TNodeType.Element, null, null) :
|
getOrCreateTNode(tView, index, TNodeType.Text, value, null) :
|
||||||
tView.data[adjustedIndex] as TElementNode;
|
tView.data[adjustedIndex] as TElementNode;
|
||||||
|
|
||||||
const textNative = lView[adjustedIndex] = createTextNode(lView[RENDERER], value);
|
const textNative = lView[adjustedIndex] = createTextNode(lView[RENDERER], value);
|
||||||
|
|
|
@ -15,30 +15,47 @@ import {LView, TView} from './view';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TNodeType corresponds to the {@link TNode} `type` property.
|
* TNodeType corresponds to the {@link TNode} `type` property.
|
||||||
|
*
|
||||||
|
* NOTE: type IDs are such that we use each bit to denote a type. This is done so that we can easily
|
||||||
|
* check if the `TNode` is of more than one type.
|
||||||
|
*
|
||||||
|
* `if (tNode.type === TNodeType.Text || tNode.type === TNode.Element)`
|
||||||
|
* can be written as:
|
||||||
|
* `if (tNode.type & (TNodeType.Text | TNodeType.Element))`
|
||||||
|
*
|
||||||
|
* However any given `TNode` can only be of one type.
|
||||||
*/
|
*/
|
||||||
export const enum TNodeType {
|
export const enum TNodeType {
|
||||||
// FIXME(misko): Add `Text` type so that it would be much easier to reason/debug about `TNode`s.
|
/**
|
||||||
|
* The TNode contains information about a DOM element aka {@link RText}.
|
||||||
|
*/
|
||||||
|
Text = 0b1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TNode contains information about a DOM element aka {@link RElement}.
|
||||||
|
*/
|
||||||
|
Element = 0b10,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The TNode contains information about an {@link LContainer} for embedded views.
|
* The TNode contains information about an {@link LContainer} for embedded views.
|
||||||
*/
|
*/
|
||||||
// FIXME(misko): Verify that we still need a `Container`, at the very least update the text.
|
Container = 0b100,
|
||||||
Container = 0,
|
|
||||||
/**
|
|
||||||
* The TNode contains information about an `<ng-content>` projection
|
|
||||||
*/
|
|
||||||
Projection = 1,
|
|
||||||
/**
|
|
||||||
* The TNode contains information about a DOM element aka {@link RNode}.
|
|
||||||
*/
|
|
||||||
Element = 2,
|
|
||||||
/**
|
/**
|
||||||
* The TNode contains information about an `<ng-container>` element {@link RNode}.
|
* The TNode contains information about an `<ng-container>` element {@link RNode}.
|
||||||
*/
|
*/
|
||||||
ElementContainer = 3,
|
ElementContainer = 0b1000,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TNode contains information about an `<ng-content>` projection
|
||||||
|
*/
|
||||||
|
Projection = 0b10000,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The TNode contains information about an ICU comment used in `i18n`.
|
* The TNode contains information about an ICU comment used in `i18n`.
|
||||||
*/
|
*/
|
||||||
IcuContainer = 4,
|
Icu = 0b100000,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special node type representing a placeholder for future `TNode` at this location.
|
* Special node type representing a placeholder for future `TNode` at this location.
|
||||||
*
|
*
|
||||||
|
@ -52,22 +69,31 @@ export const enum TNodeType {
|
||||||
* location. Seeing a `Placeholder` `TNode` already there tells the system that it should reuse
|
* location. Seeing a `Placeholder` `TNode` already there tells the system that it should reuse
|
||||||
* existing `TNode` (rather than create a new one) and just update the missing information.
|
* existing `TNode` (rather than create a new one) and just update the missing information.
|
||||||
*/
|
*/
|
||||||
Placeholder = 5,
|
Placeholder = 0b1000000,
|
||||||
|
|
||||||
|
// Combined Types These should never be used for `TNode.type` only as a useful way to check
|
||||||
|
// if `TNode.type` is one of several choices.
|
||||||
|
|
||||||
|
// See: https://github.com/microsoft/TypeScript/issues/35875 why we can't refer to existing enum.
|
||||||
|
AnyRNode = 0b11, // Text | Element,
|
||||||
|
AnyContainer = 0b1100, // Container | ElementContainer, // See:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts `TNodeType` into human readable text.
|
* Converts `TNodeType` into human readable text.
|
||||||
* Make sure this matches with `TNodeType`
|
* Make sure this matches with `TNodeType`
|
||||||
*/
|
*/
|
||||||
export const TNodeTypeAsString = [
|
export function toTNodeTypeAsString(tNodeType: TNodeType): string {
|
||||||
'Container', // 0
|
let text = '';
|
||||||
'Projection', // 1
|
(tNodeType & TNodeType.Text) && (text += '|Text');
|
||||||
'Element', // 2
|
(tNodeType & TNodeType.Element) && (text += '|Element');
|
||||||
'ElementContainer', // 3
|
(tNodeType & TNodeType.Container) && (text += '|Container');
|
||||||
'IcuContainer', // 4
|
(tNodeType & TNodeType.ElementContainer) && (text += '|ElementContainer');
|
||||||
'Placeholder', // 5
|
(tNodeType & TNodeType.Projection) && (text += '|Projection');
|
||||||
] as const;
|
(tNodeType & TNodeType.Icu) && (text += '|IcuContainer');
|
||||||
|
(tNodeType & TNodeType.Placeholder) && (text += '|Placeholder');
|
||||||
|
return text.length > 0 ? text.substring(1) : text;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Corresponds to the TNode.flags property.
|
* Corresponds to the TNode.flags property.
|
||||||
|
@ -223,7 +249,8 @@ export const enum AttributeMarker {
|
||||||
Template = 4,
|
Template = 4,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that the following attribute is `ngProjectAs` and its value is a parsed `CssSelector`.
|
* Signals that the following attribute is `ngProjectAs` and its value is a parsed
|
||||||
|
* `CssSelector`.
|
||||||
*
|
*
|
||||||
* For example, given the following HTML:
|
* For example, given the following HTML:
|
||||||
*
|
*
|
||||||
|
@ -273,10 +300,10 @@ export type TAttributes = (string|AttributeMarker|CssSelector)[];
|
||||||
export type TConstants = (TAttributes|string)[];
|
export type TConstants = (TAttributes|string)[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory function that returns an array of consts. Consts can be represented as a function in case
|
* Factory function that returns an array of consts. Consts can be represented as a function in
|
||||||
* any additional statements are required to define consts in the list. An example is i18n where
|
* case any additional statements are required to define consts in the list. An example is i18n
|
||||||
* additional i18n calls are generated, which should be executed when consts are requested for the
|
* where additional i18n calls are generated, which should be executed when consts are requested
|
||||||
* first time.
|
* for the first time.
|
||||||
*/
|
*/
|
||||||
export type TConstantsFactory = () => TConstants;
|
export type TConstantsFactory = () => TConstants;
|
||||||
|
|
||||||
|
@ -332,8 +359,8 @@ export interface TNode {
|
||||||
* nodes. It can also insert `Hello ` and `!` text node as a child of `<div>`, but it can't
|
* nodes. It can also insert `Hello ` and `!` text node as a child of `<div>`, but it can't
|
||||||
* insert `World` because the `<span>` node has not yet been created. In such a case the
|
* insert `World` because the `<span>` node has not yet been created. In such a case the
|
||||||
* `<span>` `TNode` will have an array which will direct the `<span>` to not only insert
|
* `<span>` `TNode` will have an array which will direct the `<span>` to not only insert
|
||||||
* itself in front of `!` but also to insert the `World` (created by `ɵɵi18nStart`) into `<span>`
|
* itself in front of `!` but also to insert the `World` (created by `ɵɵi18nStart`) into
|
||||||
* itself.
|
* `<span>` itself.
|
||||||
*
|
*
|
||||||
* Pseudo code:
|
* Pseudo code:
|
||||||
* ```
|
* ```
|
||||||
|
@ -369,10 +396,11 @@ export interface TNode {
|
||||||
*
|
*
|
||||||
* If the index === -1, there is no injector on this node or any ancestor node in this view.
|
* If the index === -1, there is no injector on this node or any ancestor node in this view.
|
||||||
*
|
*
|
||||||
* If the index !== -1, it is the index of this node's injector OR the index of a parent injector
|
* If the index !== -1, it is the index of this node's injector OR the index of a parent
|
||||||
* in the same view. We pass the parent injector index down the node tree of a view so it's
|
* injector in the same view. We pass the parent injector index down the node tree of a view so
|
||||||
* possible to find the parent injector without walking a potentially deep node tree. Injector
|
* it's possible to find the parent injector without walking a potentially deep node tree.
|
||||||
* indices are not set across view boundaries because there could be multiple component hosts.
|
* Injector indices are not set across view boundaries because there could be multiple component
|
||||||
|
* hosts.
|
||||||
*
|
*
|
||||||
* If tNode.injectorIndex === tNode.parent.injectorIndex, then the index belongs to a parent
|
* If tNode.injectorIndex === tNode.parent.injectorIndex, then the index belongs to a parent
|
||||||
* injector.
|
* injector.
|
||||||
|
@ -398,8 +426,8 @@ export interface TNode {
|
||||||
*
|
*
|
||||||
* Valid values are:
|
* Valid values are:
|
||||||
* - `-1` No `hostBindings` instruction has executed.
|
* - `-1` No `hostBindings` instruction has executed.
|
||||||
* - `directiveStart <= directiveStylingLast < directiveEnd`: Points to the `DirectiveDef` of the
|
* - `directiveStart <= directiveStylingLast < directiveEnd`: Points to the `DirectiveDef` of
|
||||||
* last styling instruction which executed in the `hostBindings`.
|
* the last styling instruction which executed in the `hostBindings`.
|
||||||
*
|
*
|
||||||
* This data is needed so that styling instructions know which static styling data needs to be
|
* This data is needed so that styling instructions know which static styling data needs to be
|
||||||
* collected from the `DirectiveDef.hostAttrs`. A styling instruction needs to collect all data
|
* collected from the `DirectiveDef.hostAttrs`. A styling instruction needs to collect all data
|
||||||
|
@ -408,13 +436,14 @@ export interface TNode {
|
||||||
directiveStylingLast: number;
|
directiveStylingLast: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores indexes of property bindings. This field is only set in the ngDevMode and holds indexes
|
* Stores indexes of property bindings. This field is only set in the ngDevMode and holds
|
||||||
* of property bindings so TestBed can get bound property metadata for a given node.
|
* indexes of property bindings so TestBed can get bound property metadata for a given node.
|
||||||
*/
|
*/
|
||||||
propertyBindings: number[]|null;
|
propertyBindings: number[]|null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores if Node isComponent, isProjected, hasContentQuery, hasClassInput and hasStyleInput etc.
|
* Stores if Node isComponent, isProjected, hasContentQuery, hasClassInput and hasStyleInput
|
||||||
|
* etc.
|
||||||
*/
|
*/
|
||||||
flags: TNodeFlags;
|
flags: TNodeFlags;
|
||||||
|
|
||||||
|
@ -437,8 +466,8 @@ export interface TNode {
|
||||||
value: any;
|
value: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attributes associated with an element. We need to store attributes to support various use-cases
|
* Attributes associated with an element. We need to store attributes to support various
|
||||||
* (attribute injection, content projection with selectors, directives matching).
|
* use-cases (attribute injection, content projection with selectors, directives matching).
|
||||||
* Attributes are stored statically because reading them from the DOM would be way too slow for
|
* Attributes are stored statically because reading them from the DOM would be way too slow for
|
||||||
* content projection and queries.
|
* content projection and queries.
|
||||||
*
|
*
|
||||||
|
@ -528,10 +557,10 @@ export interface TNode {
|
||||||
next: TNode|null;
|
next: TNode|null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The next projected sibling. Since in Angular content projection works on the node-by-node basis
|
* The next projected sibling. Since in Angular content projection works on the node-by-node
|
||||||
* the act of projecting nodes might change nodes relationship at the insertion point (target
|
* basis the act of projecting nodes might change nodes relationship at the insertion point
|
||||||
* view). At the same time we need to keep initial relationship between nodes as expressed in
|
* (target view). At the same time we need to keep initial relationship between nodes as
|
||||||
* content view.
|
* expressed in content view.
|
||||||
*/
|
*/
|
||||||
projectionNext: TNode|null;
|
projectionNext: TNode|null;
|
||||||
|
|
||||||
|
@ -584,8 +613,8 @@ export interface TNode {
|
||||||
* - `projection` size is equal to the number of projections `<ng-content>`. The size of
|
* - `projection` size is equal to the number of projections `<ng-content>`. The size of
|
||||||
* `c1` will be `1` because `<child>` has only one `<ng-content>`.
|
* `c1` will be `1` because `<child>` has only one `<ng-content>`.
|
||||||
* - we store `projection` with the host (`c1`, `c2`) rather than the `<ng-content>` (`cont1`)
|
* - we store `projection` with the host (`c1`, `c2`) rather than the `<ng-content>` (`cont1`)
|
||||||
* because the same component (`<child>`) can be used in multiple locations (`c1`, `c2`) and as
|
* because the same component (`<child>`) can be used in multiple locations (`c1`, `c2`) and
|
||||||
* a result have different set of nodes to project.
|
* as a result have different set of nodes to project.
|
||||||
* - without `projection` it would be difficult to efficiently traverse nodes to be projected.
|
* - without `projection` it would be difficult to efficiently traverse nodes to be projected.
|
||||||
*
|
*
|
||||||
* If `typeof projection == 'number'` then `TNode` is a `<ng-content>` element:
|
* If `typeof projection == 'number'` then `TNode` is a `<ng-content>` element:
|
||||||
|
@ -619,9 +648,9 @@ export interface TNode {
|
||||||
* (e.g. `<div style="width:200px;">`)
|
* (e.g. `<div style="width:200px;">`)
|
||||||
* Must be stored separately from `tNode.styles` to facilitate setting directive
|
* Must be stored separately from `tNode.styles` to facilitate setting directive
|
||||||
* inputs that shadow the `style` property. If we used `tNode.styles` as is for shadowed inputs,
|
* inputs that shadow the `style` property. If we used `tNode.styles` as is for shadowed inputs,
|
||||||
* we would feed host styles back into directives as "inputs". If we used `tNode.attrs`, we would
|
* we would feed host styles back into directives as "inputs". If we used `tNode.attrs`, we
|
||||||
* have to concatenate the attributes on every template pass. Instead, we process once on first
|
* would have to concatenate the attributes on every template pass. Instead, we process once on
|
||||||
* create pass and store here.
|
* first create pass and store here.
|
||||||
*/
|
*/
|
||||||
stylesWithoutHost: string|null;
|
stylesWithoutHost: string|null;
|
||||||
|
|
||||||
|
@ -629,8 +658,8 @@ export interface TNode {
|
||||||
* A `KeyValueArray` version of residual `styles`.
|
* A `KeyValueArray` version of residual `styles`.
|
||||||
*
|
*
|
||||||
* When there are styling instructions than each instruction stores the static styling
|
* When there are styling instructions than each instruction stores the static styling
|
||||||
* which is of lower priority than itself. This means that there may be a higher priority styling
|
* which is of lower priority than itself. This means that there may be a higher priority
|
||||||
* than the instruction.
|
* styling than the instruction.
|
||||||
*
|
*
|
||||||
* Imagine:
|
* Imagine:
|
||||||
* ```
|
* ```
|
||||||
|
@ -671,10 +700,10 @@ export interface TNode {
|
||||||
* Populated when there are one or more initial classes on an element
|
* Populated when there are one or more initial classes on an element
|
||||||
* (e.g. `<div class="SOME_CLASS">`)
|
* (e.g. `<div class="SOME_CLASS">`)
|
||||||
* Must be stored separately from `tNode.classes` to facilitate setting directive
|
* Must be stored separately from `tNode.classes` to facilitate setting directive
|
||||||
* inputs that shadow the `class` property. If we used `tNode.classes` as is for shadowed inputs,
|
* inputs that shadow the `class` property. If we used `tNode.classes` as is for shadowed
|
||||||
* we would feed host classes back into directives as "inputs". If we used `tNode.attrs`, we would
|
* inputs, we would feed host classes back into directives as "inputs". If we used
|
||||||
* have to concatenate the attributes on every template pass. Instead, we process once on first
|
* `tNode.attrs`, we would have to concatenate the attributes on every template pass. Instead,
|
||||||
* create pass and store here.
|
* we process once on first create pass and store here.
|
||||||
*/
|
*/
|
||||||
classesWithoutHost: string|null;
|
classesWithoutHost: string|null;
|
||||||
|
|
||||||
|
@ -740,8 +769,8 @@ export interface TElementNode extends TNode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this is a component TNode with projection, this will be an array of projected
|
* If this is a component TNode with projection, this will be an array of projected
|
||||||
* TNodes or native nodes (see TNode.projection for more info). If it's a regular element node or
|
* TNodes or native nodes (see TNode.projection for more info). If it's a regular element node
|
||||||
* a component without projection, it will be null.
|
* or a component without projection, it will be null.
|
||||||
*/
|
*/
|
||||||
projection: (TNode|RNode[])[]|null;
|
projection: (TNode|RNode[])[]|null;
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {Sanitizer} from '../../sanitization/sanitizer';
|
||||||
import {LContainer} from './container';
|
import {LContainer} from './container';
|
||||||
import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefList, HostBindingsFunction, PipeDef, PipeDefList, ViewQueriesFunction} from './definition';
|
import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefList, HostBindingsFunction, PipeDef, PipeDefList, ViewQueriesFunction} from './definition';
|
||||||
import {I18nUpdateOpCodes, TI18n, TIcu} from './i18n';
|
import {I18nUpdateOpCodes, TI18n, TIcu} from './i18n';
|
||||||
import {TConstants, TNode, TNodeTypeAsString} from './node';
|
import {TConstants, TNode} from './node';
|
||||||
import {PlayerHandler} from './player';
|
import {PlayerHandler} from './player';
|
||||||
import {LQueries, TQueries} from './query';
|
import {LQueries, TQueries} from './query';
|
||||||
import {RComment, RElement, Renderer3, RendererFactory3} from './renderer';
|
import {RComment, RElement, Renderer3, RendererFactory3} from './renderer';
|
||||||
|
@ -1025,7 +1025,7 @@ export interface DebugNode {
|
||||||
/**
|
/**
|
||||||
* Human readable node type.
|
* Human readable node type.
|
||||||
*/
|
*/
|
||||||
type: typeof TNodeTypeAsString[number];
|
type: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DOM native node.
|
* DOM native node.
|
||||||
|
|
|
@ -6,44 +6,29 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {assertDefined, assertEqual} from '../util/assert';
|
import {assertDefined, throwError} from '../util/assert';
|
||||||
|
import {TNode, TNodeType, toTNodeTypeAsString} from './interfaces/node';
|
||||||
|
|
||||||
import {TContainerNode, TElementContainerNode, TElementNode, TIcuContainerNode, TNode, TNodeType, TNodeTypeAsString, TProjectionNode} from './interfaces/node';
|
export function assertTNodeType(
|
||||||
|
tNode: TNode|null, expectedTypes: TNodeType, message?: string): void {
|
||||||
export function assertNodeType(
|
|
||||||
tNode: TNode, type: TNodeType.Container): asserts tNode is TContainerNode;
|
|
||||||
export function assertNodeType(
|
|
||||||
tNode: TNode, type: TNodeType.Element): asserts tNode is TElementNode;
|
|
||||||
export function assertNodeType(
|
|
||||||
tNode: TNode, type: TNodeType.ElementContainer): asserts tNode is TElementContainerNode;
|
|
||||||
export function assertNodeType(
|
|
||||||
tNode: TNode, type: TNodeType.IcuContainer): asserts tNode is TIcuContainerNode;
|
|
||||||
export function assertNodeType(
|
|
||||||
tNode: TNode, type: TNodeType.Projection): asserts tNode is TProjectionNode;
|
|
||||||
export function assertNodeType(tNode: TNode, type: TNodeType): asserts tNode is TNode {
|
|
||||||
assertDefined(tNode, 'should be called with a TNode');
|
assertDefined(tNode, 'should be called with a TNode');
|
||||||
assertEqual(tNode.type, type, `should be a ${typeName(type)}`);
|
if ((tNode.type & expectedTypes) === 0) {
|
||||||
|
throwError(
|
||||||
|
message ||
|
||||||
|
`Expected [${toTNodeTypeAsString(expectedTypes)}] but got ${
|
||||||
|
toTNodeTypeAsString(tNode.type)}.`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertNodeOfPossibleTypes(
|
export function assertPureTNodeType(type: TNodeType) {
|
||||||
tNode: TNode|null, types: TNodeType[], message?: string): void {
|
if (!(type === TNodeType.Element || //
|
||||||
assertDefined(tNode, 'should be called with a TNode');
|
type === TNodeType.Text || //
|
||||||
const found = types.some(type => tNode.type === type);
|
type === TNodeType.Container || //
|
||||||
assertEqual(
|
type === TNodeType.ElementContainer || //
|
||||||
found, true,
|
type === TNodeType.Icu || //
|
||||||
message ??
|
type === TNodeType.Projection || //
|
||||||
`Should be one of ${types.map(typeName).join(', ')} but got ${typeName(tNode.type)}`);
|
type === TNodeType.Placeholder)) {
|
||||||
|
throwError(`Expected TNodeType to have only a single type selected, but got ${
|
||||||
|
toTNodeTypeAsString(type)}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertNodeNotOfTypes(tNode: TNode, types: TNodeType[], message?: string): void {
|
|
||||||
assertDefined(tNode, 'should be called with a TNode');
|
|
||||||
const found = types.some(type => tNode.type === type);
|
|
||||||
assertEqual(
|
|
||||||
found, false,
|
|
||||||
message ??
|
|
||||||
`Should not be one of ${types.map(typeName).join(', ')} but got ${typeName(tNode.type)}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function typeName(type: TNodeType): string {
|
|
||||||
return TNodeTypeAsString[type] || '<unknown>';
|
|
||||||
}
|
}
|
|
@ -22,10 +22,12 @@ import {unusedValueExportToPlacateAjd as unused3} from './interfaces/projection'
|
||||||
import {isProceduralRenderer, ProceduralRenderer3, RComment, RElement, Renderer3, RNode, RText, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
import {isProceduralRenderer, ProceduralRenderer3, RComment, RElement, Renderer3, RNode, RText, unusedValueExportToPlacateAjd as unused4} from './interfaces/renderer';
|
||||||
import {isLContainer, isLView} from './interfaces/type_checks';
|
import {isLContainer, isLView} from './interfaces/type_checks';
|
||||||
import {CHILD_HEAD, CLEANUP, DECLARATION_COMPONENT_VIEW, DECLARATION_LCONTAINER, DestroyHookData, FLAGS, HookData, HookFn, HOST, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, T_HOST, TVIEW, TView, TViewType, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
import {CHILD_HEAD, CLEANUP, DECLARATION_COMPONENT_VIEW, DECLARATION_LCONTAINER, DestroyHookData, FLAGS, HookData, HookFn, HOST, LView, LViewFlags, NEXT, PARENT, QUERIES, RENDERER, T_HOST, TVIEW, TView, TViewType, unusedValueExportToPlacateAjd as unused5} from './interfaces/view';
|
||||||
import {assertNodeOfPossibleTypes, assertNodeType} from './node_assert';
|
import {assertTNodeType} from './node_assert';
|
||||||
import {getLViewParent} from './util/view_traversal_utils';
|
import {getLViewParent} from './util/view_traversal_utils';
|
||||||
import {getNativeByTNode, unwrapRNode, updateTransplantedViewCount} from './util/view_utils';
|
import {getNativeByTNode, unwrapRNode, updateTransplantedViewCount} from './util/view_utils';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
|
const unusedValueToPlacateAjd = unused1 + unused2 + unused3 + unused4 + unused5;
|
||||||
|
|
||||||
const enum WalkTNodeTreeAction {
|
const enum WalkTNodeTreeAction {
|
||||||
|
@ -539,9 +541,8 @@ export function getClosestRElement(tView: TView, tNode: TNode|null, lView: LView
|
||||||
let parentTNode: TNode|null = tNode;
|
let parentTNode: TNode|null = tNode;
|
||||||
// Skip over element and ICU containers as those are represented by a comment node and
|
// Skip over element and ICU containers as those are represented by a comment node and
|
||||||
// can't be used as a render parent.
|
// can't be used as a render parent.
|
||||||
while (parentTNode != null &&
|
while (parentTNode !== null &&
|
||||||
(parentTNode.type === TNodeType.ElementContainer ||
|
(parentTNode.type & (TNodeType.ElementContainer | TNodeType.Icu))) {
|
||||||
parentTNode.type === TNodeType.IcuContainer)) {
|
|
||||||
tNode = parentTNode;
|
tNode = parentTNode;
|
||||||
parentTNode = tNode.parent;
|
parentTNode = tNode.parent;
|
||||||
}
|
}
|
||||||
|
@ -553,7 +554,7 @@ export function getClosestRElement(tView: TView, tNode: TNode|null, lView: LView
|
||||||
// it should always be eager.
|
// it should always be eager.
|
||||||
return lView[HOST];
|
return lView[HOST];
|
||||||
} else {
|
} else {
|
||||||
// ngDevMode && assertTNodeType(parentTNode, TNodeType.AnyRNode | TNodeType.Container);
|
ngDevMode && assertTNodeType(parentTNode, TNodeType.AnyRNode | TNodeType.Container);
|
||||||
if (parentTNode.flags & TNodeFlags.isComponentHost) {
|
if (parentTNode.flags & TNodeFlags.isComponentHost) {
|
||||||
ngDevMode && assertTNodeForLView(parentTNode, lView);
|
ngDevMode && assertTNodeForLView(parentTNode, lView);
|
||||||
const tData = tView.data;
|
const tData = tView.data;
|
||||||
|
@ -650,8 +651,7 @@ function getInsertInFrontOfRNode(parentTNode: TNode, currentTNode: TNode, lView:
|
||||||
const insertBeforeIndex =
|
const insertBeforeIndex =
|
||||||
Array.isArray(tNodeInsertBeforeIndex) ? tNodeInsertBeforeIndex[0] : tNodeInsertBeforeIndex;
|
Array.isArray(tNodeInsertBeforeIndex) ? tNodeInsertBeforeIndex[0] : tNodeInsertBeforeIndex;
|
||||||
if (insertBeforeIndex === null) {
|
if (insertBeforeIndex === null) {
|
||||||
if (parentTNode.type === TNodeType.ElementContainer ||
|
if (parentTNode.type & (TNodeType.ElementContainer | TNodeType.Icu)) {
|
||||||
parentTNode.type === TNodeType.IcuContainer) {
|
|
||||||
return getNativeByTNode(parentTNode, lView);
|
return getNativeByTNode(parentTNode, lView);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -716,7 +716,7 @@ function processI18nText(
|
||||||
const isProcedural = isProceduralRenderer(renderer);
|
const isProcedural = isProceduralRenderer(renderer);
|
||||||
let i18nParent: RElement|null = childRNode as RElement;
|
let i18nParent: RElement|null = childRNode as RElement;
|
||||||
let anchorRNode: RNode|null = null;
|
let anchorRNode: RNode|null = null;
|
||||||
if (childTNode.type !== TNodeType.Element) {
|
if (!(childTNode.type & TNodeType.AnyRNode)) {
|
||||||
anchorRNode = i18nParent;
|
anchorRNode = i18nParent;
|
||||||
i18nParent = parentRElement;
|
i18nParent = parentRElement;
|
||||||
}
|
}
|
||||||
|
@ -738,17 +738,17 @@ function processI18nText(
|
||||||
*/
|
*/
|
||||||
function getFirstNativeNode(lView: LView, tNode: TNode|null): RNode|null {
|
function getFirstNativeNode(lView: LView, tNode: TNode|null): RNode|null {
|
||||||
if (tNode !== null) {
|
if (tNode !== null) {
|
||||||
ngDevMode && assertNodeOfPossibleTypes(tNode, [
|
ngDevMode &&
|
||||||
TNodeType.Element, TNodeType.Container, TNodeType.ElementContainer, TNodeType.IcuContainer,
|
assertTNodeType(
|
||||||
TNodeType.Projection
|
tNode,
|
||||||
]);
|
TNodeType.AnyRNode | TNodeType.AnyContainer | TNodeType.Icu | TNodeType.Projection);
|
||||||
|
|
||||||
const tNodeType = tNode.type;
|
const tNodeType = tNode.type;
|
||||||
if (tNodeType === TNodeType.Element) {
|
if (tNodeType & TNodeType.AnyRNode) {
|
||||||
return getNativeByTNode(tNode, lView);
|
return getNativeByTNode(tNode, lView);
|
||||||
} else if (tNodeType === TNodeType.Container) {
|
} else if (tNodeType & TNodeType.Container) {
|
||||||
return getBeforeNodeForView(-1, lView[tNode.index]);
|
return getBeforeNodeForView(-1, lView[tNode.index]);
|
||||||
} else if (tNodeType === TNodeType.ElementContainer) {
|
} else if (tNodeType & TNodeType.ElementContainer) {
|
||||||
const elIcuContainerChild = tNode.child;
|
const elIcuContainerChild = tNode.child;
|
||||||
if (elIcuContainerChild !== null) {
|
if (elIcuContainerChild !== null) {
|
||||||
return getFirstNativeNode(lView, elIcuContainerChild);
|
return getFirstNativeNode(lView, elIcuContainerChild);
|
||||||
|
@ -760,7 +760,7 @@ function getFirstNativeNode(lView: LView, tNode: TNode|null): RNode|null {
|
||||||
return unwrapRNode(rNodeOrLContainer);
|
return unwrapRNode(rNodeOrLContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (tNodeType === TNodeType.IcuContainer) {
|
} else if (tNodeType & TNodeType.Icu) {
|
||||||
let nextRNode = icuContainerIterate(tNode as TIcuContainerNode, lView);
|
let nextRNode = icuContainerIterate(tNode as TIcuContainerNode, lView);
|
||||||
let rNode: RNode|null = nextRNode();
|
let rNode: RNode|null = nextRNode();
|
||||||
// If the ICU container has no nodes, than we use the ICU anchor as the node.
|
// If the ICU container has no nodes, than we use the ICU anchor as the node.
|
||||||
|
@ -824,10 +824,10 @@ function applyNodes(
|
||||||
parentRElement: RElement|null, beforeNode: RNode|null, isProjection: boolean) {
|
parentRElement: RElement|null, beforeNode: RNode|null, isProjection: boolean) {
|
||||||
while (tNode != null) {
|
while (tNode != null) {
|
||||||
ngDevMode && assertTNodeForLView(tNode, lView);
|
ngDevMode && assertTNodeForLView(tNode, lView);
|
||||||
ngDevMode && assertNodeOfPossibleTypes(tNode, [
|
ngDevMode &&
|
||||||
TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer, TNodeType.Projection,
|
assertTNodeType(
|
||||||
TNodeType.IcuContainer
|
tNode,
|
||||||
]);
|
TNodeType.AnyRNode | TNodeType.AnyContainer | TNodeType.Projection | TNodeType.Icu);
|
||||||
const rawSlotValue = lView[tNode.index];
|
const rawSlotValue = lView[tNode.index];
|
||||||
const tNodeType = tNode.type;
|
const tNodeType = tNode.type;
|
||||||
if (isProjection) {
|
if (isProjection) {
|
||||||
|
@ -837,21 +837,21 @@ function applyNodes(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((tNode.flags & TNodeFlags.isDetached) !== TNodeFlags.isDetached) {
|
if ((tNode.flags & TNodeFlags.isDetached) !== TNodeFlags.isDetached) {
|
||||||
if (tNodeType === TNodeType.ElementContainer) {
|
if (tNodeType & TNodeType.ElementContainer) {
|
||||||
applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);
|
applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);
|
||||||
applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
|
applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
|
||||||
} else if (tNodeType === TNodeType.IcuContainer) {
|
} else if (tNodeType & TNodeType.Icu) {
|
||||||
const nextRNode = icuContainerIterate(tNode as TIcuContainerNode, lView);
|
const nextRNode = icuContainerIterate(tNode as TIcuContainerNode, lView);
|
||||||
let rNode: RNode|null;
|
let rNode: RNode|null;
|
||||||
while (rNode = nextRNode()) {
|
while (rNode = nextRNode()) {
|
||||||
applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
|
applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
|
||||||
}
|
}
|
||||||
applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
|
applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
|
||||||
} else if (tNodeType === TNodeType.Projection) {
|
} else if (tNodeType & TNodeType.Projection) {
|
||||||
applyProjectionRecursive(
|
applyProjectionRecursive(
|
||||||
renderer, action, lView, tNode as TProjectionNode, parentRElement, beforeNode);
|
renderer, action, lView, tNode as TProjectionNode, parentRElement, beforeNode);
|
||||||
} else {
|
} else {
|
||||||
ngDevMode && assertNodeOfPossibleTypes(tNode, [TNodeType.Element, TNodeType.Container]);
|
ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode | TNodeType.Container);
|
||||||
applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
|
applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {unusedValueExportToPlacateAjd as unused2} from './interfaces/injector';
|
||||||
import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeType, unusedValueExportToPlacateAjd as unused3} from './interfaces/node';
|
import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeType, unusedValueExportToPlacateAjd as unused3} from './interfaces/node';
|
||||||
import {LQueries, LQuery, TQueries, TQuery, TQueryMetadata, unusedValueExportToPlacateAjd as unused4} from './interfaces/query';
|
import {LQueries, LQuery, TQueries, TQuery, TQueryMetadata, unusedValueExportToPlacateAjd as unused4} from './interfaces/query';
|
||||||
import {DECLARATION_LCONTAINER, LView, PARENT, QUERIES, TVIEW, TView} from './interfaces/view';
|
import {DECLARATION_LCONTAINER, LView, PARENT, QUERIES, TVIEW, TView} from './interfaces/view';
|
||||||
import {assertNodeOfPossibleTypes} from './node_assert';
|
import {assertTNodeType} from './node_assert';
|
||||||
import {getCurrentQueryIndex, getCurrentTNode, getLView, getTView, setCurrentQueryIndex} from './state';
|
import {getCurrentQueryIndex, getCurrentTNode, getLView, getTView, setCurrentQueryIndex} from './state';
|
||||||
import {isCreationMode} from './util/view_utils';
|
import {isCreationMode} from './util/view_utils';
|
||||||
import {createContainerRef, createElementRef, createTemplateRef} from './view_engine_compatibility';
|
import {createContainerRef, createElementRef, createTemplateRef} from './view_engine_compatibility';
|
||||||
|
@ -217,7 +217,7 @@ class TQuery_ implements TQuery {
|
||||||
// - <needs-target><ng-container><i #target></i></ng-container></needs-target>: here we need
|
// - <needs-target><ng-container><i #target></i></ng-container></needs-target>: here we need
|
||||||
// to go past `<ng-container>` to determine <i #target> parent node (but we shouldn't traverse
|
// to go past `<ng-container>` to determine <i #target> parent node (but we shouldn't traverse
|
||||||
// up past the query's host node!).
|
// up past the query's host node!).
|
||||||
while (parent !== null && parent.type === TNodeType.ElementContainer &&
|
while (parent !== null && (parent.type & TNodeType.ElementContainer) &&
|
||||||
parent.index !== declarationNodeIdx) {
|
parent.index !== declarationNodeIdx) {
|
||||||
parent = parent.parent;
|
parent = parent.parent;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ class TQuery_ implements TQuery {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((predicate as any) === ViewEngine_TemplateRef) {
|
if ((predicate as any) === ViewEngine_TemplateRef) {
|
||||||
if (tNode.type === TNodeType.Container) {
|
if (tNode.type & TNodeType.Container) {
|
||||||
this.matchTNodeWithReadOption(tView, tNode, -1);
|
this.matchTNodeWithReadOption(tView, tNode, -1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -253,7 +253,7 @@ class TQuery_ implements TQuery {
|
||||||
const read = this.metadata.read;
|
const read = this.metadata.read;
|
||||||
if (read !== null) {
|
if (read !== null) {
|
||||||
if (read === ViewEngine_ElementRef || read === ViewContainerRef ||
|
if (read === ViewEngine_ElementRef || read === ViewContainerRef ||
|
||||||
read === ViewEngine_TemplateRef && tNode.type === TNodeType.Container) {
|
read === ViewEngine_TemplateRef && (tNode.type & TNodeType.Container)) {
|
||||||
this.addMatch(tNode.index, -2);
|
this.addMatch(tNode.index, -2);
|
||||||
} else {
|
} else {
|
||||||
const directiveOrProviderIdx =
|
const directiveOrProviderIdx =
|
||||||
|
@ -299,9 +299,9 @@ function getIdxOfMatchingSelector(tNode: TNode, selector: string): number|null {
|
||||||
|
|
||||||
|
|
||||||
function createResultByTNodeType(tNode: TNode, currentView: LView): any {
|
function createResultByTNodeType(tNode: TNode, currentView: LView): any {
|
||||||
if (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) {
|
if (tNode.type & (TNodeType.AnyRNode | TNodeType.ElementContainer)) {
|
||||||
return createElementRef(ViewEngine_ElementRef, tNode, currentView);
|
return createElementRef(ViewEngine_ElementRef, tNode, currentView);
|
||||||
} else if (tNode.type === TNodeType.Container) {
|
} else if (tNode.type & TNodeType.Container) {
|
||||||
return createTemplateRef(ViewEngine_TemplateRef, ViewEngine_ElementRef, tNode, currentView);
|
return createTemplateRef(ViewEngine_TemplateRef, ViewEngine_ElementRef, tNode, currentView);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -327,9 +327,7 @@ function createSpecialToken(lView: LView, tNode: TNode, read: any): any {
|
||||||
} else if (read === ViewEngine_TemplateRef) {
|
} else if (read === ViewEngine_TemplateRef) {
|
||||||
return createTemplateRef(ViewEngine_TemplateRef, ViewEngine_ElementRef, tNode, lView);
|
return createTemplateRef(ViewEngine_TemplateRef, ViewEngine_ElementRef, tNode, lView);
|
||||||
} else if (read === ViewContainerRef) {
|
} else if (read === ViewContainerRef) {
|
||||||
ngDevMode &&
|
ngDevMode && assertTNodeType(tNode, TNodeType.AnyRNode | TNodeType.AnyContainer);
|
||||||
assertNodeOfPossibleTypes(
|
|
||||||
tNode, [TNodeType.Element, TNodeType.Container, TNodeType.ElementContainer]);
|
|
||||||
return createContainerRef(
|
return createContainerRef(
|
||||||
ViewContainerRef, ViewEngine_ElementRef,
|
ViewContainerRef, ViewEngine_ElementRef,
|
||||||
tNode as TElementNode | TContainerNode | TElementContainerNode, lView);
|
tNode as TElementNode | TContainerNode | TElementContainerNode, lView);
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {DirectiveDef} from './interfaces/definition';
|
||||||
import {TNode, TNodeType} from './interfaces/node';
|
import {TNode, TNodeType} from './interfaces/node';
|
||||||
import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState, TData, TVIEW, TView} from './interfaces/view';
|
import {CONTEXT, DECLARATION_VIEW, LView, OpaqueViewState, TData, TVIEW, TView} from './interfaces/view';
|
||||||
import {MATH_ML_NAMESPACE, SVG_NAMESPACE} from './namespaces';
|
import {MATH_ML_NAMESPACE, SVG_NAMESPACE} from './namespaces';
|
||||||
|
import {assertTNodeType} from './node_assert';
|
||||||
import {getTNode} from './util/view_utils';
|
import {getTNode} from './util/view_utils';
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {TContainerNode, TDirectiveHostNode, TElementContainerNode, TElementNode,
|
||||||
import {isProceduralRenderer, RComment, RElement} from './interfaces/renderer';
|
import {isProceduralRenderer, RComment, RElement} from './interfaces/renderer';
|
||||||
import {isComponentHost, isLContainer, isLView, isRootView} from './interfaces/type_checks';
|
import {isComponentHost, isLContainer, isLView, isRootView} from './interfaces/type_checks';
|
||||||
import {DECLARATION_COMPONENT_VIEW, DECLARATION_LCONTAINER, LView, LViewFlags, PARENT, QUERIES, RENDERER, T_HOST, TVIEW, TView} from './interfaces/view';
|
import {DECLARATION_COMPONENT_VIEW, DECLARATION_LCONTAINER, LView, LViewFlags, PARENT, QUERIES, RENDERER, T_HOST, TVIEW, TView} from './interfaces/view';
|
||||||
import {assertNodeOfPossibleTypes} from './node_assert';
|
import {assertTNodeType} from './node_assert';
|
||||||
import {addViewToContainer, appendChild, destroyLView, detachView, getBeforeNodeForView, insertView, nativeInsertBefore, nativeNextSibling, nativeParentNode} from './node_manipulation';
|
import {addViewToContainer, appendChild, destroyLView, detachView, getBeforeNodeForView, insertView, nativeInsertBefore, nativeNextSibling, nativeParentNode} from './node_manipulation';
|
||||||
import {getCurrentTNode, getLView} from './state';
|
import {getCurrentTNode, getLView} from './state';
|
||||||
import {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_utils';
|
import {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_utils';
|
||||||
|
@ -123,7 +123,7 @@ export function createTemplateRef<T>(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hostTNode.type === TNodeType.Container) {
|
if (hostTNode.type & TNodeType.Container) {
|
||||||
ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated');
|
ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated');
|
||||||
return new R3TemplateRef(
|
return new R3TemplateRef(
|
||||||
hostView, hostTNode as TContainerNode,
|
hostView, hostTNode as TContainerNode,
|
||||||
|
@ -357,9 +357,7 @@ export function createContainerRef(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDevMode &&
|
ngDevMode && assertTNodeType(hostTNode, TNodeType.AnyContainer | TNodeType.AnyRNode);
|
||||||
assertNodeOfPossibleTypes(
|
|
||||||
hostTNode, [TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer]);
|
|
||||||
|
|
||||||
let lContainer: LContainer;
|
let lContainer: LContainer;
|
||||||
const slotValue = hostView[hostTNode.index];
|
const slotValue = hostView[hostTNode.index];
|
||||||
|
@ -372,7 +370,7 @@ export function createContainerRef(
|
||||||
// comment and we can reuse that comment as anchor element for the new LContainer.
|
// comment and we can reuse that comment as anchor element for the new LContainer.
|
||||||
// The comment node in question is already part of the DOM structure so we don't need to append
|
// The comment node in question is already part of the DOM structure so we don't need to append
|
||||||
// it again.
|
// it again.
|
||||||
if (hostTNode.type === TNodeType.ElementContainer) {
|
if (hostTNode.type & TNodeType.ElementContainer) {
|
||||||
commentNode = unwrapRNode(slotValue) as RComment;
|
commentNode = unwrapRNode(slotValue) as RComment;
|
||||||
} else {
|
} else {
|
||||||
ngDevMode && ngDevMode.rendererCreateComment++;
|
ngDevMode && ngDevMode.rendererCreateComment++;
|
||||||
|
@ -431,9 +429,7 @@ function createViewRef(tNode: TNode, lView: LView, isPipe: boolean): ViewEngine_
|
||||||
// Instead we want the LView for the component View and so we need to look it up.
|
// Instead we want the LView for the component View and so we need to look it up.
|
||||||
const componentView = getComponentLViewByIndex(tNode.index, lView); // look down
|
const componentView = getComponentLViewByIndex(tNode.index, lView); // look down
|
||||||
return new ViewRef(componentView, componentView);
|
return new ViewRef(componentView, componentView);
|
||||||
} else if (
|
} else if (tNode.type & (TNodeType.AnyRNode | TNodeType.AnyContainer | TNodeType.Icu)) {
|
||||||
tNode.type === TNodeType.Element || tNode.type === TNodeType.Container ||
|
|
||||||
tNode.type === TNodeType.ElementContainer || tNode.type === TNodeType.IcuContainer) {
|
|
||||||
// The LView represents the location where the injection is requested from.
|
// The LView represents the location where the injection is requested from.
|
||||||
// We need to locate the containing LView (in case where the `lView` is an embedded view)
|
// We need to locate the containing LView (in case where the `lView` is an embedded view)
|
||||||
const hostComponentView = lView[DECLARATION_COMPONENT_VIEW]; // look up
|
const hostComponentView = lView[DECLARATION_COMPONENT_VIEW]; // look up
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {TElementNode, TIcuContainerNode, TNode, TNodeType} from './interfaces/no
|
||||||
import {RNode} from './interfaces/renderer';
|
import {RNode} from './interfaces/renderer';
|
||||||
import {isLContainer} from './interfaces/type_checks';
|
import {isLContainer} from './interfaces/type_checks';
|
||||||
import {CONTEXT, DECLARATION_COMPONENT_VIEW, FLAGS, LView, LViewFlags, T_HOST, TVIEW, TView} from './interfaces/view';
|
import {CONTEXT, DECLARATION_COMPONENT_VIEW, FLAGS, LView, LViewFlags, T_HOST, TVIEW, TView} from './interfaces/view';
|
||||||
import {assertNodeOfPossibleTypes} from './node_assert';
|
import {assertTNodeType} from './node_assert';
|
||||||
import {destroyLView, renderDetachView} from './node_manipulation';
|
import {destroyLView, renderDetachView} from './node_manipulation';
|
||||||
import {getLViewParent} from './util/view_traversal_utils';
|
import {getLViewParent} from './util/view_traversal_utils';
|
||||||
import {unwrapRNode} from './util/view_utils';
|
import {unwrapRNode} from './util/view_utils';
|
||||||
|
@ -324,10 +324,10 @@ function collectNativeNodes(
|
||||||
tView: TView, lView: LView, tNode: TNode|null, result: any[],
|
tView: TView, lView: LView, tNode: TNode|null, result: any[],
|
||||||
isProjection: boolean = false): any[] {
|
isProjection: boolean = false): any[] {
|
||||||
while (tNode !== null) {
|
while (tNode !== null) {
|
||||||
ngDevMode && assertNodeOfPossibleTypes(tNode, [
|
ngDevMode &&
|
||||||
TNodeType.Element, TNodeType.Container, TNodeType.Projection, TNodeType.ElementContainer,
|
assertTNodeType(
|
||||||
TNodeType.IcuContainer
|
tNode,
|
||||||
]);
|
TNodeType.AnyRNode | TNodeType.AnyContainer | TNodeType.Projection | TNodeType.Icu);
|
||||||
|
|
||||||
const lNode = lView[tNode.index];
|
const lNode = lView[tNode.index];
|
||||||
if (lNode !== null) {
|
if (lNode !== null) {
|
||||||
|
@ -349,15 +349,15 @@ function collectNativeNodes(
|
||||||
}
|
}
|
||||||
|
|
||||||
const tNodeType = tNode.type;
|
const tNodeType = tNode.type;
|
||||||
if (tNodeType === TNodeType.ElementContainer) {
|
if (tNodeType & TNodeType.ElementContainer) {
|
||||||
collectNativeNodes(tView, lView, tNode.child, result);
|
collectNativeNodes(tView, lView, tNode.child, result);
|
||||||
} else if (tNodeType === TNodeType.IcuContainer) {
|
} else if (tNodeType & TNodeType.Icu) {
|
||||||
const nextRNode = icuContainerIterate(tNode as TIcuContainerNode, lView);
|
const nextRNode = icuContainerIterate(tNode as TIcuContainerNode, lView);
|
||||||
let rNode: RNode|null;
|
let rNode: RNode|null;
|
||||||
while (rNode = nextRNode()) {
|
while (rNode = nextRNode()) {
|
||||||
result.push(rNode);
|
result.push(rNode);
|
||||||
}
|
}
|
||||||
} else if (tNodeType === TNodeType.Projection) {
|
} else if (tNodeType & TNodeType.Projection) {
|
||||||
const componentView = lView[DECLARATION_COMPONENT_VIEW];
|
const componentView = lView[DECLARATION_COMPONENT_VIEW];
|
||||||
const componentHost = componentView[T_HOST] as TElementNode;
|
const componentHost = componentView[T_HOST] as TElementNode;
|
||||||
const slotIdx = tNode.projection as number;
|
const slotIdx = tNode.projection as number;
|
||||||
|
|
|
@ -70,7 +70,7 @@ onlyInIvy('Ivy specific').describe('Debug Representation', () => {
|
||||||
length: 1,
|
length: 1,
|
||||||
content: [{
|
content: [{
|
||||||
index: HEADER_OFFSET + 3,
|
index: HEADER_OFFSET + 3,
|
||||||
t: matchTNode({type: TNodeType.Element, value: null}),
|
t: matchTNode({type: TNodeType.Text, value: '{{?}}'}),
|
||||||
l: matchDomText('Hello World')
|
l: matchDomText('Hello World')
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
|
|
@ -618,7 +618,7 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => {
|
||||||
const exclamation = b.nextSibling!;
|
const exclamation = b.nextSibling!;
|
||||||
const lViewDebug = lView.debug!;
|
const lViewDebug = lView.debug!;
|
||||||
expect(lViewDebug.nodes.map(toTypeContent)).toEqual([
|
expect(lViewDebug.nodes.map(toTypeContent)).toEqual([
|
||||||
'Element(Hello )', 'Element(<b>)', 'Element(!)'
|
'Text(Hello )', 'Element(<b>)', 'Text(!)'
|
||||||
]);
|
]);
|
||||||
expect(lViewDebug.decls).toEqual({
|
expect(lViewDebug.decls).toEqual({
|
||||||
start: HEADER_OFFSET,
|
start: HEADER_OFFSET,
|
||||||
|
|
|
@ -668,7 +668,7 @@ describe('Runtime i18n', () => {
|
||||||
i18nRangeOffsetOpcode(0), 'Hello World!', //
|
i18nRangeOffsetOpcode(0), 'Hello World!', //
|
||||||
]);
|
]);
|
||||||
const lViewDebug = fixture.lView.debug!;
|
const lViewDebug = fixture.lView.debug!;
|
||||||
expect(lViewDebug.template).toEqual('<div>#text</div>');
|
expect(lViewDebug.template).toEqual('<div>Hello World!</div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process text with a child node', () => {
|
it('should process text with a child node', () => {
|
||||||
|
@ -685,7 +685,7 @@ describe('Runtime i18n', () => {
|
||||||
insertBeforeIndex: i18nRangeOffset(1),
|
insertBeforeIndex: i18nRangeOffset(1),
|
||||||
}));
|
}));
|
||||||
const lViewDebug = fixture.lView.debug!;
|
const lViewDebug = fixture.lView.debug!;
|
||||||
expect(lViewDebug.template).toEqual('<div>#text<Placeholder></Placeholder>#text</div>');
|
expect(lViewDebug.template).toEqual('<div>Hello <Placeholder></Placeholder>!</div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process text with a child node that has text', () => {
|
it('should process text with a child node that has text', () => {
|
||||||
|
@ -729,7 +729,7 @@ describe('Runtime i18n', () => {
|
||||||
'if (mask & 0b10) { (lView[51] as Text).textContent = `${lView[i-2]}`; }'
|
'if (mask & 0b10) { (lView[51] as Text).textContent = `${lView[i-2]}`; }'
|
||||||
]));
|
]));
|
||||||
const lViewDebug = fixture.lView.debug!;
|
const lViewDebug = fixture.lView.debug!;
|
||||||
expect(lViewDebug.template).toEqual('<div>#text<Placeholder>#text</Placeholder>#text</div>');
|
expect(lViewDebug.template).toEqual('<div>{{?}}<Placeholder>{{?}}</Placeholder>!</div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process text with a child template', () => {
|
it('should process text with a child template', () => {
|
||||||
|
|
|
@ -6,16 +6,23 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {TNodeType, TNodeTypeAsString} from '@angular/core/src/render3/interfaces/node';
|
import {TNodeType, toTNodeTypeAsString} from '@angular/core/src/render3/interfaces/node';
|
||||||
|
|
||||||
describe('node interfaces', () => {
|
describe('node interfaces', () => {
|
||||||
describe('TNodeType', () => {
|
describe('TNodeType', () => {
|
||||||
it('should agree with TNodeTypeAsString', () => {
|
it('should agree with toTNodeTypeAsString', () => {
|
||||||
expect(TNodeTypeAsString[TNodeType.Container]).toEqual('Container');
|
expect(toTNodeTypeAsString(TNodeType.Element)).toEqual('Element');
|
||||||
expect(TNodeTypeAsString[TNodeType.Projection]).toEqual('Projection');
|
expect(toTNodeTypeAsString(TNodeType.Text)).toEqual('Text');
|
||||||
expect(TNodeTypeAsString[TNodeType.Element]).toEqual('Element');
|
expect(toTNodeTypeAsString(TNodeType.Container)).toEqual('Container');
|
||||||
expect(TNodeTypeAsString[TNodeType.ElementContainer]).toEqual('ElementContainer');
|
expect(toTNodeTypeAsString(TNodeType.Projection)).toEqual('Projection');
|
||||||
expect(TNodeTypeAsString[TNodeType.IcuContainer]).toEqual('IcuContainer');
|
expect(toTNodeTypeAsString(TNodeType.ElementContainer)).toEqual('ElementContainer');
|
||||||
|
expect(toTNodeTypeAsString(TNodeType.Icu)).toEqual('IcuContainer');
|
||||||
|
expect(toTNodeTypeAsString(TNodeType.Placeholder)).toEqual('Placeholder');
|
||||||
|
|
||||||
|
expect(toTNodeTypeAsString(
|
||||||
|
TNodeType.Container | TNodeType.Projection | TNodeType.Element |
|
||||||
|
TNodeType.ElementContainer | TNodeType.Icu))
|
||||||
|
.toEqual('Element|Container|ElementContainer|Projection|IcuContainer');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
Loading…
Reference in New Issue