On Feb 1, 2011, at 11:52 AM, Mike Samuel wrote:
> 
> Do these problems go away if the stack trace is grabbed when the
> Throwable is constructed, not when it's thrown?
> 
> Java does this for java.lang.Throwable and it provides a
> fillInStackTrace() method to allow rethrowers to manually reset the
> stack trace to the throw point.
> 
> Java also allows for stackless exceptions via setStackTrace(new
> StackTraceElement[0]) which allows for pre-allocation of
> user-exceptions which for pragmatic reasons (imagine throwing an
> OutOfMemoryError because you ran out of space allocating the stack
> frame) shouldn't include stack.  This mitigates most of the
> inefficiency in using exceptions for control flow, and is used by Neal
> Gafter in his Java closures proposal to implement break/continue.
> 
Of course JavaScript doesn't have the concept of Throwable.  Any value can be 
thrown.

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

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.

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.

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.  But sometimes (for 
example within a recursive function) you need a unique throw value and that 
probably means a new object..

If I was going to compile the following Smalltalk code to JavaScript:

lookFor: obj in: seq  "return the position of obj within a sequence "
    | position |
    position = 0.
    seq do: [:elen| elem == obj ifTrue: [^position]. positiion := position+1].
    ^ -1 

(note that code in brackets [ ] is essentially an anonymous function and ^ 
within such code returns from the surrounding method)

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;
   }
}
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to