fix(ivy): errors not being logged to ErrorHandler (#28447)

Fixes Ivy not passing thrown errors along to the `ErrorHandler`.

**Note:** the failing test had to be reworked a little bit, because it has some assertions that depend on an error context being logged, however Ivy doesn't keep track of the error context.

This PR resolves FW-840.

PR Close #28447
This commit is contained in:
Kristiyan Kostadinov
2019-01-30 15:23:23 +01:00
committed by Matias Niemelä
parent a98d66078d
commit fc88a79b32
3 changed files with 137 additions and 79 deletions

View File

@ -8,6 +8,7 @@
import {InjectFlags, InjectionToken, Injector} from '../di';
import {resolveForwardRef} from '../di/forward_ref';
import {ErrorHandler} from '../error_handler';
import {Type} from '../interface/type';
import {validateAttribute, validateProperty} from '../sanitization/sanitization';
import {Sanitizer} from '../sanitization/security';
@ -936,6 +937,7 @@ function listenerInternal(
const tView = lView[TVIEW];
const firstTemplatePass = tView.firstTemplatePass;
const tCleanup: false|any[] = firstTemplatePass && (tView.cleanup || (tView.cleanup = []));
ngDevMode && assertNodeOfPossibleTypes(
tNode, TNodeType.Element, TNodeType.Container, TNodeType.ElementContainer);
@ -2605,13 +2607,17 @@ function wrapListener(
markViewDirty(startView);
}
const result = listenerFn(e);
if (wrapWithPreventDefault && result === false) {
e.preventDefault();
// Necessary for legacy browsers that don't support preventDefault (e.g. IE)
e.returnValue = false;
try {
const result = listenerFn(e);
if (wrapWithPreventDefault && result === false) {
e.preventDefault();
// Necessary for legacy browsers that don't support preventDefault (e.g. IE)
e.returnValue = false;
}
return result;
} catch (error) {
handleError(lView, error);
}
return result;
};
}
/**
@ -2723,12 +2729,17 @@ export function detectChangesInternal<T>(view: LView, context: T) {
if (rendererFactory.begin) rendererFactory.begin();
if (isCreationMode(view)) {
checkView(view, context); // creation mode pass
try {
if (isCreationMode(view)) {
checkView(view, context); // creation mode pass
}
checkView(view, context); // update mode pass
} catch (error) {
handleError(view, error);
throw error;
} finally {
if (rendererFactory.end) rendererFactory.end();
}
checkView(view, context); // update mode pass
if (rendererFactory.end) rendererFactory.end();
}
/**
@ -3237,3 +3248,10 @@ function loadComponentRenderer(tNode: TNode, lView: LView): Renderer3 {
const componentLView = lView[tNode.index] as LView;
return componentLView[RENDERER];
}
/** Handles an error thrown in an LView. */
function handleError(lView: LView, error: any): void {
const injector = lView[INJECTOR];
const errorHandler = injector ? injector.get(ErrorHandler, null) : null;
errorHandler && errorHandler.handleError(error);
}