fix(core): ensure init lifecycle events are called (#20258)
Throwing an exception in a lifecycle event will delay but not prevent an Init method, such as `ngOnInit`, `ngAfterContentInit`, or `ngAfterViewInit`, from being called. Also, calling `detectChanges()` in a way that causes duplicate change detection (such as a child component causing a parent to call `detectChanges()` on its own `ChangeDetectorRef`, will no longer prevent change `ngOnInit`, `ngAfterContentInit` and `ngAfterViewInit` from being called. With this change lifecycle methods are still not guarenteed to be called but the Init methods will be called if at least one change detection pass on its view is completed. Fixes: #17035 PR Close #20258
This commit is contained in:

committed by
Jason Aden

parent
743651f5e8
commit
24cf8b3269
@ -16,7 +16,7 @@ import {checkAndUpdatePureExpressionDynamic, checkAndUpdatePureExpressionInline,
|
||||
import {checkAndUpdateQuery, createQuery} from './query';
|
||||
import {createTemplateData, createViewContainerData} from './refs';
|
||||
import {checkAndUpdateTextDynamic, checkAndUpdateTextInline, createText} from './text';
|
||||
import {ArgumentType, CheckType, ElementData, NodeData, NodeDef, NodeFlags, ProviderData, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, asElementData, asQueryList, asTextData} from './types';
|
||||
import {ArgumentType, CheckType, ElementData, NodeData, NodeDef, NodeFlags, ProviderData, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, asElementData, asQueryList, asTextData, shiftInitState} from './types';
|
||||
import {NOOP, checkBindingNoChanges, isComponentView, markParentViewsForCheckProjectedViews, resolveDefinition, tokenKey} from './util';
|
||||
import {detachProjectedView} from './view_attach';
|
||||
|
||||
@ -236,7 +236,8 @@ function createView(
|
||||
context: null,
|
||||
component: null, nodes,
|
||||
state: ViewState.CatInit, root, renderer,
|
||||
oldValues: new Array(def.bindingCount), disposables
|
||||
oldValues: new Array(def.bindingCount), disposables,
|
||||
initIndex: -1
|
||||
};
|
||||
return view;
|
||||
}
|
||||
@ -353,29 +354,32 @@ export function checkAndUpdateView(view: ViewData) {
|
||||
} else {
|
||||
view.state &= ~ViewState.FirstCheck;
|
||||
}
|
||||
shiftInitState(view, ViewState.InitState_BeforeInit, ViewState.InitState_CallingOnInit);
|
||||
markProjectedViewsForCheck(view);
|
||||
Services.updateDirectives(view, CheckType.CheckAndUpdate);
|
||||
execEmbeddedViewsAction(view, ViewAction.CheckAndUpdate);
|
||||
execQueriesAction(
|
||||
view, NodeFlags.TypeContentQuery, NodeFlags.DynamicQuery, CheckType.CheckAndUpdate);
|
||||
|
||||
let callInit = shiftInitState(
|
||||
view, ViewState.InitState_CallingOnInit, ViewState.InitState_CallingAfterContentInit);
|
||||
callLifecycleHooksChildrenFirst(
|
||||
view, NodeFlags.AfterContentChecked |
|
||||
(view.state & ViewState.FirstCheck ? NodeFlags.AfterContentInit : 0));
|
||||
view, NodeFlags.AfterContentChecked | (callInit ? NodeFlags.AfterContentInit : 0));
|
||||
|
||||
Services.updateRenderer(view, CheckType.CheckAndUpdate);
|
||||
|
||||
execComponentViewsAction(view, ViewAction.CheckAndUpdate);
|
||||
execQueriesAction(
|
||||
view, NodeFlags.TypeViewQuery, NodeFlags.DynamicQuery, CheckType.CheckAndUpdate);
|
||||
callInit = shiftInitState(
|
||||
view, ViewState.InitState_CallingAfterContentInit, ViewState.InitState_CallingAfterViewInit);
|
||||
callLifecycleHooksChildrenFirst(
|
||||
view, NodeFlags.AfterViewChecked |
|
||||
(view.state & ViewState.FirstCheck ? NodeFlags.AfterViewInit : 0));
|
||||
view, NodeFlags.AfterViewChecked | (callInit ? NodeFlags.AfterViewInit : 0));
|
||||
|
||||
if (view.def.flags & ViewFlags.OnPush) {
|
||||
view.state &= ~ViewState.ChecksEnabled;
|
||||
}
|
||||
view.state &= ~(ViewState.CheckProjectedViews | ViewState.CheckProjectedView);
|
||||
shiftInitState(view, ViewState.InitState_CallingAfterViewInit, ViewState.InitState_AfterInit);
|
||||
}
|
||||
|
||||
export function checkAndUpdateNode(
|
||||
|
Reference in New Issue
Block a user