fix(core): correctly handle `null` or `undefined` in `ErrorHandler#handleError()` (#42881)

Since `ErrorHandler#handleError()` expects an argument of type `any` it
should be able to handle values such as `null` and `undefined`.
Previously, it failed to handle these values, because it was trying to
access properties on them.

This commit fixes it by ensuring no properties are accessed on `null` or
`undefined` values.

NOTE: This is part of fully addressing #28106.

Fixes #21252

PR Close #42881
This commit is contained in:
George Kalpakas 2021-07-20 12:25:57 +03:00 committed by Dylan Hunn
parent 4d86ea6471
commit eefe1682e8
3 changed files with 18 additions and 7 deletions

View File

@ -7,6 +7,7 @@
*/
import {getDebugContext, getErrorLogger, getOriginalError} from './errors';
import {DebugContext} from './view/types';
@ -58,17 +59,17 @@ export class ErrorHandler {
}
/** @internal */
_findContext(error: any): any {
_findContext(error: any): DebugContext|null {
return error ? (getDebugContext(error) || this._findContext(getOriginalError(error))) : null;
}
/** @internal */
_findOriginalError(error: Error): any {
let e = getOriginalError(error);
_findOriginalError(error: any): Error|null {
let e = error && getOriginalError(error);
while (e && getOriginalError(e)) {
e = getOriginalError(e);
}
return e;
return e || null;
}
}

View File

@ -21,8 +21,8 @@ export function getOriginalError(error: Error): Error {
return (error as any)[ERROR_ORIGINAL_ERROR];
}
export function getErrorLogger(error: Error): (console: Console, ...values: any[]) => void {
return (error as any)[ERROR_LOGGER] || defaultErrorLogger;
export function getErrorLogger(error: unknown): (console: Console, ...values: any[]) => void {
return error && (error as any)[ERROR_LOGGER] || defaultErrorLogger;
}

View File

@ -23,7 +23,7 @@ function errorToString(error: any) {
const errorHandler = new ErrorHandler();
(errorHandler as any)._console = logger as any;
errorHandler.handleError(error);
return logger.res.map(line => line.join('#')).join('\n');
return logger.res.map(line => line.map(x => `${x}`).join('#')).join('\n');
}
describe('ErrorHandler', () => {
@ -32,6 +32,16 @@ describe('ErrorHandler', () => {
expect(e).toContain('message!');
});
it('should correctly handle primitive values', () => {
expect(errorToString('message')).toBe('ERROR#message');
expect(errorToString(404)).toBe('ERROR#404');
expect(errorToString(0)).toBe('ERROR#0');
expect(errorToString(true)).toBe('ERROR#true');
expect(errorToString(false)).toBe('ERROR#false');
expect(errorToString(null)).toBe('ERROR#null');
expect(errorToString(undefined)).toBe('ERROR#undefined');
});
describe('context', () => {
it('should print nested context', () => {
const cause = new Error('message!');