API to get stack frame info from generator

David Bruant bruant.d at gmail.com
Sat Jun 15 10:17:31 PDT 2013


Le 15/06/2013 11:18, Bruno Jouhier a écrit :
> A generator object represents a computation which has been suspended. 
> We have an API to resume this computation (next/throw). What's missing 
> is an API to get information about this suspended computation (which 
> function, where in the source).
As an aside, note that we already have this sort of problem today with 
event loop turns.

     function schedule(){
         if(Math.random() < 0.5)
             throw new Error('whatever');
         else
             setTimeout(schedule, Math.random()*100);
     }

     setTimeout(schedule, (Math.random()*100) |0)
     setTimeout(schedule, (Math.random()*100) |0)

There is no way to know how many scheduling happened before the first 
thrown error, nor whether the error comes from the first or second 
scheduling originally. And that's a dummy 5-line example. It gets worse 
when you have a sequence of different events (or promise resolutions) 
called at different times, adding other listeners, etc.
Q solves that with long stack traces [1] (only for promises I believe). 
It might be worth looking into it.


Back to your problem, I worry that this kind of information (a call to 
get the stack trace of where the generator last yielding with line 
number) may partially break encapsulation which wouldn't be good for 
security.
I'm thinking of something like:

     (exports => {
         var someCrucialInfo = // boolean

         exports.bla = function*(){
             if(someCrucialInfo){
                 doX();
                 yield 27;
             }
             else{
                 doY();
                 yield 27;
             }
         }
     })(this);

     var v = this.bla();
     var l = getLastBlaYieldLine(bla);
     // given l, the encapsulated value of someCrucialInfo can be inferred

cc'ing MarkM to get his eyes on it as I don't feel qualified to assess 
the gravity.
oh... and we have the source code of functions by default with 
Function#toString.
This sort of inference can happen in regular error stack traces too, but 
requires for a function to throw which happens only if it's supposed to, 
not at the caller's will.
Though I realize now that anyone holding a reference to a generator can 
force an error being thrown and, if uncaught, it generates a stack trace 
leaking the line number even without the API you're asking for (but that 
would work only once)

> I see this as being similar to asking for a portable "stack" property 
> in Error objects. I don't know if it is actually mandated by ES6 but 
> it looks like all major JS engines support it now.
I believe the state of TC39 on Error#stack can be found at
http://wiki.ecmascript.org/doku.php?id=strawman:error_stack

David

[1] https://github.com/kriskowal/q#long-stack-traces


More information about the es-discuss mailing list