refactor(core): change `getPreviousOrParentTNode` to return `TNode|null` (#38707)

This change makes `getPreviousOrParentTNode` return `TNode|null` (rather
than just `TNode`) which is more reflective of the reality. The
`getPreviousOrParentTNode` can be `null` upon entering the `LView`.

PR Close #38707
This commit is contained in:
Misko Hevery 2020-09-14 13:25:13 -07:00 committed by Alex Rickabaugh
parent 5a86fb33ba
commit 7bd18fca19
11 changed files with 32 additions and 33 deletions

View File

@ -229,7 +229,7 @@ export function createRootComponent<T>(
componentDef.contentQueries(RenderFlags.Create, component, rootLView.length - 1); componentDef.contentQueries(RenderFlags.Create, component, rootLView.length - 1);
} }
const rootTNode = getPreviousOrParentTNode(); const rootTNode = getPreviousOrParentTNode()!;
if (tView.firstCreatePass && if (tView.firstCreatePass &&
(componentDef.hostBindings !== null || componentDef.hostAttrs !== null)) { (componentDef.hostBindings !== null || componentDef.hostAttrs !== null)) {
const elementIndex = rootTNode.index - HEADER_OFFSET; const elementIndex = rootTNode.index - HEADER_OFFSET;

View File

@ -76,7 +76,7 @@ function resolveProvider(
let token: any = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide); let token: any = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide);
let providerFactory: () => any = providerToFactory(provider); let providerFactory: () => any = providerToFactory(provider);
const tNode = getPreviousOrParentTNode(); const tNode = getPreviousOrParentTNode()!;
const beginIndex = tNode.providerIndexes & TNodeProviderIndexes.ProvidersStartIndexMask; const beginIndex = tNode.providerIndexes & TNodeProviderIndexes.ProvidersStartIndexMask;
const endIndex = tNode.directiveStart; const endIndex = tNode.directiveStart;
const cptViewProvidersCount = const cptViewProvidersCount =

View File

@ -70,7 +70,7 @@ export function i18nStartFirstPass(
lView: LView, tView: TView, index: number, message: string, subTemplateIndex?: number) { lView: LView, tView: TView, index: number, message: string, subTemplateIndex?: number) {
const startIndex = tView.blueprint.length - HEADER_OFFSET; const startIndex = tView.blueprint.length - HEADER_OFFSET;
i18nVarsCount = 0; i18nVarsCount = 0;
const previousOrParentTNode = getPreviousOrParentTNode(); const previousOrParentTNode = getPreviousOrParentTNode()!;
const parentTNode = const parentTNode =
getIsParent() ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent; getIsParent() ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent;
let parentIndex = let parentIndex =
@ -212,7 +212,7 @@ export function i18nStartFirstPass(
*/ */
export function i18nAttributesFirstPass( export function i18nAttributesFirstPass(
lView: LView, tView: TView, index: number, values: string[]) { lView: LView, tView: TView, index: number, values: string[]) {
const previousElement = getPreviousOrParentTNode(); const previousElement = getPreviousOrParentTNode()!;
const previousElementIndex = previousElement.index - HEADER_OFFSET; const previousElementIndex = previousElement.index - HEADER_OFFSET;
const updateOpCodes: I18nUpdateOpCodes = []; const updateOpCodes: I18nUpdateOpCodes = [];
if (ngDevMode) { if (ngDevMode) {

View File

@ -59,7 +59,7 @@ export function ɵɵdirectiveInject<T>(
* @codeGenApi * @codeGenApi
*/ */
export function ɵɵinjectAttribute(attrNameToInject: string): string|null { export function ɵɵinjectAttribute(attrNameToInject: string): string|null {
return injectAttributeImpl(getPreviousOrParentTNode(), attrNameToInject); return injectAttributeImpl(getPreviousOrParentTNode()!, attrNameToInject);
} }
/** /**

View File

@ -128,7 +128,7 @@ export function ɵɵelementStart(
* @codeGenApi * @codeGenApi
*/ */
export function ɵɵelementEnd(): void { export function ɵɵelementEnd(): void {
let previousOrParentTNode = getPreviousOrParentTNode(); let previousOrParentTNode = getPreviousOrParentTNode()!;
ngDevMode && assertDefined(previousOrParentTNode, 'No parent node to close.'); ngDevMode && assertDefined(previousOrParentTNode, 'No parent node to close.');
if (getIsParent()) { if (getIsParent()) {
setIsNotParent(); setIsNotParent();

View File

@ -98,7 +98,7 @@ export function ɵɵelementContainerStart(
* @codeGenApi * @codeGenApi
*/ */
export function ɵɵelementContainerEnd(): void { export function ɵɵelementContainerEnd(): void {
let previousOrParentTNode = getPreviousOrParentTNode(); let previousOrParentTNode = getPreviousOrParentTNode()!;
const tView = getTView(); const tView = getTView();
if (getIsParent()) { if (getIsParent()) {
setIsNotParent(); setIsNotParent();

View File

@ -41,7 +41,7 @@ export function ɵɵlistener(
eventTargetResolver?: GlobalTargetResolver): typeof ɵɵlistener { eventTargetResolver?: GlobalTargetResolver): typeof ɵɵlistener {
const lView = getLView(); const lView = getLView();
const tView = getTView(); const tView = getTView();
const tNode = getPreviousOrParentTNode(); const tNode = getPreviousOrParentTNode()!;
listenerInternal( listenerInternal(
tView, lView, lView[RENDERER], tNode, eventName, listenerFn, useCapture, eventTargetResolver); tView, lView, lView[RENDERER], tNode, eventName, listenerFn, useCapture, eventTargetResolver);
return ɵɵlistener; return ɵɵlistener;
@ -71,7 +71,7 @@ export function ɵɵlistener(
export function ɵɵsyntheticHostListener( export function ɵɵsyntheticHostListener(
eventName: string, listenerFn: (e?: any) => any, useCapture = false, eventName: string, listenerFn: (e?: any) => any, useCapture = false,
eventTargetResolver?: GlobalTargetResolver): typeof ɵɵsyntheticHostListener { eventTargetResolver?: GlobalTargetResolver): typeof ɵɵsyntheticHostListener {
const tNode = getPreviousOrParentTNode(); const tNode = getPreviousOrParentTNode()!;
const lView = getLView(); const lView = getLView();
const tView = getTView(); const tView = getTView();
const currentDef = getCurrentDirectiveDef(tView.data); const currentDef = getCurrentDirectiveDef(tView.data);

View File

@ -1125,7 +1125,7 @@ function logUnknownPropertyError(propName: string, tNode: TNode): void {
* Instantiate a root component. * Instantiate a root component.
*/ */
export function instantiateRootComponent<T>(tView: TView, lView: LView, def: ComponentDef<T>): T { export function instantiateRootComponent<T>(tView: TView, lView: LView, def: ComponentDef<T>): T {
const rootTNode = getPreviousOrParentTNode(); const rootTNode = getPreviousOrParentTNode()!;
if (tView.firstCreatePass) { if (tView.firstCreatePass) {
if (def.providersResolver) def.providersResolver(def); if (def.providersResolver) def.providersResolver(def);
generateExpandoInstructionBlock(tView, rootTNode, 1); generateExpandoInstructionBlock(tView, rootTNode, 1);

View File

@ -504,7 +504,7 @@ export function ɵɵcontentQuery<T>(
directiveIndex: number, predicate: Type<any>|InjectionToken<unknown>|string[], descend: boolean, directiveIndex: number, predicate: Type<any>|InjectionToken<unknown>|string[], descend: boolean,
read?: any): void { read?: any): void {
contentQueryInternal( contentQueryInternal(
getTView(), getLView(), predicate, descend, read, false, getPreviousOrParentTNode(), getTView(), getLView(), predicate, descend, read, false, getPreviousOrParentTNode()!,
directiveIndex); directiveIndex);
} }
@ -524,7 +524,7 @@ export function ɵɵstaticContentQuery<T>(
directiveIndex: number, predicate: Type<any>|InjectionToken<unknown>|string[], descend: boolean, directiveIndex: number, predicate: Type<any>|InjectionToken<unknown>|string[], descend: boolean,
read?: any): void { read?: any): void {
contentQueryInternal( contentQueryInternal(
getTView(), getLView(), predicate, descend, read, true, getPreviousOrParentTNode(), getTView(), getLView(), predicate, descend, read, true, getPreviousOrParentTNode()!,
directiveIndex); directiveIndex);
} }

View File

@ -54,8 +54,7 @@ interface LFrame {
* *
* This is used in conjunction with `isParent`. * This is used in conjunction with `isParent`.
*/ */
// FIXME(misko): should be `TNode|null` (add comment explaining it.) previousOrParentTNode: TNode|null;
previousOrParentTNode: TNode;
/** /**
* If `isParent` is: * If `isParent` is:
@ -263,7 +262,7 @@ export function ɵɵrestoreView(viewToRestore: OpaqueViewState) {
instructionState.lFrame.contextLView = viewToRestore as any as LView; instructionState.lFrame.contextLView = viewToRestore as any as LView;
} }
export function getPreviousOrParentTNode(): TNode { export function getPreviousOrParentTNode(): TNode|null {
return instructionState.lFrame.previousOrParentTNode; return instructionState.lFrame.previousOrParentTNode;
} }
@ -441,20 +440,20 @@ function allocLFrame() {
function createLFrame(parent: LFrame|null): LFrame { function createLFrame(parent: LFrame|null): LFrame {
const lFrame: LFrame = { const lFrame: LFrame = {
previousOrParentTNode: null!, // previousOrParentTNode: null, //
isParent: true, // isParent: true, //
lView: null!, // lView: null!, //
tView: null!, // tView: null!, //
selectedIndex: 0, // selectedIndex: 0, //
contextLView: null!, // contextLView: null!, //
elementDepthCount: 0, // elementDepthCount: 0, //
currentNamespace: null, // currentNamespace: null, //
currentDirectiveIndex: -1, // currentDirectiveIndex: -1, //
bindingRootIndex: -1, // bindingRootIndex: -1, //
bindingIndex: -1, // bindingIndex: -1, //
currentQueryIndex: 0, // currentQueryIndex: 0, //
parent: parent!, // parent: parent!, //
child: null, // child: null, //
}; };
parent !== null && (parent.child = lFrame); // link the new LFrame for reuse. parent !== null && (parent.child = lFrame); // link the new LFrame for reuse.
return lFrame; return lFrame;

View File

@ -43,7 +43,7 @@ import { ViewRef } from './view_ref';
*/ */
export function injectElementRef(ElementRefToken: typeof ViewEngine_ElementRef): export function injectElementRef(ElementRefToken: typeof ViewEngine_ElementRef):
ViewEngine_ElementRef { ViewEngine_ElementRef {
return createElementRef(ElementRefToken, getPreviousOrParentTNode(), getLView()); return createElementRef(ElementRefToken, getPreviousOrParentTNode()!, getLView());
} }
let R3ElementRef: {new (native: RElement|RComment): ViewEngine_ElementRef}; let R3ElementRef: {new (native: RElement|RComment): ViewEngine_ElementRef};
@ -79,7 +79,7 @@ export function injectTemplateRef<T>(
TemplateRefToken: typeof ViewEngine_TemplateRef, TemplateRefToken: typeof ViewEngine_TemplateRef,
ElementRefToken: typeof ViewEngine_ElementRef): ViewEngine_TemplateRef<T>|null { ElementRefToken: typeof ViewEngine_ElementRef): ViewEngine_TemplateRef<T>|null {
return createTemplateRef<T>( return createTemplateRef<T>(
TemplateRefToken, ElementRefToken, getPreviousOrParentTNode(), getLView()); TemplateRefToken, ElementRefToken, getPreviousOrParentTNode()!, getLView());
} }
/** /**
@ -407,7 +407,7 @@ export function createContainerRef(
/** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */ /** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */
export function injectChangeDetectorRef(isPipe = false): ViewEngine_ChangeDetectorRef { export function injectChangeDetectorRef(isPipe = false): ViewEngine_ChangeDetectorRef {
return createViewRef(getPreviousOrParentTNode(), getLView(), isPipe); return createViewRef(getPreviousOrParentTNode()!, getLView(), isPipe);
} }
/** /**
@ -453,7 +453,7 @@ export function injectRenderer2(): Renderer2 {
// We need the Renderer to be based on the component that it's being injected into, however since // We need the Renderer to be based on the component that it's being injected into, however since
// DI happens before we've entered its view, `getLView` will return the parent view instead. // DI happens before we've entered its view, `getLView` will return the parent view instead.
const lView = getLView(); const lView = getLView();
const tNode = getPreviousOrParentTNode(); const tNode = getPreviousOrParentTNode()!;
const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView); const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView);
return getOrCreateRenderer2(isLView(nodeAtIndex) ? nodeAtIndex : lView); return getOrCreateRenderer2(isLView(nodeAtIndex) ? nodeAtIndex : lView);
} }