fix(core): don’t stop change detection because of errors

- prevents unsubscribing from the zone on error
- prevents unsubscribing from directive `EventEmitter`s on error
- prevents detaching views in dev mode if there on error
- ensures that `ngOnInit` is only called 1x (also in prod mode)

Fixes #9531
Fixes #2413
Fixes #15925
This commit is contained in:
Tobias Bosch
2017-04-28 11:50:45 -07:00
committed by Matias Niemelä
parent ac220fc2bb
commit e263e19a2a
16 changed files with 218 additions and 68 deletions

View File

@ -211,7 +211,7 @@ function createView(
viewContainerParent: null, parentNodeDef,
context: null,
component: null, nodes,
state: ViewState.FirstCheck | ViewState.CatDetectChanges, root, renderer,
state: ViewState.CatInit, root, renderer,
oldValues: new Array(def.bindingCount), disposables
};
return view;
@ -323,6 +323,12 @@ export function checkNoChangesView(view: ViewData) {
}
export function checkAndUpdateView(view: ViewData) {
if (view.state & ViewState.BeforeFirstCheck) {
view.state &= ~ViewState.BeforeFirstCheck;
view.state |= ViewState.FirstCheck;
} else {
view.state &= ~ViewState.FirstCheck;
}
Services.updateDirectives(view, CheckType.CheckAndUpdate);
execEmbeddedViewsAction(view, ViewAction.CheckAndUpdate);
execQueriesAction(
@ -345,7 +351,6 @@ export function checkAndUpdateView(view: ViewData) {
if (view.def.flags & ViewFlags.OnPush) {
view.state &= ~ViewState.ChecksEnabled;
}
view.state &= ~ViewState.FirstCheck;
}
export function checkAndUpdateNode(
@ -453,7 +458,7 @@ function checkNoChangesQuery(view: ViewData, nodeDef: NodeDef) {
if (queryList.dirty) {
throw expressionChangedAfterItHasBeenCheckedError(
Services.createDebugContext(view, nodeDef.index), `Query ${nodeDef.query!.id} not dirty`,
`Query ${nodeDef.query!.id} dirty`, (view.state & ViewState.FirstCheck) !== 0);
`Query ${nodeDef.query!.id} dirty`, (view.state & ViewState.BeforeFirstCheck) !== 0);
}
}
@ -543,13 +548,13 @@ function callViewAction(view: ViewData, action: ViewAction) {
switch (action) {
case ViewAction.CheckNoChanges:
if ((viewState & ViewState.CatDetectChanges) === ViewState.CatDetectChanges &&
(viewState & (ViewState.Errored | ViewState.Destroyed)) === 0) {
(viewState & ViewState.Destroyed) === 0) {
checkNoChangesView(view);
}
break;
case ViewAction.CheckAndUpdate:
if ((viewState & ViewState.CatDetectChanges) === ViewState.CatDetectChanges &&
(viewState & (ViewState.Errored | ViewState.Destroyed)) === 0) {
(viewState & ViewState.Destroyed) === 0) {
checkAndUpdateView(view);
}
break;