From af80f4765e2a9e795f64103b6e15770cf6eda050 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Thu, 30 Mar 2017 09:42:29 +0100 Subject: [PATCH] provide isError and use it in place of instanceof Error Fixes #15868 --- src/.eslintrc.json | 1 + src/Angular.js | 23 +++++++++++++++++++++++ src/ng/compile.js | 2 +- src/ng/log.js | 2 +- src/ng/q.js | 2 +- src/ngMock/angular-mocks.js | 2 +- test/.eslintrc.json | 1 + test/minErrSpec.js | 1 + test/ng/qSpec.js | 2 +- 9 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/.eslintrc.json b/src/.eslintrc.json index 4c240b733bf9..3f8163dcc9af 100644 --- a/src/.eslintrc.json +++ b/src/.eslintrc.json @@ -50,6 +50,7 @@ "isNumber": false, "isNumberNaN": false, "isDate": false, + "isError": false, "isArray": false, "isFunction": false, "isRegExp": false, diff --git a/src/Angular.js b/src/Angular.js index 7f539e81fb52..dcfb2fece29e 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -45,6 +45,7 @@ isNumber, isNumberNaN, isDate, + isError, isArray, isFunction, isRegExp, @@ -673,6 +674,28 @@ function isDate(value) { */ var isArray = Array.isArray; +/** + * @ngdoc function + * @name angular.isError + * @module ng + * @kind function + * + * @description + * Determines if a reference is an `Error`. + * + * @param {*} value Reference to check. + * @returns {boolean} True if `value` is an `Error`. + */ +function isError(value) { + var tag = ({}).toString.call(value); + switch (tag) { + case '[object Error]': return true; + case '[object Exception]': return true; + case '[object DOMException]': return true; + default: return value instanceof Error; + } +} + /** * @ngdoc function * @name angular.isFunction diff --git a/src/ng/compile.js b/src/ng/compile.js index 0405d3be76d3..a2d9730c3920 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -3098,7 +3098,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { } linkQueue = null; }).catch(function(error) { - if (error instanceof Error) { + if (isError(error)) { $exceptionHandler(error); } }); diff --git a/src/ng/log.js b/src/ng/log.js index 6849ed46de29..5dc36f23ae46 100644 --- a/src/ng/log.js +++ b/src/ng/log.js @@ -132,7 +132,7 @@ function $LogProvider() { }; function formatError(arg) { - if (arg instanceof Error) { + if (isError(arg)) { if (arg.stack && formatStackTrace) { arg = (arg.message && arg.stack.indexOf(arg.message) === -1) ? 'Error: ' + arg.message + '\n' + arg.stack diff --git a/src/ng/q.js b/src/ng/q.js index 8aff2e0cfe21..03cb238cd7dd 100644 --- a/src/ng/q.js +++ b/src/ng/q.js @@ -381,7 +381,7 @@ function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) { if (!toCheck.pur) { toCheck.pur = true; var errorMessage = 'Possibly unhandled rejection: ' + toDebugString(toCheck.value); - if (toCheck.value instanceof Error) { + if (isError(toCheck.value)) { exceptionHandler(toCheck.value, errorMessage); } else { exceptionHandler(errorMessage); diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index d6e84c75584f..3fcf3a31ea84 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -984,7 +984,7 @@ angular.mock.dump = function(object) { } else if (angular.isObject(object)) { if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) { out = serializeScope(object); - } else if (object instanceof Error) { + } else if (angular.isError(object)) { out = object.stack || ('' + object.name + ': ' + object.message); } else { // TODO(i): this prevents methods being logged, diff --git a/test/.eslintrc.json b/test/.eslintrc.json index 007b458949ad..37a263e305f2 100644 --- a/test/.eslintrc.json +++ b/test/.eslintrc.json @@ -64,6 +64,7 @@ "isNumber": false, "isNumberNaN": false, "isDate": false, + "isError": false, "isArray": false, "isFunction": false, "isRegExp": false, diff --git a/test/minErrSpec.js b/test/minErrSpec.js index 62f78c2c3ad1..633e795452a6 100644 --- a/test/minErrSpec.js +++ b/test/minErrSpec.js @@ -17,6 +17,7 @@ describe('minErr', function() { it('should return an Error factory', function() { var myError = testError('test', 'Oops'); expect(myError instanceof Error).toBe(true); + expect(isError(myError)).toBe(true); }); it('should generate stack trace at the frame where the minErr instance was called', function() { diff --git a/test/ng/qSpec.js b/test/ng/qSpec.js index f3a983100e41..23c939e689f4 100644 --- a/test/ng/qSpec.js +++ b/test/ng/qSpec.js @@ -37,7 +37,7 @@ describe('q', function() { // The following private functions are used to help with logging for testing invocation of the // promise callbacks. function _argToString(arg) { - return (typeof arg === 'object' && !(arg instanceof Error)) ? toJson(arg) : '' + arg; + return (typeof arg === 'object' && !(isError(arg))) ? toJson(arg) : '' + arg; } function _argumentsToString(args) {