idea: try/catch and "rethrow"...?

Brendan Eich brendan at mozilla.com
Tue Feb 1 15:57:29 PST 2011


On Feb 1, 2011, at 1:17 PM, Allen Wirfs-Brock wrote:

> Also note that stacktrace properties on Error objects is not in the ECMAScript standard and personally I don't think it should be.

Having implemented SpiderMonkey's Error object 'stack' property as an extension, I agree.


> A debugger (or debugger infrastructure)  can capture stack trace information and maintain an association between a stack trace info and specific thrown objects.  Even if the object is thrown multiple times.  (BTW, this is probably a good use of Ephemeron tables.).  This information could even be reflected back to the JavaScript layer via an API that on-demand provides the stack trace info for a recently thrown error object.  But I really don't think stack-trace info should be automatically reified for every throw.  I think it should only happen if a debugger is active or if reflective debug support has been explicitly enabled.

This could be standardized some day, but just from what you describe, which is right on, it would take a lot of experimenting and evolution to get to the point where we could construct a good de-jure standard (bike-sheddy and nit-picky but little invention beyond the de-facto standard).


> You can probably get into a debate about about whether exceptions should be used for normal control flow purposes.  But they really are the only way in JavaScript to implement control flow that crosses function invocation  boundaries.  Because being a good host language is one of our goals keeping that style of throw as cheap as possible seems like something we should care about.

To reduce the cost I made SpiderMonkey's Error objects' 'stack' property string-valued, with the string formatted to be easily split or regexp-global-matched to get an array of useful frame info.

Also, this stack string is cons'ed up only for errors-as-exceptions. Throwing 42, "foo", false, or a user-defined object, does not entail any such overhead.


> Throwing a known string value at a handler with a catch guard for that string should seem to be about as lightweight as you can get.

Right. One place we require this is the Harmony iteration protocol, which uses a StopIteration singleton. We discussed Scheme-ish optional parameterization of the stop-iterating value but it is not worth its weight and the possibility of the option being used contaminates due to failure to catch. And mostly because it's exceedingly rare to have to catch StopIteration because the for-in loops and comprehensions catch for you.


> It would probably generate into something like the following
> 
> function loopForIn( obj, seq) {
>     let __innerReturn = {};
>     let __exitValue = __escape;
>     try {
>        let position = 0;
>        seq.do(function(elem) {
>            if (elem==obj) {
>                  //this clause is what the ^ compilers into
>                  if (__exitValue !== __innerReturn ) throw new cannotReturn();  //only one return allowed (not a full continuation)
>                  __exitValue = position;  //probably cheaper than adding a property to __exit object
>                 throw __innerReturn;
>            }
>           position = position + 1;
>       });
>       return -1;
>    } catch (e if e === __innerReturn) {
>        return  __exitValue;
>    }
> }

This can be made quite fast. But IIRC the current JS VMs, which optimize heavily, still don't go so fast when you add exception-handling to the profiles. It's rare in web JS.

/be



More information about the es-discuss mailing list