-
Notifications
You must be signed in to change notification settings - Fork 20.5k
Core: Re-throw errors that happened in callbacks wrapped in jQuery ready #3210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Please review. I'd like to have it released quickly, preferably no later than next week. cc @jquery/core |
test/unit/core.js
Outdated
| var message, | ||
| origWindowSetTimeout = window.setTimeout; | ||
|
|
||
| window.setTimeout = function( fn ) { |
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 was wondering how you'd do this 👍
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.
You could use sinon here, right?
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.
Yeah, I was thinking about sinon but it's not activated at all for this module, I'd need to enter the sinon sandbox to be able to use spies, wouldn't I?
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.
Not necessary to use sandbox i think, sandbox usually needed to clean up some scope of spies/stubs, you probably could just use -
sinon.stub(window, 'setTimeout', myOwnThing);
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.
Thanks, I'll try that.
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.
You can use sinon if you want, but for a case like this it's really nice to be able to look at the code and understand what it does without reading though sinon docs.
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'd say sinon is used almost universally for mocking/spying/stubing/etc it has very simple obvious api with clear documentation and we already use it.
So i would suggest to use it anywhere we can
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.
@markelog I had to create a sandbox and use this.sandbox.stub instead of sinon.stub or stubs wouldn't have been cleaned up (because how would Sinon know when to clean up?). It works fine now.
|
LGTM |
| define( [ | ||
| "../core", | ||
| "../var/document", | ||
| "../core/readyException", |
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 should be 3.1 only though i.e. minor? Do we have corresponding docs pr/issue?
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 know you labelled it as 3.1.0, just checking
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.
Oh, i see jquery/api.jquery.com#942, we need a pr for it though? Before we can release?
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'll submit a docs PR once this is accepted, no worries.
At the meeting we agreed that since this issue kind of breaks all Angular apps (as they wrap their init code in $() and all bootstrapping errors are silenced) we'll release a quick 3.1.0 with maybe only this fix. I renamed previous milestones: 3.0.1 to 3.1.1 and 3.1.0 to 3.2.0.
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.
Sounds good
|
Do you wanna release before providing a fix for #3194? |
| jQuery.readyException = function( error ) { | ||
| window.setTimeout( function() { | ||
| throw error; | ||
| } ); |
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 forgot @gibson042 wanted to have this reject as well so that a more general potential unhandled rejections mechanism would catch it. The code would be:
jQuery.readyException = function( error ) {
window.setTimeout( function() {
throw error;
} );
throw error;
};I have doubts about the need for that, though - the error thrown in a timeout would fire window.onerror anyway, do we need both mechanism to work here? Usually an error is either synchronous and handled by window.onerror or asynchronous and handled by the other mechanism.
cc @dmethvin as you already LGTM'd this PR. :)
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 seems we would need to rename readyException? If it would be used in more general sense? Also we need to re-throw error twice?
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 not meant to be used in a more general sense, it was only about integrating with existing debugging tools.
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.
Not sure if i understand the use-case, maybe it would be better to discuss this in separate ticket?
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 forgot @gibson042 wanted to have this reject as well so that a more general potential unhandled rejections mechanism would catch it.
If you wanted to catch your own ready handler's rejections you can already do $.when($.ready).then(fn).catch(errfn) in 3.0. What other cases do we want to handle? I feel like 99.9% of the cases are errors and as long as we manage to dump a stack we're doing all we need to do.
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.
The important detail to me is that our default handling doesn't suppress unhandled rejections, since doing so was the essence of the original complaint (and I still want to keep the door open for an unhandled rejections plugin). In fact, if we were willing to advocate $.when($.ready).then(fn).catch(errfn) strongly enough, then gh-3174 could be closed with no code changes whatsoever.
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.
@gibson042 I think that could work only if we deprecated/removed $(fn) but this is such a popular pattern that I don't see it going away any time soon. And this fact alone is enough for me to want it not silencing exceptions.
|
Is it possible that we use something similar to For instance: $( fn ).on( "exception", handler );That way, you don't break the existing API and the modification is not on deferreds necessarily, although I am not sure if it is possible to put a correlation between the |
|
For existing code, no additional API is useful unless its default provides helpful information, which this PR does. Someone who doesn't like the default can change it. For new code where an exception is expected, you can either attach a handler to the promise via I don't think anything else is required is it? What case would another API handle that those options do not? |
Also, expose jQuery.readyException that allows to overwrite the default ready error handler. Fixes jquerygh-3174 Closes jquerygh-3210
|
The PR is ready and passes I've also submitted API docs for this method: jquery/api.jquery.com#946. Please review. I'd like to land this today if no one objects. |
test/unit/core.js
Outdated
| jQuery( function() { | ||
| throw new Error( "Error in jQuery ready" ); | ||
| } ); | ||
| assert.strictEqual( message, "Error in jQuery ready", "The error wasn't thrown in a timeout" ); |
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.
Shouldn't "wasn't" here be "was"?
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.
Fixed.
|
The default |
Also, expose jQuery.readyException that allows to overwrite the default ready error handler. Fixes jquerygh-3174 Closes jquerygh-3210
What about the @dmethvin's remark at #3210 (comment)? I'm not sure I see the need of a double-error-dispatch approach here. In general there are two kinds of errors - the ones that propagate to To me the fact that |
|
I agree. The main problem was that there was no info on the error. One throw seems like enough. |
Okay, that's persuasive. Suggestion withdrawn. |
| readyList.then( fn ); | ||
| readyList | ||
| .then( fn ) | ||
| .catch( function( error ) { |
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.
.catch(jQuery.readyException)wouldn't work?
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.
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 added a comment there.
Also, expose jQuery.readyException that allows to overwrite the default ready error handler. Fixes jquerygh-3174 Closes jquerygh-3210
|
LGTM |
|
All comments addressed. I'll land it later today unless new review remarks come up before. |
Summary
Re-throw errors that happened in callbacks wrapped in jQuery ready
Also, expose jQuery.readyException that allows to overwrite the default
ready error handler.
Checklist
Mark an
[x]for completed items, if you're not sure leave them unchecked and we can assist.Thanks! Bots and humans will be around shortly to check it out.
Fixes gh-3174