-
Notifications
You must be signed in to change notification settings - Fork 27.5k
provide isError and use it in place of instanceof Error #15872
Conversation
@gkalpak what would be a good way to construct a test that boots up an iframe? And where should I put it? function testError(createError) {
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
try {
var error = createError(contentWindow);
expect(error instanceof Error).to.be.false();
expect(isError(error)).to.be.true();
} finally {
iframe.parentElement.removeChild(iframe);
}
}
testError(function (win) {
return new win.Error();
});
testError(function (win) {
try {
win.document.querySelectorAll('');
catch(e) {
return e;
}
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of minor comments. Looks OK otherwise (except for the missing tests).
The tests can go in https://github.com/graingert/angular.js/blob/af80f4765e2a9e795f64103b6e15770cf6eda050/test/AngularSpec.js.
src/Angular.js
Outdated
@@ -675,6 +676,28 @@ var isArray = Array.isArray; | |||
|
|||
/** | |||
* @ngdoc function | |||
* @name angular.isError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we want to make this public.
src/Angular.js
Outdated
* @returns {boolean} True if `value` is an `Error`. | ||
*/ | ||
function isError(value) { | ||
var tag = ({}).toString.call(value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have a closure-global toString = Object.prototype.toString
. You can simply toString.call(value)
.
test/minErrSpec.js
Outdated
@@ -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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems irrelevant here. Please remove.
What's wrong with publishing it?
…On 30 Mar 2017 16:02, "George Kalpakas" ***@***.***> wrote:
***@***.**** commented on this pull request.
A couple of minor comments. Looks OK otherwise (except for the missing
tests).
The tests can go in https://github.com/graingert/angular.js/blob/
af80f47/test/AngularSpec.js.
------------------------------
In src/Angular.js
<#15872 (comment)>:
> @@ -675,6 +676,28 @@ var isArray = Array.isArray;
/**
* @ngdoc function
+ * @name angular.isError
I don't think we want to make this public.
------------------------------
In src/Angular.js
<#15872 (comment)>:
> @@ -675,6 +676,28 @@ 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);
We already have a closure-global toString = Object.prototype.toString.
You can simply toString.call(value).
------------------------------
In test/minErrSpec.js
<#15872 (comment)>:
> @@ -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);
This seems irrelevant here. Please remove.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#15872 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAZQTITCKX7C5KczFgrrgsjIyNF_59gJks5rq8PvgaJpZM4MuDhG>
.
|
We have to maintain it in a backwards compatible way. If it is not public we can change/improve/remove it without any concerns. |
How do you not publish it?
…On 30 Mar 2017 16:12, "George Kalpakas" ***@***.***> wrote:
What's wrong with publishing it?
We have to maintain it in a backwards compatible way. If it is not public
we can change/improve/remove it without any concerns.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#15872 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAZQTBBUqkJGm3d_0jwZXROJIntlmhH7ks5rq8Z6gaJpZM4MuDhG>
.
|
Remove the |
src/ngMock/angular-mocks.js
Outdated
@@ -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)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a published isError is required here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could make it "private API" (e.g. angular.$$isError
), but I don't think it is worth it. This function (angular.mock.dump
) is very rarely used. It is also very rare to have new window contexts in unit tests and it is even more rare to have them throw errors. Plus, DOMException
s get decently stringified by JSON.stringify
(in contrast to plain Error
s which become "{}"
). All that considered, I think this one occurrence can remain object instanceof Error
😃
fdaccde
to
fb8f226
Compare
test/AngularSpec.js
Outdated
expect(isError(new Error())).toBe(true); | ||
}); | ||
|
||
function testError(createError) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this either at the top or at the bottom of the describe
block (or even create a nested describe
for "other-context" tests) and give it a more descriptive name (e.g. testErrorFromDifferent context
.
Maybe having a separate describe
block with beforeAll
/afterAll
blocks for creating/destorying the iframe is a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try { } finally { } is more fine grained in this usecase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's specific to the actual call to the testErrorFromDifferentContext function. Like the lifetime of the iframe is shorter than a test, no point leaving it hanging around until afterAll/beforeAll is called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am fine either way, so feel free to leave things as they are 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
src/ngMock/angular-mocks.js
Outdated
@@ -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)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could make it "private API" (e.g. angular.$$isError
), but I don't think it is worth it. This function (angular.mock.dump
) is very rarely used. It is also very rare to have new window contexts in unit tests and it is even more rare to have them throw errors. Plus, DOMException
s get decently stringified by JSON.stringify
(in contrast to plain Error
s which become "{}"
). All that considered, I think this one occurrence can remain object instanceof Error
😃
85edd0f
to
a5710b1
Compare
@gkalpak ok, I'm pretty sure I've resolved everything. Interestingly enough if seems as though Safari thinks DOMExceptions from frames are instances of Errors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
test/AngularSpec.js
Outdated
|
||
it('should not assume objects are errors', function() { | ||
expect(isError({ message: 'A fake error', stack: 'no stack here'})) | ||
.toBe(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Unnecessarily wrapped line.
(The commit message needs some love (as it doesn't follow our guidelines).) |
I am going to merge this as is, but feel free to add |
scratch that, DOMError only has a 'name' property and never has a stack, so it shouldn't be added imhop. |
Actually, before I merge it can you take care of the following:
|
what message should I use? |
Something that follows the guidelines. E.g. something like:
|
12345678901234567890123456789012345678901234567890123456789012345678901234567890 Errors thrown from different contexts (such as an iframe or webworker) are not detected as Error instances and handled accordingly. This commit fixes it by introducing an isError() helper, that is able to correctly detect such instances. Fixes angular#15868
@gkalpak any updates on this? |
What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
feature/bug
What is the current behavior? (You can also link to an open issue here)
What is the new behavior (if this is a feature change)?
Angular should pass them on to the correct excetion handler, and there's an angular.isError function now.
Does this PR introduce a breaking change?
No
Please check if the PR fulfills these requirements
Other information:
re-implimented https://github.com/yefremov/iserror/blob/master/index.js to avoid license and make code faster.
Fixes #15868