Discussion:
Maximally minimal stack trace standardization
John Lenz
2014-09-28 05:15:15 UTC
Permalink
I would like to get see stack traces standardized for ES7, to that end, I
would like to define a minimal set of behaviors that would need to be
defined:

* the "stack" property (a string)
* when the stack property is attached (at Error object creation or at throw)
* what happens when Error object that has been thrown, is thrown again
(nothing)
* the stack trace in the face of tail recursion optimizations (skipped?)
* the minimal information that a stack trace should contain (file, line,
column)
* the format of the minimal information
* how additional information is added to the stack trace (named evals, etc)

Does this sound like a reasonable minimal set?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140927/fbdf9bdc/attachment.html>
Filip Pizlo
2014-09-28 05:53:59 UTC
Permalink
I would also like to see this standardized. Comments inline.
Post by John Lenz
* the "stack" property (a string)
* when the stack property is attached (at Error object creation or at throw)
* what happens when Error object that has been thrown, is thrown again (nothing)
* the stack trace in the face of tail recursion optimizations (skipped?)
Is that really necessary? If so, can you say something about the motivation?

You can do some tail recursion optimizations while preserving the stack trace. For example if you call yourself recursively and the JIT turns it into a loop, then all you need is the loop trip count to recover the original stack trace.
Post by John Lenz
* the minimal information that a stack trace should contain (file, line, column)
* the format of the minimal information
* how additional information is added to the stack trace (named evals, etc)
Does this sound like a reasonable minimal set?
+1
Post by John Lenz
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
John Lenz
2014-09-29 14:55:30 UTC
Permalink
Post by Filip Pizlo
I would also like to see this standardized. Comments inline.
Post by John Lenz
I would like to get see stack traces standardized for ES7, to that end,
I would like to define a minimal set of behaviors that would need to be
Post by John Lenz
* the "stack" property (a string)
* when the stack property is attached (at Error object creation or at
throw)
Post by John Lenz
* what happens when Error object that has been thrown, is thrown again
(nothing)
Post by John Lenz
* the stack trace in the face of tail recursion optimizations (skipped?)
Is that really necessary? If so, can you say something about the motivation?
You can do some tail recursion optimizations while preserving the stack
trace. For example if you call yourself recursively and the JIT turns it
into a loop, then all you need is the loop trip count to recover the
original stack trace.
I really have no idea what the behavior should be in the faces of optimized
tail calls (which is must broader than simply self recursive methods that
can be rewritten as a loop). I've seen various suggestions (a capped call
history) but I'm curious how efficient functional languages deal with this.


I haven't actually seen anything about tail recursion optimizations being
implemented, have any of the VM actually tried or committed to implementing
tail call optimizations?
Post by Filip Pizlo
Post by John Lenz
* the minimal information that a stack trace should contain (file, line,
column)
Post by John Lenz
* the format of the minimal information
* how additional information is added to the stack trace (named evals,
etc)
Post by John Lenz
Does this sound like a reasonable minimal set?
+1
Post by John Lenz
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/b86b3737/attachment-0001.html>
Filip Pizlo
2014-09-29 16:06:26 UTC
Permalink
Post by Filip Pizlo
I would also like to see this standardized. Comments inline.
Post by John Lenz
* the "stack" property (a string)
* when the stack property is attached (at Error object creation or at throw)
* what happens when Error object that has been thrown, is thrown again (nothing)
* the stack trace in the face of tail recursion optimizations (skipped?)
Is that really necessary? If so, can you say something about the motivation?
You can do some tail recursion optimizations while preserving the stack trace. For example if you call yourself recursively and the JIT turns it into a loop, then all you need is the loop trip count to recover the original stack trace.
I really have no idea what the behavior should be in the faces of optimized tail calls (which is must broader than simply self recursive methods that can be rewritten as a loop). I've seen various suggestions (a capped call history) but I'm curious how efficient functional languages deal with this.
The last time I used ML, which was admittedly a long time ago, the two main implementations (MLton and SML/NJ) simply didn?t have stack traces.
Post by Filip Pizlo
I haven't actually seen anything about tail recursion optimizations being implemented, have any of the VM actually tried or committed to implementing tail call optimizations?
We (JSC) haven?t. And we don?t plan to, because:

- We still need to be able to reconstruct the original stack for things like function.caller and function.arguments. We are trying to remove the latter but the former still lives.

- Debugging. Our inspector UI promises stack traces for breakpoints and whenever exceptions are thrown. We could make tail call optimizations work only when the inspector is not attached, but this would be weird. Tail call optimizations end up being a kind of semantic guarantee, since if they work you can write loops using tail calls. It would be weird if attaching the inspector suddenly made all of your tail calls turn into stack overflows. It?s actually better if the risk of stack overflow is equal regardless of whether the inspector is attached.

- JS is a great language; it actually lets you write an honest loop. You don?t *need* tail calls.

-Filip
Post by Filip Pizlo
Post by John Lenz
* the minimal information that a stack trace should contain (file, line, column)
* the format of the minimal information
* how additional information is added to the stack trace (named evals, etc)
Does this sound like a reasonable minimal set?
+1
Post by John Lenz
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
https://mail.mozilla.org/listinfo/es-discuss <https://mail.mozilla.org/listinfo/es-discuss>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/84476fd7/attachment.html>
Andreas Rossberg
2014-09-29 16:10:43 UTC
Permalink
Post by Filip Pizlo
- JS is a great language; it actually lets you write an honest loop. You
don?t *need* tail calls.
Let me repeat what I just wrote in my previous mail: "I think not
enough people appreciate the (substantial) difference between general
TCO and mere tail recursion." ;)

/Andreas
Mark S. Miller
2014-09-29 16:23:47 UTC
Permalink
On Mon, Sep 29, 2014 at 12:06 PM, Filip Pizlo <fpizlo at apple.com> wrote:
[...]
Post by John Lenz
I haven't actually seen anything about tail recursion optimizations being
implemented, have any of the VM actually tried or committed to implementing
tail call optimizations?
- We still need to be able to reconstruct the original stack for things
like function.caller and function.arguments. We are trying to remove the
latter but the former still lives.
First, kudos on trying to remove function.arguments. It would be awesome to
see this gone, and I greatly appreciate that you/JSC are willing to test
the waters.

Although we would both like to see function.caller gone as well, we are
also both much more skeptical that this is possible. Let's assume that it
is not. The conclusion that follows is only that sloppy calls to sloppy
functions can't be TCOed away. That is in any case what we've been
assuming. That's why, IIRC (haven't checked lately), TCO is only specified
for calls from non-sloppy functions.

[...]
--
Cheers,
--MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/65544744/attachment.html>
Brendan Eich
2014-09-29 17:25:40 UTC
Permalink
That's why, IIRC (haven't checked lately), TCO is only specified for
calls from non-sloppy functions.
PTC (Proper Tail Calls), not TCO. It's confusing to equate the two, from
what I know (corrections welcome0.

To add to confusion, ES6 drafts say "Tail Position Calls" (TPC). Is this
story reminidng anyone of the origin of the "UTC" acronym?

Anyway, Mark: you recall correctly: see 14.6.1 step 2 under

http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tail-position-calls

Fil, this is normative draft spec for ES6, observable asymptotic space
performance. Not optional at implementor's discretion. :-P

/be
Filip Pizlo
2014-09-29 17:34:02 UTC
Permalink
That's why, IIRC (haven't checked lately), TCO is only specified for calls from non-sloppy functions.
PTC (Proper Tail Calls), not TCO. It's confusing to equate the two, from what I know (corrections welcome0.
To add to confusion, ES6 drafts say "Tail Position Calls" (TPC). Is this story reminidng anyone of the origin of the "UTC" acronym?
Anyway, Mark: you recall correctly: see 14.6.1 step 2 under
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tail-position-calls
Fil, this is normative draft spec for ES6, observable asymptotic space performance. Not optional at implementor's discretion. :-P
Bummer.

-Filip
/be
Andreas Rossberg
2014-09-30 10:56:50 UTC
Permalink
Post by Brendan Eich
That's why, IIRC (haven't checked lately), TCO is only specified for calls
from non-sloppy functions.
PTC (Proper Tail Calls), not TCO. It's confusing to equate the two, from
what I know (corrections welcome0.
Hm, people most often refer to "mandatory tail call
optimisation/elimination" when talking about a spec level requirement.
I have never seen "PTC" used in a formal context, let alone the
acronym.

/Andreas
Sam Tobin-Hochstadt
2014-09-30 14:31:35 UTC
Permalink
Post by Andreas Rossberg
Post by Brendan Eich
That's why, IIRC (haven't checked lately), TCO is only specified for calls
from non-sloppy functions.
PTC (Proper Tail Calls), not TCO. It's confusing to equate the two, from
what I know (corrections welcome0.
Hm, people most often refer to "mandatory tail call
optimisation/elimination" when talking about a spec level requirement.
I have never seen "PTC" used in a formal context, let alone the
acronym.
Clinger's paper, which formalizes the concept, calls it "proper tail
recursion" in the title, as does the R5RS Scheme standard. Since
recursion isn't fundamental, though, proper tail calls seems more
accurate. This terminology is used lots of places these days, such as
the Lua docs and this (archive of a) post by Guy Steele:
http://www.eighty-twenty.org/index.cgi/tech/oo-tail-calls-20111001.html

Sam
Andreas Rossberg
2014-09-30 14:37:56 UTC
Permalink
Post by Sam Tobin-Hochstadt
Post by Andreas Rossberg
Post by Brendan Eich
That's why, IIRC (haven't checked lately), TCO is only specified for calls
from non-sloppy functions.
PTC (Proper Tail Calls), not TCO. It's confusing to equate the two, from
what I know (corrections welcome0.
Hm, people most often refer to "mandatory tail call
optimisation/elimination" when talking about a spec level requirement.
I have never seen "PTC" used in a formal context, let alone the
acronym.
Clinger's paper, which formalizes the concept, calls it "proper tail
recursion" in the title, as does the R5RS Scheme standard. Since
recursion isn't fundamental, though, proper tail calls seems more
accurate. This terminology is used lots of places these days, such as
http://www.eighty-twenty.org/index.cgi/tech/oo-tail-calls-20111001.html
Interesting, good to know. Thanks for the clarification.

(Still wondering what improper tail calls would be.)

/Andreas
Filip Pizlo
2014-09-29 17:43:06 UTC
Permalink
[...]
Post by Filip Pizlo
Post by Filip Pizlo
I haven't actually seen anything about tail recursion optimizations being implemented, have any of the VM actually tried or committed to implementing tail call optimizations?
- We still need to be able to reconstruct the original stack for things like function.caller and function.arguments. We are trying to remove the latter but the former still lives.
First, kudos on trying to remove function.arguments. It would be awesome to see this gone, and I greatly appreciate that you/JSC are willing to test the waters.
Although we would both like to see function.caller gone as well, we are also both much more skeptical that this is possible. Let's assume that it is not. The conclusion that follows is only that sloppy calls to sloppy functions can't be TCOed away. That is in any case what we've been assuming. That's why, IIRC (haven't checked lately), TCO is only specified for calls from non-sloppy functions.
I agree! Thanks for the explanation. :-)

-Filip
[...]
--
Cheers,
--MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/38a93e32/attachment-0001.html>
Allen Wirfs-Brock
2014-09-29 17:44:09 UTC
Permalink
Although we would both like to see function.caller gone as well, we are also both much more skeptical that this is possible. Let's assume that it is not. The conclusion that follows is only that sloppy calls to sloppy functions can't be TCOed away. That is in any case what we've been assuming. That's why, IIRC (haven't checked lately), TCO is only specified for calls from non-sloppy functions.
Actually, TCO is only specified for calls from strict mode ECMAScript functions.

The only place the distinction between strict and non-sloppy is really significant is WRT built-in functions. Standard built-ins are allowed to be implemented either as strict ECMAScript functions or in some implementation defined manner (ie, using some other programming language). If the latter is the case, we don't really have any say over their internal call semantics, etc.

Allen
Mark S. Miller
2014-09-29 18:00:21 UTC
Permalink
Agreed. TCO or PTC specified only for strict mode functions, not for all
non-sloppy functions.

Would be nice to extend this at least to bound functions resulting from
binding a strict function, but too late to consider for ES6. In any case,
all such TCO extensions can compatibly happen later.



On Mon, Sep 29, 2014 at 1:44 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>
Post by Mark S. Miller
Post by Mark S. Miller
Although we would both like to see function.caller gone as well, we are
also both much more skeptical that this is possible. Let's assume that it
is not. The conclusion that follows is only that sloppy calls to sloppy
functions can't be TCOed away. That is in any case what we've been
assuming. That's why, IIRC (haven't checked lately), TCO is only specified
for calls from non-sloppy functions.
Actually, TCO is only specified for calls from strict mode ECMAScript functions.
The only place the distinction between strict and non-sloppy is really
significant is WRT built-in functions. Standard built-ins are allowed to
be implemented either as strict ECMAScript functions or in some
implementation defined manner (ie, using some other programming language).
If the latter is the case, we don't really have any say over their
internal call semantics, etc.
Allen
--
Cheers,
--MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/9fb330e6/attachment.html>
Allen Wirfs-Brock
2014-09-29 18:06:15 UTC
Permalink
Agreed. TCO or PTC specified only for strict mode functions, not for all non-sloppy functions.
Would be nice to extend this at least to bound functions resulting from binding a strict function, but too late to consider for ES6. In any case, all such TCO extensions can compatibly happen later.
Bound functions don't have bodies, and hence don't directly make ECMAScript function calls. All they do is delegate their [[Call]] behavior to the target function's [[Call]]. No particular reason an implementation can't optimize through that if they want to.

Allen
Brendan Eich
2014-09-29 19:02:04 UTC
Permalink
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).

/be
Mark Miller
2014-09-29 19:16:17 UTC
Permalink
Yes, I believe that we should consider some non-strict non-sloppy
functions, such as .bind()ings of strict functions, to also normatively
have some TCO/PTC requirements. However, it is too late to consider such
for ES6 and we can always extend such TCO/PTC requirements to more cases
later.
Post by Brendan Eich
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
--
Cheers,
--MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/984434d7/attachment.html>
Allen Wirfs-Brock
2014-09-29 20:02:47 UTC
Permalink
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable asymptotic space performance (I keep saying :-P).
/be
What should be normative? You guys probably should probably review the actual spec. language and see if you have any issues with it. All the tail call action takes place in the spec. on the caller side. See http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-evaluatecall and http://people.mozilla.org/~jorendorff/es6-draft.html#sec-preparefortailcall

The resources requirements of a function are represented by its "execution context". PrepareForTailCall says the the caller's "execution context" is discarded before invoking the callee's [[call]] internal method. [[Call]] for bound functions does not create a new "execution context" so there is no associated specified resource consumption that needs to be optimized away. At least as far as the spec. is concerned, bound functions (whether strict or sloppy) have no impact on TCO.

I can't imagine what you would want be to try to say about non-EMCAScript functions. Their internal "call" semantics is determined by the semantics of their implementation language.

Allen


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/b5ac6bc5/attachment.html>
Mark S. Miller
2014-09-29 20:13:17 UTC
Permalink
The issue is the asymptotic space consumption almost-contract. The reason I
say "almost" is that conformance of an implementation is not testable.
Currently, the spec says nothing about when an implementation might run out
of storage.

So we (at least I) mean normative only in the following sense: When someone
writes an algorithm in ES6 using, say, bound functions in a loop, what
claims may they validly make about the space complexity of their program?
The specification should help answer such questions, sometimes.

Note that I distinguish here between "the space complexity of their
program" and the space usage growth when their program is run on an actual
implementation. Again, conformance with any requirement on the latter is
not testable.


On Mon, Sep 29, 2014 at 1:02 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
What should be normative? You guys probably should probably review the
actual spec. language and see if you have any issues with it. All the tail
call action takes place in the spec. on the caller side. See
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-evaluatecall
and
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-preparefortailcall
The resources requirements of a function are represented by its "execution
context". PrepareForTailCall says the the caller's "execution context" is
discarded before invoking the callee's [[call]] internal method. [[Call]]
for bound functions does not create a new "execution context" so there is
no associated specified resource consumption that needs to be optimized
away. At least as far as the spec. is concerned, bound functions (whether
strict or sloppy) have no impact on TCO.
I can't imagine what you would want be to try to say about non-EMCAScript
functions. Their internal "call" semantics is determined by the semantics
of their implementation language.
Allen
--
Cheers,
--MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/a6e385d4/attachment-0001.html>
Sam Tobin-Hochstadt
2014-09-29 20:16:28 UTC
Permalink
Post by Mark S. Miller
The issue is the asymptotic space consumption almost-contract. The reason I
say "almost" is that conformance of an implementation is not testable.
Currently, the spec says nothing about when an implementation might run out
of storage.
So we (at least I) mean normative only in the following sense: When someone
writes an algorithm in ES6 using, say, bound functions in a loop, what
claims may they validly make about the space complexity of their program?
The specification should help answer such questions, sometimes.
Note that I distinguish here between "the space complexity of their program"
and the space usage growth when their program is run on an actual
implementation. Again, conformance with any requirement on the latter is not
testable.
I think we can make it testable.

We'd consider it a spec violation (at least, I would), if this program
ran out of space, ever:

var i = 0;
while (1) { i++; };

similarly, this program should never run out of space:

var i = 0;
function f() { i++; return f(); }
f();

If we write a test that checks counting to a specified number, I think
test262 can adequately test this behavior.

Sam
Post by Mark S. Miller
On Mon, Sep 29, 2014 at 1:02 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
What should be normative? You guys probably should probably review the
actual spec. language and see if you have any issues with it. All the tail
call action takes place in the spec. on the caller side. See
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-evaluatecall
and
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-preparefortailcall
The resources requirements of a function are represented by its "execution
context". PrepareForTailCall says the the caller's "execution context" is
discarded before invoking the callee's [[call]] internal method. [[Call]]
for bound functions does not create a new "execution context" so there is no
associated specified resource consumption that needs to be optimized away.
At least as far as the spec. is concerned, bound functions (whether strict
or sloppy) have no impact on TCO.
I can't imagine what you would want be to try to say about non-EMCAScript
functions. Their internal "call" semantics is determined by the semantics of
their implementation language.
Allen
--
Cheers,
--MarkM
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
Mark S. Miller
2014-09-29 20:18:58 UTC
Permalink
Practically speaking, I agree.

On Mon, Sep 29, 2014 at 1:16 PM, Sam Tobin-Hochstadt <samth at cs.indiana.edu>
Post by Mark S. Miller
Post by Mark S. Miller
The issue is the asymptotic space consumption almost-contract. The
reason I
Post by Mark S. Miller
say "almost" is that conformance of an implementation is not testable.
Currently, the spec says nothing about when an implementation might run
out
Post by Mark S. Miller
of storage.
So we (at least I) mean normative only in the following sense: When
someone
Post by Mark S. Miller
writes an algorithm in ES6 using, say, bound functions in a loop, what
claims may they validly make about the space complexity of their program?
The specification should help answer such questions, sometimes.
Note that I distinguish here between "the space complexity of their
program"
Post by Mark S. Miller
and the space usage growth when their program is run on an actual
implementation. Again, conformance with any requirement on the latter is
not
Post by Mark S. Miller
testable.
I think we can make it testable.
We'd consider it a spec violation (at least, I would), if this program
var i = 0;
while (1) { i++; };
var i = 0;
function f() { i++; return f(); }
f();
If we write a test that checks counting to a specified number, I think
test262 can adequately test this behavior.
Sam
Post by Mark S. Miller
On Mon, Sep 29, 2014 at 1:02 PM, Allen Wirfs-Brock <
allen at wirfs-brock.com>
Post by Mark S. Miller
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if
they
Post by Mark S. Miller
Post by Allen Wirfs-Brock
want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
What should be normative? You guys probably should probably review the
actual spec. language and see if you have any issues with it. All the
tail
Post by Mark S. Miller
Post by Allen Wirfs-Brock
call action takes place in the spec. on the caller side. See
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-evaluatecall
Post by Mark S. Miller
Post by Allen Wirfs-Brock
and
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-preparefortailcall
Post by Mark S. Miller
Post by Allen Wirfs-Brock
The resources requirements of a function are represented by its
"execution
Post by Mark S. Miller
Post by Allen Wirfs-Brock
context". PrepareForTailCall says the the caller's "execution context"
is
Post by Mark S. Miller
Post by Allen Wirfs-Brock
discarded before invoking the callee's [[call]] internal method.
[[Call]]
Post by Mark S. Miller
Post by Allen Wirfs-Brock
for bound functions does not create a new "execution context" so there
is no
Post by Mark S. Miller
Post by Allen Wirfs-Brock
associated specified resource consumption that needs to be optimized
away.
Post by Mark S. Miller
Post by Allen Wirfs-Brock
At least as far as the spec. is concerned, bound functions (whether
strict
Post by Mark S. Miller
Post by Allen Wirfs-Brock
or sloppy) have no impact on TCO.
I can't imagine what you would want be to try to say about
non-EMCAScript
Post by Mark S. Miller
Post by Allen Wirfs-Brock
functions. Their internal "call" semantics is determined by the
semantics of
Post by Mark S. Miller
Post by Allen Wirfs-Brock
their implementation language.
Allen
--
Cheers,
--MarkM
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
--
Cheers,
--MarkM
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/5e813f34/attachment-0001.html>
Filip Pizlo
2014-09-29 20:19:07 UTC
Permalink
Another way to make this (somewhat) testable is to require specific error.stack behavior for TCO. For example, a call in tail position may require that the caller does not show up in the stack trace.

-Filip
Post by Sam Tobin-Hochstadt
Post by Mark S. Miller
The issue is the asymptotic space consumption almost-contract. The reason I
say "almost" is that conformance of an implementation is not testable.
Currently, the spec says nothing about when an implementation might run out
of storage.
So we (at least I) mean normative only in the following sense: When someone
writes an algorithm in ES6 using, say, bound functions in a loop, what
claims may they validly make about the space complexity of their program?
The specification should help answer such questions, sometimes.
Note that I distinguish here between "the space complexity of their program"
and the space usage growth when their program is run on an actual
implementation. Again, conformance with any requirement on the latter is not
testable.
I think we can make it testable.
We'd consider it a spec violation (at least, I would), if this program
var i = 0;
while (1) { i++; };
var i = 0;
function f() { i++; return f(); }
f();
If we write a test that checks counting to a specified number, I think
test262 can adequately test this behavior.
Sam
Post by Mark S. Miller
On Mon, Sep 29, 2014 at 1:02 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
What should be normative? You guys probably should probably review the
actual spec. language and see if you have any issues with it. All the tail
call action takes place in the spec. on the caller side. See
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-evaluatecall
and
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-preparefortailcall
The resources requirements of a function are represented by its "execution
context". PrepareForTailCall says the the caller's "execution context" is
discarded before invoking the callee's [[call]] internal method. [[Call]]
for bound functions does not create a new "execution context" so there is no
associated specified resource consumption that needs to be optimized away.
At least as far as the spec. is concerned, bound functions (whether strict
or sloppy) have no impact on TCO.
I can't imagine what you would want be to try to say about non-EMCAScript
functions. Their internal "call" semantics is determined by the semantics of
their implementation language.
Allen
--
Cheers,
--MarkM
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
https://mail.mozilla.org/listinfo/es-discuss <https://mail.mozilla.org/listinfo/es-discuss>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/fc020181/attachment-0001.html>
Sam Tobin-Hochstadt
2014-09-29 20:26:38 UTC
Permalink
I think this would be a mistake -- as I mentioned, there are a number
of possible strategies for stack traces w/ proper tail calls, and as
Steve Fink mentioned, these also arise when considering inlining and
other optimizations. We shouldn't prevent implementations from trying
to experiment with what works best here.

Sam
Post by Filip Pizlo
Another way to make this (somewhat) testable is to require specific
error.stack behavior for TCO. For example, a call in tail position may
require that the caller does not show up in the stack trace.
-Filip
The issue is the asymptotic space consumption almost-contract. The reason I
say "almost" is that conformance of an implementation is not testable.
Currently, the spec says nothing about when an implementation might run out
of storage.
So we (at least I) mean normative only in the following sense: When someone
writes an algorithm in ES6 using, say, bound functions in a loop, what
claims may they validly make about the space complexity of their program?
The specification should help answer such questions, sometimes.
Note that I distinguish here between "the space complexity of their program"
and the space usage growth when their program is run on an actual
implementation. Again, conformance with any requirement on the latter is not
testable.
I think we can make it testable.
We'd consider it a spec violation (at least, I would), if this program
var i = 0;
while (1) { i++; };
var i = 0;
function f() { i++; return f(); }
f();
If we write a test that checks counting to a specified number, I think
test262 can adequately test this behavior.
Sam
On Mon, Sep 29, 2014 at 1:02 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
What should be normative? You guys probably should probably review the
actual spec. language and see if you have any issues with it. All the tail
call action takes place in the spec. on the caller side. See
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-evaluatecall
and
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-preparefortailcall
The resources requirements of a function are represented by its "execution
context". PrepareForTailCall says the the caller's "execution context" is
discarded before invoking the callee's [[call]] internal method. [[Call]]
for bound functions does not create a new "execution context" so there is no
associated specified resource consumption that needs to be optimized away.
At least as far as the spec. is concerned, bound functions (whether strict
or sloppy) have no impact on TCO.
I can't imagine what you would want be to try to say about non-EMCAScript
functions. Their internal "call" semantics is determined by the semantics of
their implementation language.
Allen
--
Cheers,
--MarkM
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
Filip Pizlo
2014-09-29 20:57:02 UTC
Permalink
Post by Sam Tobin-Hochstadt
I think this would be a mistake -- as I mentioned, there are a number
of possible strategies for stack traces w/ proper tail calls,
But we should spec one of them, particularly if we want to move towards returning the stack trace as structured data. I think it would be good for implementations to be consistent and for the stack trace to not vary depending on which optimization tier you ended up in.
Post by Sam Tobin-Hochstadt
and as
Steve Fink mentioned, these also arise when considering inlining and
other optimizations.
Nope. Inlining and other optimization a don't typically wreak the havoc on stack traces that TCO does.
Post by Sam Tobin-Hochstadt
We shouldn't prevent implementations from trying
to experiment with what works best here.
Is there something concrete that it would prevent anyone from trying?
Post by Sam Tobin-Hochstadt
Sam
Post by Filip Pizlo
Another way to make this (somewhat) testable is to require specific
error.stack behavior for TCO. For example, a call in tail position may
require that the caller does not show up in the stack trace.
-Filip
The issue is the asymptotic space consumption almost-contract. The reason I
say "almost" is that conformance of an implementation is not testable.
Currently, the spec says nothing about when an implementation might run out
of storage.
So we (at least I) mean normative only in the following sense: When someone
writes an algorithm in ES6 using, say, bound functions in a loop, what
claims may they validly make about the space complexity of their program?
The specification should help answer such questions, sometimes.
Note that I distinguish here between "the space complexity of their program"
and the space usage growth when their program is run on an actual
implementation. Again, conformance with any requirement on the latter is not
testable.
I think we can make it testable.
We'd consider it a spec violation (at least, I would), if this program
var i = 0;
while (1) { i++; };
var i = 0;
function f() { i++; return f(); }
f();
If we write a test that checks counting to a specified number, I think
test262 can adequately test this behavior.
Sam
On Mon, Sep 29, 2014 at 1:02 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
What should be normative? You guys probably should probably review the
actual spec. language and see if you have any issues with it. All the tail
call action takes place in the spec. on the caller side. See
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-evaluatecall
and
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-preparefortailcall
The resources requirements of a function are represented by its "execution
context". PrepareForTailCall says the the caller's "execution context" is
discarded before invoking the callee's [[call]] internal method. [[Call]]
for bound functions does not create a new "execution context" so there is no
associated specified resource consumption that needs to be optimized away.
At least as far as the spec. is concerned, bound functions (whether strict
or sloppy) have no impact on TCO.
I can't imagine what you would want be to try to say about non-EMCAScript
functions. Their internal "call" semantics is determined by the semantics of
their implementation language.
Allen
--
Cheers,
--MarkM
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
Sam Tobin-Hochstadt
2014-09-29 21:05:23 UTC
Permalink
Post by Filip Pizlo
Post by Sam Tobin-Hochstadt
I think this would be a mistake -- as I mentioned, there are a number
of possible strategies for stack traces w/ proper tail calls,
But we should spec one of them, particularly if we want to move towards returning the stack trace as structured data. I think it would be good for implementations to be consistent and for the stack trace to not vary depending on which optimization tier you ended up in.
Post by Sam Tobin-Hochstadt
and as
Steve Fink mentioned, these also arise when considering inlining and
other optimizations.
Nope. Inlining and other optimization a don't typically wreak the havoc on stack traces that TCO does.
A lot of time spent staring at C stack frames where calls have been
inlined away disagrees.
Post by Filip Pizlo
Post by Sam Tobin-Hochstadt
We shouldn't prevent implementations from trying
to experiment with what works best here.
Is there something concrete that it would prevent anyone from trying?
If we mandate that we get exactly the same stack frames from every
implementation, which is what you are suggesting, then that would
prevent (some forms of) experimentation. Especially experimentation
that would produce _better_ stack traces than what you suggest
mandating.

Sam
Post by Filip Pizlo
Post by Sam Tobin-Hochstadt
Sam
Post by Filip Pizlo
Another way to make this (somewhat) testable is to require specific
error.stack behavior for TCO. For example, a call in tail position may
require that the caller does not show up in the stack trace.
-Filip
The issue is the asymptotic space consumption almost-contract. The reason I
say "almost" is that conformance of an implementation is not testable.
Currently, the spec says nothing about when an implementation might run out
of storage.
So we (at least I) mean normative only in the following sense: When someone
writes an algorithm in ES6 using, say, bound functions in a loop, what
claims may they validly make about the space complexity of their program?
The specification should help answer such questions, sometimes.
Note that I distinguish here between "the space complexity of their program"
and the space usage growth when their program is run on an actual
implementation. Again, conformance with any requirement on the latter is not
testable.
I think we can make it testable.
We'd consider it a spec violation (at least, I would), if this program
var i = 0;
while (1) { i++; };
var i = 0;
function f() { i++; return f(); }
f();
If we write a test that checks counting to a specified number, I think
test262 can adequately test this behavior.
Sam
On Mon, Sep 29, 2014 at 1:02 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
What should be normative? You guys probably should probably review the
actual spec. language and see if you have any issues with it. All the tail
call action takes place in the spec. on the caller side. See
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-evaluatecall
and
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-preparefortailcall
The resources requirements of a function are represented by its "execution
context". PrepareForTailCall says the the caller's "execution context" is
discarded before invoking the callee's [[call]] internal method. [[Call]]
for bound functions does not create a new "execution context" so there is no
associated specified resource consumption that needs to be optimized away.
At least as far as the spec. is concerned, bound functions (whether strict
or sloppy) have no impact on TCO.
I can't imagine what you would want be to try to say about non-EMCAScript
functions. Their internal "call" semantics is determined by the semantics of
their implementation language.
Allen
--
Cheers,
--MarkM
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
Filip Pizlo
2014-09-29 21:38:24 UTC
Permalink
Post by Sam Tobin-Hochstadt
Post by Filip Pizlo
Post by Sam Tobin-Hochstadt
I think this would be a mistake -- as I mentioned, there are a number
of possible strategies for stack traces w/ proper tail calls,
But we should spec one of them, particularly if we want to move towards returning the stack trace as structured data. I think it would be good for implementations to be consistent and for the stack trace to not vary depending on which optimization tier you ended up in.
Post by Sam Tobin-Hochstadt
and as
Steve Fink mentioned, these also arise when considering inlining and
other optimizations.
Nope. Inlining and other optimization a don't typically wreak the havoc on stack traces that TCO does.
A lot of time spent staring at C stack frames where calls have been
inlined away disagrees.
Ugh, that?s so irrelevant! ;-)

C compilers internally know what they inlined and where, but have trouble communicating this information to the debugger because the de facto standard debug data formats are old and messy. I have vague memories of DWARF making this particularly hard. Personally I?ve seen a stigma in the C compiler community against having compilers produce high-fidelity debug data at any optimization level other than -O0, so I suspect that the reason why this hasn?t been fixed is just that nobody really wants to do it. For example the top priority in LLVM?s debug support, last I checked, was to make it as compact as possible because of the dangers of space explosion in the case of C++, templates, and LTO. Seriously, the reasons for why C gets this wrong are completely irrelevant to this discussion. So this is a red herring. An ES VM can internally choose whatever format it wants for remembering inlining metadata, it never has to worry about interoperating with zillions of versions of gdb and lldb, and thankfully ES hasn?t own-goaled itself with anything like C++ templates (yet? ;-)).

Let?s look at some examples of runtimes that are more relevant to ES. Java VMs have for over a decade now performed aggressive inlining without ever forgetting about any frames (in fact they are almost spec-required to remember all frames because of how the runtime APIs work). The closest thing to ?forgetting? a frame was in the old IBM JVM (the one before J9); all they would forget was the line numbers in functions that were inlined but the fact that they inlined them was still remembered.

I?m not aware of a major JS implementation forgetting an inlined stack frame.
Post by Sam Tobin-Hochstadt
Post by Filip Pizlo
Post by Sam Tobin-Hochstadt
We shouldn't prevent implementations from trying
to experiment with what works best here.
Is there something concrete that it would prevent anyone from trying?
If we mandate that we get exactly the same stack frames from every
implementation, which is what you are suggesting, then that would
prevent (some forms of) experimentation. Especially experimentation
that would produce _better_ stack traces than what you suggest
mandating.
Such is life when you spec a language. You have to sometimes spec something in a way that might in the future disagree with someone?s experiment.

-Filip
Post by Sam Tobin-Hochstadt
Sam
Post by Filip Pizlo
Post by Sam Tobin-Hochstadt
Sam
Post by Filip Pizlo
Another way to make this (somewhat) testable is to require specific
error.stack behavior for TCO. For example, a call in tail position may
require that the caller does not show up in the stack trace.
-Filip
The issue is the asymptotic space consumption almost-contract. The reason I
say "almost" is that conformance of an implementation is not testable.
Currently, the spec says nothing about when an implementation might run out
of storage.
So we (at least I) mean normative only in the following sense: When someone
writes an algorithm in ES6 using, say, bound functions in a loop, what
claims may they validly make about the space complexity of their program?
The specification should help answer such questions, sometimes.
Note that I distinguish here between "the space complexity of their program"
and the space usage growth when their program is run on an actual
implementation. Again, conformance with any requirement on the latter is not
testable.
I think we can make it testable.
We'd consider it a spec violation (at least, I would), if this program
var i = 0;
while (1) { i++; };
var i = 0;
function f() { i++; return f(); }
f();
If we write a test that checks counting to a specified number, I think
test262 can adequately test this behavior.
Sam
On Mon, Sep 29, 2014 at 1:02 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
What should be normative? You guys probably should probably review the
actual spec. language and see if you have any issues with it. All the tail
call action takes place in the spec. on the caller side. See
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-evaluatecall
and
http://people.mozilla.org/~jorendorff/es6-draft.html#sec-preparefortailcall
The resources requirements of a function are represented by its "execution
context". PrepareForTailCall says the the caller's "execution context" is
discarded before invoking the callee's [[call]] internal method. [[Call]]
for bound functions does not create a new "execution context" so there is no
associated specified resource consumption that needs to be optimized away.
At least as far as the spec. is concerned, bound functions (whether strict
or sloppy) have no impact on TCO.
I can't imagine what you would want be to try to say about non-EMCAScript
functions. Their internal "call" semantics is determined by the semantics of
their implementation language.
Allen
--
Cheers,
--MarkM
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/579003c2/attachment-0001.html>
Boris Zbarsky
2014-09-30 01:47:56 UTC
Permalink
Post by Sam Tobin-Hochstadt
We'd consider it a spec violation (at least, I would), if this program
var i = 0;
while (1) { i++; };
How would you know whether it does? You can't tell whether your program
is terminated because it runs out of space or because the browser has
decided it's hung and killed it....

-Boris
Brendan Eich
2014-09-30 02:48:52 UTC
Permalink
Put it in a worker or node.js. The point Sam was making was based on Ecma-262, no browser watchdog required.

/be
Post by Sam Tobin-Hochstadt
We'd consider it a spec violation (at least, I would), if this program
var i = 0;
while (1) { i++; };
How would you know whether it does? You can't tell whether your program is terminated because it runs out of space or because the browser has decided it's hung and killed it....
-Boris
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
Andreas Rossberg
2014-09-30 10:59:56 UTC
Permalink
Boris' point seems to be -- and I agree -- that such a test would only
be a semi-decision procedure. I.e., it can only falsify, but not
validate the property for the test program.

/Andreas
Post by Brendan Eich
Put it in a worker or node.js. The point Sam was making was based on Ecma-262, no browser watchdog required.
/be
Post by Sam Tobin-Hochstadt
We'd consider it a spec violation (at least, I would), if this program
var i = 0;
while (1) { i++; };
How would you know whether it does? You can't tell whether your program is terminated because it runs out of space or because the browser has decided it's hung and killed it....
-Boris
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
Allen Wirfs-Brock
2014-09-29 20:44:26 UTC
Permalink
The issue is the asymptotic space consumption almost-contract. The reason I say "almost" is that conformance of an implementation is not testable. Currently, the spec says nothing about when an implementation might run out of storage.
So we (at least I) mean normative only in the following sense: When someone writes an algorithm in ES6 using, say, bound functions in a loop, what claims may they validly make about the space complexity of their program? The specification should help answer such questions, sometimes.
Note that I distinguish here between "the space complexity of their program" and the space usage growth when their program is run on an actual implementation. Again, conformance with any requirement on the latter is not testable.
So what would you like it to say that it doesn't already say?

Here is what it currently says:

14.6.3 Runtime Semantics: PrepareForTailCall ( )

The abstract operation PrepareForTailCall performs the following steps:

1 Let leafContext be the running execution context.
2 Suspend leafContext.
3 Pop leafContext from the execution context context stack. The execution context now on the top of the stack becomes the running execution context.
4 Assert: leafContext has no further use. It will never be activated as the running execution context.

A tail position call must either release any transient internal resources associated with the currently executing function execution context before invoking the target function or reuse those resources in support of the target function.

NOTE For example, a tail position call should only grow an implementation?s activation record stack by the amount that the size of the target function?s activation record exceeds the size of the calling function?s activation record. If the target function?s activation record is smaller, then the total size of the stack should decrease.
Jason Orendorff
2014-09-29 20:41:19 UTC
Permalink
On Mon, Sep 29, 2014 at 3:02 PM, Allen Wirfs-Brock
Post by Allen Wirfs-Brock
I can't imagine what you would want be to try to say about non-EMCAScript
functions. Their internal "call" semantics is determined by the semantics of
their implementation language.
Function.prototype.apply, Function.prototype.call, and Reflect.apply
currently call PrepareForTailCall. Is this a bug?

I can see that the current language in 14.6.3 PrepareForTailCall only
covers "tail position calls" and "resources associated with the
currently executing function execution context", but what's wrong with
copying that sentence into 19.2.3.3 and changing it to refer to "the
internal method call in the last step of the above algorithm" and
"resources associated with the current call to
Function.prototype.call"?

The spec constrains the behavior of builtins in all kinds of ways,
regardless of what language they're written in. I don't understand
what is special about stack space usage that makes it off-limits.

-j
Allen Wirfs-Brock
2014-09-29 21:06:46 UTC
Permalink
Post by Jason Orendorff
On Mon, Sep 29, 2014 at 3:02 PM, Allen Wirfs-Brock
Post by Allen Wirfs-Brock
I can't imagine what you would want be to try to say about non-EMCAScript
functions. Their internal "call" semantics is determined by the semantics of
their implementation language.
Function.prototype.apply, Function.prototype.call, and Reflect.apply
currently call PrepareForTailCall. Is this a bug?
No, I don't believe so. Built-ins (whether implemented in ES or native) are specified to have an "execution context". The PrepareForTailCall release that execution context for before performing a [[Call]]. It's working in the above functions just like it works from any other call site.

In other words, the spec. language says that these buil;t-ins functions explicitly end with an ECMAScript tail call.
Post by Jason Orendorff
I can see that the current language in 14.6.3 PrepareForTailCall only
covers "tail position calls" and "resources associated with the
currently executing function execution context", but what's wrong with
copying that sentence into 19.2.3.3 and changing it to refer to "the
internal method call in the last step of the above algorithm" and
"resources associated with the current call to
Function.prototype.call"?
The spec constrains the behavior of builtins in all kinds of ways,
regardless of what language they're written in. I don't understand
what is special about stack space usage that makes it off-limits.
I'm not sure what would be the point of duplicating the language. Since those functions use PrepareForTailCall, what is says applies to them.

Allen
Jason Orendorff
2014-09-29 22:37:54 UTC
Permalink
On Mon, Sep 29, 2014 at 4:06 PM, Allen Wirfs-Brock
Post by Allen Wirfs-Brock
Post by Jason Orendorff
Function.prototype.apply, Function.prototype.call, and Reflect.apply
currently call PrepareForTailCall. Is this a bug?
No, I don't believe so. Built-ins (whether implemented in ES or native) are specified to have an "execution context".
Oh, I see! Thanks. (This is specified in 9.3.1 [[Call]], for anyone
following along.)

But in this case, the spec already has some non-ECMAScript functions
performing tail calls, so now I am at a loss as to what your earlier
Post by Allen Wirfs-Brock
I can't imagine what you would want be to try to say about non-EMCAScript functions. Their internal "call" semantics is determined by the semantics of their implementation language.
It seems like to the full extent that the current draft manages to
constrain Function.prototype.call, it could constrain bound functions
too.

-j
Allen Wirfs-Brock
2014-09-29 23:24:30 UTC
Permalink
Post by Jason Orendorff
On Mon, Sep 29, 2014 at 4:06 PM, Allen Wirfs-Brock
Post by Allen Wirfs-Brock
Post by Jason Orendorff
Function.prototype.apply, Function.prototype.call, and Reflect.apply
currently call PrepareForTailCall. Is this a bug?
No, I don't believe so. Built-ins (whether implemented in ES or native) are specified to have an "execution context".
Oh, I see! Thanks. (This is specified in 9.3.1 [[Call]], for anyone
following along.)
But in this case, the spec already has some non-ECMAScript functions
performing tail calls, so now I am at a loss as to what your earlier
I guess we need to be a bit more careful about what kind of "call" we are talking about.

The ECMAScript spec. execution model uses a stack of "execution contexts" to tracks [[Call]]'s to and returns from function objects. [[Call]]'s to built-in functions are specified as creating an "execution context" so that, from a spec. perspective, both self-hosted and native implementations of built-ins can be treated uniformly within the spec.

The ES tail call resource rules are expressed in terms of manipulating the execution context stack, immediately prior to performing a [[Call]]. Or to put it another way, ES tail calls rules are only about [[Call]] operations. So, ES tail calls can occur in a built-in's that invoke [[Call]]. Generally this is possible if the built-in is specified to immediately return the [[Call]] result.

When I said we couldn't specify tail call behavior for non-ECMAScript functions, I think about the actual "call" semantics used by the implementation language. For example, if F.p.apply is implemented in C++ and if the last thing it does is a C++ call to another C++ function that is the [[Call]] implementation. I can't say anything about how C++ implements that C++ call.

However, from the ES perspective all the C++ execution state that is using to represent such an implementation of F.p.apply is just part of the ES execution context for the [[Call]] to F.p.apply. The C++ code could call thousands of levels deep before it performs its [[Call]] back to an ES function and from the ES perspective all of that C++ stack space is just part of the single F.p.apply execution context.

When we perform PrepareForTailCall in F.p.apply we are saying that the current ES execution context (the one that potentially includes that deep C++ call stack) must be discard (or mae available for reuse) before performing the the subsequent ES [[Call]]. How that is actually accomplished is an implementation "detail".

I strongly support full employment opportunities for language implementations hacker.
Post by Jason Orendorff
Post by Allen Wirfs-Brock
I can't imagine what you would want be to try to say about non-EMCAScript functions. Their internal "call" semantics is determined by the semantics of their implementation language.
It seems like to the full extent that the current draft manages to
constrain Function.prototype.call, it could constrain bound functions
too.
It does. The spec doesn't introduce an additional execution context between the [[Call]] of a bound function and the [[Call]] to the bound functions target. If the [[Call]] to the bound function is in tail position then the caller's execution context is discarded before the [[Call]] to the bound function.

Allen
Brendan Eich
2014-09-29 23:27:39 UTC
Permalink
Post by Allen Wirfs-Brock
Post by Brendan Eich
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about
observable asymptotic space performance (I keep saying :-P).
/be
What should be normative?
Something observable. I was picking on your "optimize".

Looks like Jason and others covered the rest of what I was gonna write
Post by Allen Wirfs-Brock
You guys probably should probably review the actual spec. language
and see if you have any issues with it.
I've read it, earlier today. You're hearing issues now. :-D

/be
John Lenz
2014-09-29 22:20:03 UTC
Permalink
What does TC39 expect with regard to PTC and the
standard-because-everyone-has-one "stack" property? Has any of the VMs
actually tried to implement PTC for JS?
Post by Brendan Eich
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/917fefd7/attachment.html>
John Lenz
2014-10-04 16:31:23 UTC
Permalink
Is ES6 "shipping" PTCs without implementer feedback? Or how have those that
tried dealt with stack traces?
Post by John Lenz
What does TC39 expect with regard to PTC and the
standard-because-everyone-has-one "stack" property? Has any of the VMs
actually tried to implement PTC for JS?
Post by Brendan Eich
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141004/7b715903/attachment.html>
Frankie Bagnardi
2014-10-10 18:47:30 UTC
Permalink
I think this is a great idea. I often use stack traces, especially in
node.js, for debug error messages and logging. This would make it much
simpler to work with them.

Also there are some libraries which end up with a lot of wrapped functions,
which could be omitted using an error cleaner function.

I suggest a stackTrace property (getter, no write) of Error objects:

- .frames is an array of stack frame metadata objects
- no concept of sourcemaps
- [[ToString]] is left implementation dependant, allowing them to add
information from sourcemaps, or otherwise customize it

This allows for a programmable api, and a human readable version. Also
devtools and other code applications (like Carl Smith's) can create rich
UIs for this data.

I'm sure the smart people at TC39 can come up with a good (or good enough)
way to represent PTCs.
Post by John Lenz
Is ES6 "shipping" PTCs without implementer feedback? Or how have those
that tried dealt with stack traces?
Post by John Lenz
What does TC39 expect with regard to PTC and the
standard-because-everyone-has-one "stack" property? Has any of the VMs
actually tried to implement PTC for JS?
Post by Brendan Eich
Post by Allen Wirfs-Brock
No particular reason an implementation can't optimize through that if they want to.
The question is whether it should be normative. PTC is about observable
asymptotic space performance (I keep saying :-P).
/be
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141010/a4c6ec1f/attachment-0001.html>
Andreas Rossberg
2014-09-29 16:09:22 UTC
Permalink
Post by John Lenz
Post by Filip Pizlo
Post by John Lenz
I would like to get see stack traces standardized for ES7, to that end,
I would like to define a minimal set of behaviors that would need to be
* the "stack" property (a string)
* when the stack property is attached (at Error object creation or at throw)
* what happens when Error object that has been thrown, is thrown again (nothing)
* the stack trace in the face of tail recursion optimizations (skipped?)
Is that really necessary? If so, can you say something about the motivation?
You can do some tail recursion optimizations while preserving the stack
trace. For example if you call yourself recursively and the JIT turns it
into a loop, then all you need is the loop trip count to recover the
original stack trace.
I really have no idea what the behavior should be in the faces of optimized
tail calls (which is must broader than simply self recursive methods that
can be rewritten as a loop). I've seen various suggestions (a capped call
history) but I'm curious how efficient functional languages deal with this.
Indeed, I think not enough people appreciate the (substantial)
difference between general TCO and tail recursion. If the language was
required to be able to construct stack traces then that would
effectively kill the benefit of TCO.

/Andreas
Sam Tobin-Hochstadt
2014-09-29 16:14:49 UTC
Permalink
Post by John Lenz
I really have no idea what the behavior should be in the faces of optimized
tail calls (which is must broader than simply self recursive methods that
can be rewritten as a loop). I've seen various suggestions (a capped call
history) but I'm curious how efficient functional languages deal with this.
Different functional languages do a variety of things here:

- simply show the current stack, without the functions that made tail
calls (this is probably the most common)
- have a bounded buffer for stack traces
- implement tail calls via a trampoline; this has the side-effect that
the stack has "recent" tail calls in it already

I'm sure there are other choices here that people have made.

Sam
Steve Fink
2014-09-29 19:19:22 UTC
Permalink
Post by Sam Tobin-Hochstadt
Post by John Lenz
I really have no idea what the behavior should be in the faces of optimized
tail calls (which is must broader than simply self recursive methods that
can be rewritten as a loop). I've seen various suggestions (a capped call
history) but I'm curious how efficient functional languages deal with this.
- simply show the current stack, without the functions that made tail
calls (this is probably the most common)
- have a bounded buffer for stack traces
- implement tail calls via a trampoline; this has the side-effect that
the stack has "recent" tail calls in it already
I'm sure there are other choices here that people have made.
"Stack traces" are really an overload of (at least?) 3 different concepts:

1. A record of how execution reached the current state. What debuggers
want, mostly.
2. The continuation from this point on - what function will be returned
to when the current function returns normally, recursively up the call
chain.
3. A description of the actual state of the stack.

In all of these, the semantics of the youngest frame are different from
all other frames in the stack trace.

For #2, thrown exceptions make the implied continuation ordering a lie,
or at least a little more nuanced. You sort of want to see what frames
will catch exceptions. (But that's not a trivial determination if you
have some "native" frames mixed in there, with arbitrary logic for
determining whether to catch or propagate an exception. Even JS frames
may re-throw.)

Inlined functions may cause gaps in #1 and #2, unless the implementation
takes pains to fill them in with dummy frames (in which case it's not
really #3 anymore.)

Unless the implementation plays games, tail calls can make #1 lie as
well. You really called f(), but it doesn't appear because its frame was
used for executing g() before pushing the remaining frames on your
stack. Tail calls don't really muck with #2 afaict.

All three meanings are legitimate things to want, and all of them
require some implementation effort. Even #3 is tricky with a JIT
involved. And I'm not even considering floating generator frames, which
may not fit into a linear structure at all. Or when users want "long
stacks" for callbacks, where the stack in effect when a callback was set
is relevant.
Filip Pizlo
2014-09-29 20:54:50 UTC
Permalink
Post by Steve Fink
Post by Sam Tobin-Hochstadt
Post by John Lenz
I really have no idea what the behavior should be in the faces of optimized
tail calls (which is must broader than simply self recursive methods that
can be rewritten as a loop). I've seen various suggestions (a capped call
history) but I'm curious how efficient functional languages deal with this.
- simply show the current stack, without the functions that made tail
calls (this is probably the most common)
- have a bounded buffer for stack traces
- implement tail calls via a trampoline; this has the side-effect that
the stack has "recent" tail calls in it already
I'm sure there are other choices here that people have made.
1. A record of how execution reached the current state. What debuggers
want, mostly.
2. The continuation from this point on - what function will be returned
to when the current function returns normally, recursively up the call
chain.
3. A description of the actual state of the stack.
In all of these, the semantics of the youngest frame are different from
all other frames in the stack trace.
For #2, thrown exceptions make the implied continuation ordering a lie,
or at least a little more nuanced. You sort of want to see what frames
will catch exceptions. (But that's not a trivial determination if you
have some "native" frames mixed in there, with arbitrary logic for
determining whether to catch or propagate an exception. Even JS frames
may re-throw.)
Inlined functions may cause gaps in #1 and #2, unless the implementation
takes pains to fill them in with dummy frames (in which case it's not
really #3 anymore.)
AFAICT, production compilers already take pains to ensure that they leave behind sufficient meta-data for the runtime to fill in the missing stack frames whenever inlining has happened. This is certainly true in JSC. Crucially, the infrastructure to do this is also needed for other random stuff and it imposes zero overhead.

So let's not compare this to inlining.

-Filip
Post by Steve Fink
Unless the implementation plays games, tail calls can make #1 lie as
well. You really called f(), but it doesn't appear because its frame was
used for executing g() before pushing the remaining frames on your
stack. Tail calls don't really muck with #2 afaict.
All three meanings are legitimate things to want, and all of them
require some implementation effort. Even #3 is tricky with a JIT
involved. And I'm not even considering floating generator frames, which
may not fit into a linear structure at all. Or when users want "long
stacks" for callbacks, where the stack in effect when a callback was set
is relevant.
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
John Lenz
2014-09-29 22:08:07 UTC
Permalink
Post by John Lenz
On Mon, Sep 29, 2014 at 10:55 AM, John Lenz <concavelenz at gmail.com>
Post by John Lenz
I really have no idea what the behavior should be in the faces of
optimized
Post by John Lenz
tail calls (which is must broader than simply self recursive methods
that
Post by John Lenz
can be rewritten as a loop). I've seen various suggestions (a capped
call
Post by John Lenz
history) but I'm curious how efficient functional languages deal with
this.
- simply show the current stack, without the functions that made tail
calls (this is probably the most common)
- have a bounded buffer for stack traces
- implement tail calls via a trampoline; this has the side-effect that
the stack has "recent" tail calls in it already
I'm sure there are other choices here that people have made.
1. A record of how execution reached the current state. What debuggers
want, mostly.
This is also important for server side reporting of client side error,
which while similar, is not the same as an optionally debugger activated.
Post by John Lenz
2. The continuation from this point on - what function will be returned
to when the current function returns normally, recursively up the call
chain.
3. A description of the actual state of the stack.
In all of these, the semantics of the youngest frame are different from
all other frames in the stack trace.
For #2, thrown exceptions make the implied continuation ordering a lie,
or at least a little more nuanced. You sort of want to see what frames
will catch exceptions. (But that's not a trivial determination if you
have some "native" frames mixed in there, with arbitrary logic for
determining whether to catch or propagate an exception. Even JS frames
may re-throw.)
Inlined functions may cause gaps in #1 and #2, unless the implementation
takes pains to fill them in with dummy frames (in which case it's not
really #3 anymore.)
Unless the implementation plays games, tail calls can make #1 lie as
well. You really called f(), but it doesn't appear because its frame was
used for executing g() before pushing the remaining frames on your
stack. Tail calls don't really muck with #2 afaict.
All three meanings are legitimate things to want, and all of them
require some implementation effort. Even #3 is tricky with a JIT
involved. And I'm not even considering floating generator frames, which
may not fit into a linear structure at all. Or when users want "long
stacks" for callbacks, where the stack in effect when a callback was set
is relevant.
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/f2e6570f/attachment.html>
Boris Zbarsky
2014-09-28 06:09:57 UTC
Permalink
Post by John Lenz
* the "stack" property (a string)
I'd somewhat like to see this be an accessor, to allow implementations
to compute the stack string lazily.
Post by John Lenz
Does this sound like a reasonable minimal set?
Yes.

-Boris
Erik Arvidsson
2014-09-28 13:26:09 UTC
Permalink
Last time this was tried the conclusion was that the current format using
the stack property as a string could not be standardized. Different
browsers use different format and therefore the format can not be changed
without breaking existing code.

The conclusion was that we needed to use a different name and then we might
add well stop using a string to represent this structured data.

Other than that. Great. +1.
Post by John Lenz
* the "stack" property (a string)
I'd somewhat like to see this be an accessor, to allow implementations to
compute the stack string lazily.
Does this sound like a reasonable minimal set?
Yes.
-Boris
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140928/c3293b9e/attachment.html>
Marius Gundersen
2014-09-28 15:01:37 UTC
Permalink
It would be helpful if the stack trace was machine readable, not just human
readable. As Erik said

[...] we might ass well stop using a string to represent this structured
data.
The stacktrace should probably be an array of objects with the properties
`filename`, `function`, `line` and `column`. It would then be simple to
format this stacktrace as a string and make it look exactly like it does in
browsers today. With a machine readable stack trace it would be easier to
build editor sandboxes (jsbin, codepen.io, etc) where errors inside the
sandbox could be caught by the editor and shown to the user.

Another feature of the stacktrace as an array is that a library could
manipulate the stack trace after it has been thrown, to hide the internals
of the library. This is similar to the black box feature in the Firefox
devtools. For example, a divide function which takes two integers could
throw an error when the second parameter is 0 (can't divide by zero). This
would result in the library internals ending up in the stack trace:

```js
function calculate(x, y){
return myIntegerMathLibrary.divide(2, x)*y;
}

calculate(0, 5)
/*
Exception: Second parameter is '0'; can't divide by zero
divide at myIntegerMathLibrary/divide.js:15:15 <= this is library code,it's
not helpful to the developer
calculate at myApplication:2:3 <= this tells the developer where the problem
is in their code
@myApplication:4:1
*/
```

If the library was allowed to manipulate the stack of the Error object
before throwing it, it could remove the top n lines that are internal to
it, which would help the developer locate the issue in their code.

Since all modern browsers implement a non-standard stack trace it is
possible to find out what file you are in and what line you are on by
throwing and catching an exception and analyzing the stack string. If stack
traces are added to the standard, then maybe a reflection API that can tell
what file and line the code is on should be added as well. The module meta
object will most likely get a filename property, but line number/character
number is not yet available.

Marius Gundersen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140928/cded96d9/attachment.html>
Filip Pizlo
2014-09-28 15:33:19 UTC
Permalink
It would be helpful if the stack trace was machine readable, not just human readable. As Erik said
+1
[...] we might ass well stop using a string to represent this structured data.
The stacktrace should probably be an array of objects with the properties `filename`, `function`, `line` and `column`. It would then be simple to format this stacktrace as a string and make it look exactly like it does in browsers today. With a machine readable stack trace it would be easier to build editor sandboxes (jsbin, codepen.io <http://codepen.io/>, etc) where errors inside the sandbox could be caught by the editor and shown to the user.
```js
function calculate(x, y){
return myIntegerMathLibrary.divide(2, x)*y;
}
calculate(0, 5)
/*
Exception: Second parameter is '0'; can't divide by zero
divide at myIntegerMathLibrary/divide.js:15:15 <= this is library code,it's not helpful to the developer
calculate at myApplication:2:3 <= this tells the developer where the problem is in their code
@myApplication:4:1
*/
```
If the library was allowed to manipulate the stack of the Error object before throwing it, it could remove the top n lines that are internal to it, which would help the developer locate the issue in their code.
Since all modern browsers implement a non-standard stack trace it is possible to find out what file you are in and what line you are on by throwing and catching an exception and analyzing the stack string. If stack traces are added to the standard, then maybe a reflection API that can tell what file and line the code is on should be added as well. The module meta object will most likely get a filename property, but line number/character number is not yet available.
Marius Gundersen
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140928/425d74e1/attachment.html>
John Lenz
2014-09-29 00:02:28 UTC
Permalink
Of course a standard string format can be machine readable (we maintain
stack trace parsers for existing browsers) but it is inconvenient compared
to simple JSON or whatever.
Post by Marius Gundersen
It would be helpful if the stack trace was machine readable, not just
human readable. As Erik said
[...] we might ass well stop using a string to represent this structured
data.
The stacktrace should probably be an array of objects with the properties
`filename`, `function`, `line` and `column`. It would then be simple to
format this stacktrace as a string and make it look exactly like it does in
browsers today. With a machine readable stack trace it would be easier to
build editor sandboxes (jsbin, codepen.io, etc) where errors inside the
sandbox could be caught by the editor and shown to the user.
Another feature of the stacktrace as an array is that a library could
manipulate the stack trace after it has been thrown, to hide the internals
of the library. This is similar to the black box feature in the Firefox
devtools. For example, a divide function which takes two integers could
throw an error when the second parameter is 0 (can't divide by zero). This
```js
function calculate(x, y){
return myIntegerMathLibrary.divide(2, x)*y;
}
calculate(0, 5)
/*
Exception: Second parameter is '0'; can't divide by zero
divide at myIntegerMathLibrary/divide.js:15:15 <= this is library code,it's
not helpful to the developer
calculate at myApplication:2:3 <= this tells the developer where the problem
is in their code
@myApplication:4:1
*/
```
If the library was allowed to manipulate the stack of the Error object
before throwing it, it could remove the top n lines that are internal to
it, which would help the developer locate the issue in their code.
Since all modern browsers implement a non-standard stack trace it is
possible to find out what file you are in and what line you are on by
throwing and catching an exception and analyzing the stack string. If stack
traces are added to the standard, then maybe a reflection API that can tell
what file and line the code is on should be added as well. The module meta
object will most likely get a filename property, but line number/character
number is not yet available.
Marius Gundersen
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140928/74b12e57/attachment.html>
Andreas Rossberg
2014-09-29 16:04:27 UTC
Permalink
Post by Marius Gundersen
The stacktrace should probably be an array of objects with the properties
`filename`, `function`, `line` and `column`.
Just to be clear, since you said "array of objects": 'function' would
still have to be string-valued, to avoid security leaks.

/Andreas
John Lenz
2014-09-28 23:35:59 UTC
Permalink
Firefox has changed aspects (adding columns and other things) so I think it
is possible that we can change this. Was there hard data otherwise?
Post by Erik Arvidsson
Last time this was tried the conclusion was that the current format using
the stack property as a string could not be standardized. Different
browsers use different format and therefore the format can not be changed
without breaking existing code.
The conclusion was that we needed to use a different name and then we
might add well stop using a string to represent this structured data.
Other than that. Great. +1.
Post by John Lenz
* the "stack" property (a string)
I'd somewhat like to see this be an accessor, to allow implementations to
compute the stack string lazily.
Does this sound like a reasonable minimal set?
Yes.
-Boris
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140928/a0a8864f/attachment.html>
John Lenz
2014-09-28 23:42:04 UTC
Permalink
But that said an new name and structure would be fine with me. I'm a little
worried "stack" would be out of sync with "stack trace" or whatever.
Making stack an accesor of "stackTrace" would help but what do we do with
writes?
Post by John Lenz
Firefox has changed aspects (adding columns and other things) so I think
it is possible that we can change this. Was there hard data otherwise?
Post by Erik Arvidsson
Last time this was tried the conclusion was that the current format using
the stack property as a string could not be standardized. Different
browsers use different format and therefore the format can not be changed
without breaking existing code.
The conclusion was that we needed to use a different name and then we
might add well stop using a string to represent this structured data.
Other than that. Great. +1.
Post by Boris Zbarsky
Post by John Lenz
* the "stack" property (a string)
I'd somewhat like to see this be an accessor, to allow implementations
to compute the stack string lazily.
Does this sound like a reasonable minimal set?
Yes.
-Boris
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140928/240d5ca2/attachment-0001.html>
Carl Smith
2014-09-29 18:49:46 UTC
Permalink
Just wanted to add that CoffeeShop [https://github.com/carlsmith/coffeeshop]
already uses stack traces the way JSFiddle and CodePen may do if they were
standardised. This only works on V8 as it's the only engine that respects
sourceURL 'directives' when listing eval'ed code in stack traces.

Providing the trace as an array, instead of a string, would be nice, but
nothing special. It's not difficult to parse the string into an array of
hashes now. On the other hand, named eval'ed code is absolutely killer. We
need named evals now.

It's currently impossible to build a JavaScript shell in *any* browser. FF
provides line and column numbers for compilation errors, but omits the
actual name, so they may as well just not bother ~ it's impossible to build
a traceback on Gecko runtime errors. V8 honours the given name, but doesn't
do line and column numbers on compilation errors, so you'd better hope your
users never make a syntax error.

CoffeeShop uses CoffeeScript, who's compiler provides it's own line and
column numbers on compilation errors, so it actually does work in Chrome,
but the app can't support JS :/

We *need* (1) the name of the file (2) the line number and (3) the column
number. The function's name could be useful, but everything else is just
go-faster-stripes.

Cheers -- carlsmith
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/5b1d2e04/attachment.html>
Carl Smith
2014-09-29 18:55:19 UTC
Permalink
Sorry, this paragraph is a bit confusing...
Post by Carl Smith
It's currently impossible to build a JavaScript shell in *any* browser. FF
provides line and column numbers for compilation errors, but omits the
actual name, so they may as well just not bother ~ it's impossible to build
a traceback on Gecko runtime errors. V8 honours the given name, but doesn't
do line and column numbers on compilation errors, so you'd better hope your
users never make a syntax error.
I meant to say that on Gecko, you can do compilation errors, but not
runtime ones. On Chrome, it's the other way around.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/94f1aba8/attachment-0001.html>
John Lenz
2014-09-29 22:04:59 UTC
Permalink
The issues with "sourceUrl" and syntax errors is fixed in the latest Chrome
dev channel and should be making its way to us in the near future. :-)
Post by Carl Smith
Just wanted to add that CoffeeShop [
https://github.com/carlsmith/coffeeshop] already uses stack traces the
way JSFiddle and CodePen may do if they were standardised. This only works
on V8 as it's the only engine that respects sourceURL 'directives' when
listing eval'ed code in stack traces.
Providing the trace as an array, instead of a string, would be nice, but
nothing special. It's not difficult to parse the string into an array of
hashes now. On the other hand, named eval'ed code is absolutely killer. We
need named evals now.
It's currently impossible to build a JavaScript shell in *any* browser. FF
provides line and column numbers for compilation errors, but omits the
actual name, so they may as well just not bother ~ it's impossible to build
a traceback on Gecko runtime errors. V8 honours the given name, but doesn't
do line and column numbers on compilation errors, so you'd better hope your
users never make a syntax error.
CoffeeShop uses CoffeeScript, who's compiler provides it's own line and
column numbers on compilation errors, so it actually does work in Chrome,
but the app can't support JS :/
We *need* (1) the name of the file (2) the line number and (3) the column
number. The function's name could be useful, but everything else is just
go-faster-stripes.
Cheers -- carlsmith
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/15a251ce/attachment.html>
Carl Smith
2014-09-29 22:39:07 UTC
Permalink
Post by John Lenz
The issues with "sourceUrl" and syntax errors is fixed in the latest
Chrome dev channel and should be making its way to us in the near future.
:-)
Awesome. I can add JavaScript support to the shell :)

I still think the omission of some method for naming eval'ed code in the
ES6 spec is unacceptable. It's not a nice-to-have that can be bundled with
nicer stack objects, which are relatively unimportant [easily fixed with a
regex].

Cheers John -- carlsmith
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/7ac5039f/attachment-0001.html>
Brendan Eich
2014-09-29 23:33:17 UTC
Permalink
Post by Carl Smith
I still think the omission of some method for naming eval'ed code in
the ES6 spec is unacceptable. It's not a nice-to-have that can be
bundled with nicer stack objects, which are relatively unimportant
[easily fixed with a regex].
See
http://esdiscuss.org/topic/dynamic-compilation-including-eval-and-script-tag-insertion-was-re-clean-scope
and possibly other old threads. JJB and I discussed, I forgot whether he
implemented.

/be
Carl Smith
2014-09-30 01:05:17 UTC
Permalink
Post by Carl Smith
I still think the omission of some method for naming eval'ed code in the
ES6 spec is unacceptable. It's not a nice-to-have that can be bundled with
nicer stack objects, which are relatively unimportant [easily fixed with a
regex].
See http://esdiscuss.org/topic/dynamic-compilation-including-
eval-and-script-tag-insertion-was-re-clean-scope and possibly other old
threads. JJB and I discussed, I forgot whether he implemented.
Thanks Brendan [and for JavaScript]. That discussion, though interesting,
seems to deal more with the implementation details, which went over my head
a bit to be honest.

Chrome currently supports named evals by concatenating `\n//#
sourceURL=<filename>` to the string before passing it to `eval`. There's a
longstanding ticket on FF for the pretty much the same thing [
https://bugzilla.mozilla.org/show_bug.cgi?id=583083]. The script tag
workaround feels nasty in a shell, with lots of small inputs, and doesn't
work for me ~ we use CoffeeScript.

If the source URL hack, or some cleaner wrapper for it, was standardised,
it'd make all the difference.

Thanks again -- carlsmith
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140930/c4ac69f4/attachment.html>
Brendan Eich
2014-09-30 01:36:35 UTC
Permalink
Post by Carl Smith
If the source URL hack, or some cleaner wrapper for it, was
standardised, it'd make all the difference.
Why don't we just make the source URL hack a de-facto standard? That's
how evolution happens, in the best case. Cc'ing @fitzgen.

/be
John Lenz
2014-09-30 02:44:41 UTC
Permalink
It is a defacto standard.
Post by Carl Smith
If the source URL hack, or some cleaner wrapper for it, was standardised,
it'd make all the difference.
Why don't we just make the source URL hack a de-facto standard? That's how
/be
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140929/dd312be0/attachment-0001.html>
Nick Fitzgerald
2014-09-30 12:18:45 UTC
Permalink
I remember web compat concerns, but if Chrome is exposing the `//#
sourceURL` to the web in error stacks, maybe we can get away with it
as well. I'd defer to jorendorff's opinion on this.

We've also discussed exposing the source mapped location of stack
frames to JS, but that's even trickier:

* We don't do any source mapping unless devtools are open, so exposing
this would leak whether the user is using devtools or not. Not sure
how serious that is, but it makes me hesitant. On the other hand,
always source mapping seems impractical, but maybe that's a false
assumption.

* It is a nonstarter to block JS on fetching a source map, so early
stack traces would not be source mapped, while later ones would be.
This sort of non-determinism makes me feel :( We could introduce a new
async method for getting stacks and only source map for these async
stacks (or make the new method that other branches of this thread are
discussing async).

Interested in hearing everyone's thoughts on this.

Cheers,

_Nick_
Post by John Lenz
It is a defacto standard.
Post by Carl Smith
If the source URL hack, or some cleaner wrapper for it, was standardised,
it'd make all the difference.
Why don't we just make the source URL hack a de-facto standard? That's how
/be
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
John Lenz
2014-09-30 16:28:17 UTC
Permalink
I don't believe we want source map involved as, as you say, that
information needs to be retrieved separately.
Post by John Lenz
It is a defacto standard.
Post by Brendan Eich
Post by Carl Smith
If the source URL hack, or some cleaner wrapper for it, was
standardised, it'd make all the difference.
Why don't we just make the source URL hack a de-facto standard? That's
/be
I remember web compat concerns, but if Chrome is exposing the `//#
sourceURL` to the web in error stacks, maybe we can get away with it as
well. I'd defer to jorendorff's opinion on this.
We've also discussed exposing the source mapped location of stack frames
* We don't do any source mapping unless devtools are open, so exposing
this would leak whether the user is using devtools or not. Not sure how
serious that is, but it makes me hesitant. On the other hand, always source
mapping seems impractical, but maybe that's a false assumption.
* It is a nonstarter to block JS on fetching a source map, so early stack
traces would not be source mapped, while later ones would be. This sort of
non-determinism makes me feel :( We could introduce a new async method for
getting stacks and only source map for these async stacks (or make the new
method that other branches of this thread are discussing async).
Interested in hearing everyone's thoughts on this.
Cheers,
Nick
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140930/82eaa111/attachment.html>
Carl Smith
2014-09-30 18:59:44 UTC
Permalink
Post by John Lenz
I don't believe we want source map involved as, as you say, that
information needs to be retrieved separately.
I seems there's three parts to this. One is allowing evals to be named the
way Chrome does, and providing line and column numbers for both caught and
uncaught errors. Another is improving the stack traces, providing an array
of hashes instead of a string. The last is source map support. I don't
personally see any reason to bundle this stuff into one issue.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140930/9169e37f/attachment.html>
Carl Smith
2014-09-30 19:08:13 UTC
Permalink
Just to be clear, you can convert a stack trace into a struct pretty
easily, and then do source mapping on it with Mozilla Source Maps. This
already works. I can see why a console would provide integrated source map
support, but no reason for that to be exposed to client code. It's only a
rarely used, pure convenience outside of dev tools.
From a humble Web dev's point of view, the important distinction is between
what I depend on the browser for, and what I can fix myself.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140930/fad5c7f5/attachment.html>
Carl Smith
2014-10-01 00:55:12 UTC
Permalink
Sorry, I didn't mean to kind of hijack the thread. Just read it back.
Really just wanted to share the point of view of someone who actually has
to provide tracebacks to the user as a central feature in an app. It's
difficult, but doable, but only in Chrome/Opera. Pragmatically, it'd just
be nice if FireFox did the named eval thing so it wasn't an engine specific
hack. That'd be close enough to a standard for a lot of cases. Other
vendors are what they are.

Cheers all
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141001/7a03d71a/attachment.html>
Carl Smith
2014-09-30 11:28:42 UTC
Permalink
John Lenz, using source URLs for naming eval'ed code in the traceback
provided to `window.onerror` isn't a de-facto standard; only V8 does it??
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140930/f1ace0fd/attachment-0001.html>
Loading...