-
Notifications
You must be signed in to change notification settings - Fork 13
Should wrapped functions send their errors to HostReportErrors (i.e. window.onerror)? #1
Comments
Now most browser APIs fall into 2(b) category. For example So the safe thing to do is to say that when we are passing a callback into the library:
|
I don't think that is the correct conclusion from your premises. 2(b) libraries like EventTarget can do something useful with the error: they forward it to the global event handler. But that's a very specific decision that EventTarget made. Other libraries (e.g. Node's EventEmitter) just let the error bubble (so To me, the conclusion is that we should instead add a primitive to the platform like the following: window.runGuarded = function (cb) {
try {
cb();
} catch (e) {
window.dispatchEvent(new ErrorEvent({ message: e.message, filename: parseFilename(e), lineno: parselineNo(e), colno: parsecolNo(e), error: e }));
// Or, in the future: call Zone.current's error handler with e.
}
}; Then libraries who want to censor thrown errors can easily do I don't think, however, that the behavior of |
The event handling must be done inside the |
How would doing the exception handling in the wrap method help with that at all? |
OK, I think I see... addEventListener(name, cb) {
this._eventListeners.append(name, Zone.current.wrap(cb));
}
dispatchEvent(name, e) {
for (const listener of this._eventListeners.get(name)) {
try {
listener(e);
} catch (err) {
// we want to send err to listener's zone, not to Zone.current. Problem.
}
}
} There are a lot of potential solutions here besides having wrap implicitly do runGuarded behavior, though. Let's brainstorm a bit.
I'm not sure if these are better or worse than having wrap run things with special behavior. They're certainly more low-level and flexible, which is a plus. (2) seems pretty good, in particular. |
I think Could you explain your motivation why you don't want to catch errors? What is the issue you are concerned with? |
Please read (2) again. You can make I'll respond more later today. |
Sorry, not following, Could you show actual code implementation of how that would work. |
Sure. Zone.runGuarded = function (f, thisArg, ...args) {
const zoneForF = GetZoneForWrappedFunction(f);
try {
zoneForF.run(() => f.apply(thisArg, args));
} catch (e) {
zoneForF.handleError(e);
}
}; (In reality you wouldn't do the enter-run-exit-reenter-handleError-exit dance but instead just enter-run-handleError-exit.) |
My motivation here is that |
A more inclusive approach would be to have all four of wrap+wrapGuarded and run+runGuarded. That might start making this proposal seem too heavy though and like it is dealing with error handling too much. @ofrobots @littledan thoughts? If we are going for minimal, and for not dealing with error handling (i.e. we have no desire to run error handlers inside a specific zone in the initial proposal), then it really seems like we should let errors bubble instead of sending them to |
I strongly favor keeping the proposal minimal and staying away from error handling at the moment. Couldn't runGuarded and wrapGuarded be introduced in the future when we are add error handling semantics to the spec. I don't think the semantics of run and wrap need to change at that point, correct? /cc @matthewloring |
I like the minimal proposal better too, leaving out error handling. It seems like implementations of user-level queuing have two different problems--propagating zones and having different error handling semantics. Error handling semantics can be done in JavaScript instead, and don't need built-in support the way that Zones do. It could be a nice convenience for these queuing library authors, but it is not part of the minimal package. |
I have great fear that unexpected errors will be silenced and leave applications in bad state. This was a problem with domains once libraries started to swallow each other's errors. |
(sorry for the delay in getting back to this issue) From my experience with implementing Zones I think that having Proposal: Let's remove |
Are you proposing that |
@littledan yes. (there is nothing special about |
As a language nerd, I always like fewer primitives. However, this may have implications for being efficiently implementable. It might be that a wrap primitive is more efficient than run+closure, but we have not yet done enough implementation design work to say. |
@mhevery and I discussed this in some detail and he managed to convince me that most libraries do in fact want wrapGuarded instead of wrap. Since there seems to be a general push against having error handling in the MVP spec, I think the course of action is then to remove wrap. |
@domenic could you explain what caused your change of heart here? |
Does this mean more silent errors if handleError is not callable? |
What is handleError? |
From #1 (comment)
That was for runGuarded, but I presume wrapGuarded would be similar. |
That's not part of this proposal, it was just a strawman as part of the discussion. |
@domenic then what is wrapGuarded? |
It's not clear. That's what this thread was discussing, before we decided to not have any type of wrap at all. |
@mhevery In my initial spec for Zone.prototype.wrap I've just had it act similarly to calling
z.run(cb)
. Errors are rethrown.In previous discussions you thought it was necessary to use "runGuarded" functionality here, where errors are not rethrown but instead sent to
window.onerror
(or, in the future, a zone-specific error handler).However, I'm no longer convinced this is the right design. I think we can accomplish everything we want with errors being rethrown. We just have to make sure that callers like EventTarget continue to send thrown errors to window.onerror (and, in the future, the relevant zone).
Can you remind me why you thought it was necessary to catch the errors and send them to
window.onerror
wheneverwrap
is used?The text was updated successfully, but these errors were encountered: