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);
}
const rootTNode = getPreviousOrParentTNode();
const rootTNode = getPreviousOrParentTNode()!;
if (tView.firstCreatePass &&
(componentDef.hostBindings !== null || componentDef.hostAttrs !== null)) {
const elementIndex = rootTNode.index - HEADER_OFFSET;

View File

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

View File

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

View File

@ -59,7 +59,7 @@ export function ɵɵdirectiveInject<T>(
* @codeGenApi
*/
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
*/
export function ɵɵelementEnd(): void {
let previousOrParentTNode = getPreviousOrParentTNode();
let previousOrParentTNode = getPreviousOrParentTNode()!;
ngDevMode && assertDefined(previousOrParentTNode, 'No parent node to close.');
if (getIsParent()) {
setIsNotParent();

View File

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

View File

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

View File

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

View File

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

View File

@ -54,8 +54,7 @@ interface LFrame {
*
* This is used in conjunction with `isParent`.
*/
// FIXME(misko): should be `TNode|null` (add comment explaining it.)
previousOrParentTNode: TNode;
previousOrParentTNode: TNode|null;
/**
* If `isParent` is:
@ -263,7 +262,7 @@ export function ɵɵrestoreView(viewToRestore: OpaqueViewState) {
instructionState.lFrame.contextLView = viewToRestore as any as LView;
}
export function getPreviousOrParentTNode(): TNode {
export function getPreviousOrParentTNode(): TNode|null {
return instructionState.lFrame.previousOrParentTNode;
}
@ -441,7 +440,7 @@ function allocLFrame() {
function createLFrame(parent: LFrame|null): LFrame {
const lFrame: LFrame = {
previousOrParentTNode: null!, //
previousOrParentTNode: null, //
isParent: true, //
lView: null!, //
tView: null!, //

View File

@ -43,7 +43,7 @@ import { ViewRef } from './view_ref';
*/
export function injectElementRef(ElementRefToken: typeof ViewEngine_ElementRef):
ViewEngine_ElementRef {
return createElementRef(ElementRefToken, getPreviousOrParentTNode(), getLView());
return createElementRef(ElementRefToken, getPreviousOrParentTNode()!, getLView());
}
let R3ElementRef: {new (native: RElement|RComment): ViewEngine_ElementRef};
@ -79,7 +79,7 @@ export function injectTemplateRef<T>(
TemplateRefToken: typeof ViewEngine_TemplateRef,
ElementRefToken: typeof ViewEngine_ElementRef): ViewEngine_TemplateRef<T>|null {
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) */
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
// DI happens before we've entered its view, `getLView` will return the parent view instead.
const lView = getLView();
const tNode = getPreviousOrParentTNode();
const tNode = getPreviousOrParentTNode()!;
const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView);
return getOrCreateRenderer2(isLView(nodeAtIndex) ? nodeAtIndex : lView);
}