<div dir="ltr">On Mon, Jun 17, 2013 at 11:33 AM, Chad Austin <span dir="ltr"><<a href="mailto:chad@imvu.com" target="_blank">chad@imvu.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<div dir="ltr">Hi Mark,<div><br></div><div>I'm the author of IMVU's task system, which is very similar to what Bruno describes except with Python Futures and Python generators.  Python provides stack traces as a linked list of activation records from the thrower to the catcher.  On the other hand, Error().stack in most JavaScript implementations returns a complete stack trace all the way up to the main event loop.  Python's linked list stack traces allows stitching them together so that if async generator A yields to async generator B, and B throws, both A and B can be made to appear in the stack together.  Finally, and this is key, Python attaches stack traces to the act of _throwing_ and not to the exception object itself.</div>
</div></blockquote><div><br></div><div style>I hope we can stitch together stack traces in JS as well. This is desperately needed to make asynchronous and distributed code practical, more on a par with local synchronous code. Please follow the Causeway links in the email you're responding to.</div>
<div style><br></div><div style>The Causeway work was done in the context of event-loops and promises, but not generators. We should explore how to extend its stack stitching approach to include generators.</div><div><br>
</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><div>

<br></div><div>I'm not familiar with the security or encapsulation issues with Error().stack (is it that bad if Chrome and Firefox appear to support the .stack property?)</div></div></div></blockquote><div><br></div>
<div style>Yes. Fortunately on Chrome we can effectively remove it <<a href="https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/debug.js">https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/debug.js</a>>. </div>
<div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><div>, but I would like to express my support for being able to stitch together stack traces on the open web so that if something goes wrong developers have a shot at diagnosing what happened.  Native application developers have dozens of fantastic options for phone-home crash reporting, but on the web the best you can hope for is that your customer's browser supports Error#stack and window.onerror provides the thrown exception.</div>
</div></div></blockquote><div><br></div><div style>The built-in window.onerror can have/use the rights amplification powers of the getStack or @stacktrace in my previous message. This would not violate any security constraint, since untrusted scripts within a frame are denied direct access to their true window and global scope anyway.</div>
<div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div>

</div><div><br></div><div>Thanks,</div><div>Chad</div><div><br></div><div>p.s. E was hugely influential in my thinking about concurrency and led me to build the task system at IMVU in the first place, so thanks!</div></div>
</blockquote><div><br></div><div style>You are very welcome! Always nice to hear.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div dir="ltr">
<div><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote"><div>On Sat, Jun 15, 2013 at 6:56 PM, Mark S. Miller <span dir="ltr"><<a href="mailto:erights@google.com" target="_blank">erights@google.com</a>></span> wrote:<br>


</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div><div dir="ltr"><div><div>On Sat, Jun 15, 2013 at 10:17 AM, David Bruant <span dir="ltr"><<a href="mailto:bruant.d@gmail.com" target="_blank">bruant.d@gmail.com</a>></span> wrote:<br>


</div></div><div class="gmail_extra"><div class="gmail_quote"><div><div>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Le 15/06/2013 11:18, Bruno Jouhier a écrit :<div><br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
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).<br>





</blockquote></div>
As an aside, note that we already have this sort of problem today with event loop turns.<br>
<br>
    function schedule(){<br>
        if(Math.random() < 0.5)<br>
            throw new Error('whatever');<br>
        else<br>
            setTimeout(schedule, Math.random()*100);<br>
    }<br>
<br>
    setTimeout(schedule, (Math.random()*100) |0)<br>
    setTimeout(schedule, (Math.random()*100) |0)<br>
<br>
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.<br>





Q solves that with long stack traces [1] (only for promises I believe). It might be worth looking into it.<br>
<br>
<br>
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.<br>





I'm thinking of something like:<br>
<br>
    (exports => {<br>
        var someCrucialInfo = // boolean<br>
<br>
        exports.bla = function*(){<br>
            if(someCrucialInfo){<br>
                doX();<br>
                yield 27;<br>
            }<br>
            else{<br>
                doY();<br>
                yield 27;<br>
            }<br>
        }<br>
    })(this);<br>
<br>
    var v = this.bla();<br>
    var l = getLastBlaYieldLine(bla);<br>
    // given l, the encapsulated value of someCrucialInfo can be inferred<br>
<br>
cc'ing MarkM to get his eyes on it as I don't feel qualified to assess the gravity.<br></blockquote><div><br></div></div></div><div>Thanks for calling my attention to this thread. Generators and multiple turns aside (see below), we've been over the security issue before but a recap is useful. The stack trace information cannot be publicly accessible from the Error object because it violates encapsulation. (Historical note: When E entered its first security review, it had this vulnerability. Thanks to David Wagner for catching it.) Instead, some sort of rights amplification is required. One possible interface is a privileged function, like the getStack function at <<a href="https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/debug.js#221" target="_blank">https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/debug.js#221</a>>, where</div>



<div><br></div><div>getStack(err) returns the stacktrace. If you don't have the getStack function, you can't get the stacktrace. getStack is implemented using a WeakMap associating Errors with stacktraces.</div>
<div><br></div><div>Another approach, if <<a href="http://wiki.ecmascript.org/doku.php?id=strawman:relationships" target="_blank">http://wiki.ecmascript.org/doku.php?id=strawman:relationships</a>> are adopted in ES7, is to have a relationship associating Error objects with stacktraces. The full read/write relationship would be internal to the implementation, but a relationship representing a readonly facet of that relationship, say @stacktrace, could be made available in the same privileged manner as getStack above. Then</div>



<div><br></div><div>err@stacktrace would return the same stacktrace that getStack(err) would return above.</div><div><br></div><div>If relationships don't happen in ES7 (it's too late for ES6) and private symbols do, then @stacktrace could be a private symbol.</div>



<div><br></div><div><br></div><div><br></div><div>Multiple turn distributed debugging is indeed the next frontier, and one that will become ever more urgent as promises continue to catch on. I participated in a cool project, Causeway, that explored some of this territory well</div>



<div><a href="http://www.hpl.hp.com/techreports/2009/HPL-2009-78.html" target="_blank">http://www.hpl.hp.com/techreports/2009/HPL-2009-78.html</a><br></div><div><a href="https://code.google.com/p/causeway/" target="_blank">https://code.google.com/p/causeway/</a><br>



</div><div><br></div><div>Although the project has since been abandoned, its trace log format is a good place to start, in order to be able to support something like this in the future:</div><div><a href="http://wiki.erights.org/wiki/Causeway_Platform_Developer" target="_blank">http://wiki.erights.org/wiki/Causeway_Platform_Developer</a><br>



</div><div><a href="http://wiki.erights.org/wiki/Causeway_Platform_Developer:_Ajax" target="_blank">http://wiki.erights.org/wiki/Causeway_Platform_Developer:_Ajax</a><br></div><div><a href="http://wiki.erights.org/wiki/Causeway_Platform_Developer:_Promises" target="_blank">http://wiki.erights.org/wiki/Causeway_Platform_Developer:_Promises</a><br>



</div><div><br></div><div><a href="https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/debug.js" target="_blank">https://code.google.com/p/google-caja/source/browse/trunk/src/com/google/caja/ses/debug.js</a><br>



</div><div>also provides some support for the Causeway log format. See getCWStack.</div><div><br></div><div>See also </div><div><a href="http://crpit.com/confpapers/CRPITV135Murray.pdf" target="_blank">http://crpit.com/confpapers/CRPITV135Murray.pdf</a> and<br>



</div><div><a href="http://infoscience.epfl.ch/record/181543/files/EPFL_TH5533.pdf" target="_blank">http://infoscience.epfl.ch/record/181543/files/EPFL_TH5533.pdf</a><br></div><div>for other interesting approaches to extended debugging</div>



<div><br></div><div><br></div><div>As for generators specifically, it seems to me that whatever rights amplification operation one applies to an Error object to get a stack trace, one should also be able to apply to a generator instance to get a 1-level stacktrace showing where it is currently suspended.</div>


<div>
<div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
oh... and we have the source code of functions by default with Function#toString.<br>
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.<br>
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)<div>




<br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
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.<br>
</blockquote></div>
I believe the state of TC39 on Error#stack can be found at<br>
<a href="http://wiki.ecmascript.org/doku.php?id=strawman:error_stack" target="_blank">http://wiki.ecmascript.org/<u></u>doku.php?id=strawman:error_<u></u>stack</a><br>
<br>
David<br>
<br>
[1] <a href="https://github.com/kriskowal/q#long-stack-traces" target="_blank">https://github.com/kriskowal/<u></u>q#long-stack-traces</a><br>
</blockquote></div></div><span><font color="#888888"><br><br clear="all"><div><br></div>-- <br>    Cheers,<br>    --MarkM
</font></span></div></div>
<br></div></div><div>_______________________________________________<br>
es-discuss mailing list<br>
<a href="mailto:es-discuss@mozilla.org" target="_blank">es-discuss@mozilla.org</a><br>
<a href="https://mail.mozilla.org/listinfo/es-discuss" target="_blank">https://mail.mozilla.org/listinfo/es-discuss</a><br>
<br></div></blockquote></div><span><font color="#888888"><br><br clear="all"><div><br></div>-- <br>Chad Austin<div>Technical Director, IMVU</div><div><a href="http://www.imvu.com/members/Chad/" target="_blank">http://www.imvu.com/members/Chad/</a>
</div><div><br></div>
</font></span></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>    Cheers,<br>    --MarkM
</div></div>