W3C home > Mailing lists > Public > whatwg@whatwg.org > May 2012

Re: [whatwg] Proposal: Add window.getLastError (or modify invocation arguments of window.onerror)

From: James Greene <james.m.greene@gmail.com>
Date: Thu, 10 May 2012 14:14:23 -0500
Message-ID: <CALrbKZhGTiMftzHeg0xBSkXj25VzEdja8ZuL58BQ5zz5njt37Q@mail.gmail.com>
To: Simon Pieters <simonp@opera.com>
Cc: whatwg@whatwg.org
In my opinion, adding the stack trace to the existing message would be
messy, breaks existing developer expectations, and possibly even breaks
backward compatibility of specific libraries/functions/monitoring/etc. in
some more extreme situations. If we can't just have the "Error" object
itself passed in, I'd much prefer "stack" as a fifth parameter versus
unexpected modification of an existing parameter.

We can also keep adding parameters to the "window.onerror" invocation till
we're blue in the face... but, in reality, don't we just want all of the
properties of the relevant "Error" object?  I'd really love to *just* have
the "Error" object passed (e.g. "window.onerror(function(e) { ... })") but
I know that would break backward compatibility, so I didn't propose it.

It seems to me like "columnNumber" should be added to the "Error" object as
a standard (speaking of which: https://github.com/JSFixed/JSFixed/issues/51)
*instead of* adding it as yet another parameter to the already ugly
"window.onerror", and then just pass the "Error" object so devs can get
whatever information they want from it.  But, if it's a security thing, I
guess I'm willing to accept that....

Sincerely,
    James Greene




On Wed, May 9, 2012 at 4:12 AM, Simon Pieters <simonp@opera.com> wrote:

> On Wed, 09 May 2012 03:56:29 +0200, James Greene <james.m.greene@gmail.com>
> wrote:
>
>  Full proposal details:
>>    https://gist.github.com/**3ded0f6e7f0a658b9394<https://gist.github.com/3ded0f6e7f0a658b9394>
>>
>
> quoting the above (revision https://gist.github.com/**
> 3ded0f6e7f0a658b9394/**51e980f0474c255738a3b6ecf003bb**6cb30db49c<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<https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error>
>> [2]: https://developer.mozilla.org/**en/JavaScript/Reference/**
>> Global_Objects/Error/Stack<https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack>
>> [3]: http://stacktracejs.com/
>> [4]: https://developer.mozilla.org/**en/DOM/window<https://developer.mozilla.org/en/DOM/window>
>> [5]: https://developer.mozilla.org/**en/DOM/window.onerror<https://developer.mozilla.org/en/DOM/window.onerror>
>> [6]: https://bugzilla.mozilla.org/**show_bug.cgi?id=355430<https://bugzilla.mozilla.org/show_bug.cgi?id=355430>
>> [7]: https://github.com/eriwen/**javascript-stacktrace/issues/**26<https://github.com/eriwen/javascript-stacktrace/issues/26>
>> [8]: https://github.com/eriwen/**javascript-stacktrace/issues/9<https://github.com/eriwen/javascript-stacktrace/issues/9>
>>
>
> --
> Simon Pieters
> Opera Software
>
Received on Thursday, 10 May 2012 19:19:57 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Wednesday, 30 January 2013 18:48:08 GMT