-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
[BUGFIX release] mark handled errors and dont reraise #12549
[BUGFIX release] mark handled errors and dont reraise #12549
Conversation
@@ -865,6 +877,10 @@ function triggerEvent(handlerInfos, ignoreFailure, args) { | |||
if (handler.actions[name].apply(handler, args) === true) { | |||
eventWasHandled = true; | |||
} else { | |||
// Should only hit here if a non-bubbling error action is triggered on a route. | |||
if (name === 'error') { | |||
markErrorAsHandled(args[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.
What is args[0]
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.
args[0] is the error. It's the first argument to the error action. Should I call it out as a var?
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.
Discussed in slack with @minasmart, I believe we have a path forward. Also, this will be a |
8fba3c2
to
1217cdb
Compare
Looks like this is causing a failure in the node test suite. You can reproduce via: ember server
# in another terminal
node bin/run-node-tests.js |
Will take a look. |
This branch is based off of master, and this test seems to consistently fail on master too. |
Actually, that's wrong. It logs out the error but doesn't fail an assertion. Are errors not sent up with |
Which test is throwing? |
The error is being thrown from |
Without understanding a little bit more about how |
More research, if I just don't throw the error in the catch for node, then all the node tests pass. Which also feels wrong. |
Yes, we definitely need to rethrow unhandled errors. |
1774576
to
25c14ab
Compare
Remaining error is a sauce/IE 10 error, and I don't know how to check the actual output of the test suite for that one. |
I restarted the sauce labs tests. Likely it is a timeout issue (we have been fighting them for a while). |
Let's hope. |
Looks good to me. @stefanpenner is going to review this when he gets a minute to help ensure we have thought through all the angles on this one... |
Great! Thanks again for all your help! |
has someone isolated what code regressed this? |
ah 854d3be |
@@ -705,6 +706,24 @@ var EmberRouter = EmberObject.extend(Evented, { | |||
run.cancel(this._slowTransitionTimer); | |||
} | |||
this._slowTransitionTimer = null; | |||
}, | |||
|
|||
_handledErrors: computed(function() { |
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.
If we go down this path, it seems simpler to just brand the given error with a hasBeenHandled symbol. No need to keep these data-structures around.
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.
error[hasBeenHandledSymbol] = true
although this wont work with primitive values, i think thats fine.
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.
Directly branding the error seems ok to me (it really isn't a big change for this PR as the basic infrastructure to brand is done), but I believe that we have a few tests in Ember itself that reject("asdf")
or throw "asdf"
which will need to be changed.
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.
That was my first attempt, but the problem I hit was that there's no insurance that the error isn't a primitive type, and there are several tests where it IS a primitive type. This wouldn't be a difficult change (to fire an assertion of the type isn't an object, and update the tests) but it would probably be a problem for a lot of apps. It would need to be noted/documented/blogged about or something.
I am slightly concerned that a "handled error" that is then re-thrown, will be incorrectly branded as handled and will be eaten. I'll try to carve out some time shortly, to do a deeper dive. |
@stefanpenner - |
@rwjblue nothing prevents the user from re-throwing, or passing the exception through another promise chain, that may or may not rethrow it later. At which point, it would be totally and unexpectedly ignored. |
@stefanpenner another promise chain would resolve outside of the transition, so it shouldn't be a problem there (handled errors are only checked as part of the transition's promise). The only way the error could be re-injected into the same transition would be bubbling up. Unless I'm missing a step where after the error hook gets fired Ember makes an effort to resolve more promises as part of the same transition. |
@stefanpenner Also, just checked. If I have an error hook like this: error(e) {
throw e;
return false;
} The error isn't swallowed. Similarly, if the error is thrown as part of a separate promise chain, or other asynchronous task like this: error(e) {
Ember.run.next(function() {
throw e;
});
return false;
} The error is still not swallowed. As part of the transition, it's not re-raised, it gets thrown after the promise completes. |
Also, @stefanpenner I can write more tests to model the cases you're talking about, if you want more insurance! |
We are catching and ignoring the error only if their
@minasmart - A couple tests to show that my above statement is true would definitely be nice. |
Should have time to get tests up later this week. |
@minasmart - That would be awesome, thank you! |
@minasmart - Have you been able to make any progress here? |
@rwjblue been extremely busy. Will push them up tomorrow. |
@minasmart Thanks so much for identifying this problem and fixing it! Had been struggling for days to track down what was going on with some failures until @rwjblue pointed me here. |
@minasmart - I definitely understand that, thanks for keeping at this! |
Ember 2.1 introduced a regression where all errors during a transition were thrown, even when those errors had been handled in a route's error action. This PR adds a test to identify the regression, and adds some logic and state to identify errors that have been handled, and not reraise them, while maintaining the desired behaviour of throwing errors that aren't handled. This is especially valuable in any application that tests error handling. Since all errors were being thrown regardless of handling, failed assertions were being registered by qunit, and it became impossible to test application flow that entered the error hook. Further details about this issue are here: emberjs#12547 Remove leftover debugger This addresses an issue where handled errors are still thrown The added test passes on Ember 2.0. It fails on Ember 2.1 because even though the error is not bubbled, the application throws the handled error. This is contrary to what the documentation indicates. Full details about this issue are here: emberjs#12547 This PR also adds a very naive implementation of how to flag an error as having been handled and prevents reraising, while retaining the functionality of throwing errors that aren't caught, or are bubbled from the application route Make error checking methods a part of the router instance Attach error caching methods to EmberRouter, and use guids for errors Errors used as keys were just getting `.toString()`ed, so multiple `Error`s or hashes would all have the same key. This update uses ember `guidFor` to uniquely identify errors. Thanks for the help @rwjblue! When creating a new promise, resolve it. Don't fork the promise Tests expecting errors to bubble up, should bubble errors
25c14ab
to
dd160a6
Compare
This provides insurance that handled errors aren't swallowed
More tests added! Lots of rethrowing different ways. |
Thank you! @stefanpenner - Can you re-review? We can add more scenario tests if you still think there are missing scenarios here... |
It looks like sauce tests timing out again 😞 |
cal reminder set for tomorrow morning. |
@stefanpenner friendly reminder about this :) would love to see it get into 2.3.0 |
@swalkinshaw - Agreed. |
Rebased and slightly tweaked in #12752. Planning to land into 2.3.0 and current stable branch (2.2.x). |
Ember 2.1 introduced a regression where all errors during a transition
were thrown, even when those errors had been handled in a route's error
action. This PR adds a test to identify the regression, and adds some
logic and state to identify errors that have been handled, and not
reraise them, while maintaining the desired behaviour of throwing errors
that aren't handled.
This is especially valuable in any application that tests error
handling. Since all errors were being thrown regardless of handling,
failed assertions were being registered by qunit, and it became
impossible to test application flow that entered the error hook.
Further details about this issue are here: #12547