On Wed, 09 May 2012 03:56:29 +0200, James Greene
<james.m.gre...@gmail.com> wrote:
Full proposal details:
https://gist.github.com/3ded0f6e7f0a658b9394
quoting the above (revision
https://gist.github.com/3ded0f6e7f0a658b9394/51e980f0474c255738a3b6ecf003bb6cb30db49c
):
# Proposal: Add `window.getLastError` (or modify `window.onerror`)
## Error handling in an isolated scope
In our applications, most of us hopefully follow the UX best practice of
catching unexpected and/or unpreventable errors and logging them back to
the server-side for monitoring.
In isolated scopes, this can be achieved by setting up a try-catch
block, which also allows you to inspect the pertinent [`Error`][1]
object itself:
```
try {
throw new Error("WTF");
} catch (e) {
alert("Isolated error! Details: " + e);
}
```
This is very useful, especially in browsers that support the
[`stack`][2] property of the `Error` object to improve "debugability".
This property's availability is also of great benefit to @eriwen's
[StackTrace.js][3], which I find to be handy (though I'm not a big fan
of the StrackTrace.js API, as @eriwen and I have discussed previously).
## Error handling at the global scope
Setting up layers of try-catch blocks quickly becomes unreasonable in
large applications. As an alternative, we can attach a listener to the
[`window`][4] object's [`error`][5] event, which is invoked whenever an
error bubbles up without being handled elsewhere:
(It's not actually a real event.)
```
var oldOnError = window.onerror;
window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
if (oldOnError) {
return oldOnError(errorMsg, url, lineNumber);
}
alert("Globally unhandled error! Details: " + errorMsg);
return false;
}
```
## The problem with `window.onerror`
The problem is that this mechanism does not allow us to inspect the
pertinent `Error` object at all: it only provides us with three
arguments at invocation time: message (string), fileName (string), and
lineNumber (number). These are rarely useful in practice.
The spec now has a fourth argument for the column number (which is more
useful than line number for minimized scripts). Maybe column could be made
available on exceptions as well, though that's up to TC39, I think.
('stack' isn't specified currently, IIRC.)
## My proposal(s) to fix it
As such, I propose the following two options as fixes:
1. Add a function like `getLastError` to the global `window` object
that would fetch the actual `Error` object associated with the most
recent unhandled error. I would foresee common usage looking something
like the following:
```
var oldOnError = window.onerror;
window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
if (oldOnError) {
return oldOnError(errorMsg, url, lineNumber);
}
var e = window.getLastError();
alert("Globally unhandled error! But we now can discover its
origin. Details: " + e);
return false;
}
```
2. Alternatively (though less preferably), we could also update the
invocation arguments of `window.onerror` callbacks to include a new
fourth argument that would be the relevant `Error` object itself:
```
var oldOnError = window.onerror;
window.onerror = function myErrorHandler(errorMsg, url, lineNumber,
e) {
if (oldOnError) {
return oldOnError(errorMsg, url, lineNumber, e);
}
alert("Globally unhandled error! But we now can discover its
origin. Details: " + e);
return false;
}
```
While this essentially makes the first three arguments useless, I
have posed it this way for the sake of backward compatibility.
I'd prefer this second option (except making it the fifth argument),
because the exception object can become garbage earlier and because for
cross-origin script errors, the arguments to window.onerror are masked for
security reasons, and we would need to mask the exception object as well,
so it seems better to use the same mechanism for that.
Also for compile script errors, there is no exception object.
Are there other things on the exception object that are of interest, or
just the stack? If it's just the stack, maybe we could dump that as a
string argument?
## Errata
When [synchronously] handling an `Error` in an isolated scope, the
active `Error` object should be equivalent to the result of the
`window.getLastError()` function invocation:
```
try {
throw new Error("WTF");
} catch (e) {
assert(e === window.getLastError()); // true
}
```
## Summary
I know I can't be alone here, especially since there are logged bugs for
this in many trackers. For example: Mozilla's [bug #355430][6] and
StackTrace.js's Issues [#26][7] and [#9][8].
So... thoughts?
[1]:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error
[2]:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
[3]: http://stacktracejs.com/
[4]: https://developer.mozilla.org/en/DOM/window
[5]: https://developer.mozilla.org/en/DOM/window.onerror
[6]: https://bugzilla.mozilla.org/show_bug.cgi?id=355430
[7]: https://github.com/eriwen/javascript-stacktrace/issues/26
[8]: https://github.com/eriwen/javascript-stacktrace/issues/9
--
Simon Pieters
Opera Software