Stacktraces from dynamically-constructed functions not as expected

Vivin Suresh Paliath vivin.paliath at gmail.com
Thu May 12 22:59:31 UTC 2016


Thanks Hannes. I looked at the issue and it answered another question I had
as well; I was wondering about the possibility of using a separator other
than $ that is legal in Java, but not in JavaScript.

On Thu, May 12, 2016 at 3:08 PM, Hannes Wallnoefer <
hannes.wallnoefer at oracle.com> wrote:

> Am 2016-05-12 um 23:42 schrieb Vivin Suresh Paliath:
>
>> Thanks for the explanation Hannes! The issue with $ makes sense; I ran
>> into that some time ago - I can't remember the exact situation, but it was
>> exactly as you described: the $ introduces ambiguity because it is a valid
>> character and so could be part of the name of the original function, and
>> not a separator. Would you be able to point me to the location in the
>> nashorn source where this mapping/translation is done? It would help me
>> learn more about the internals of nashorn.
>>
>
> The method name is created in Parser#createParserContextFunctionNode:
>
> http://hg.openjdk.java.net/jdk9/dev/nashorn/file/4b118e012ac4/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java#l532
>
> The method name for the stack trace is computed in
> NashornException#getScriptFrames:
>
> http://hg.openjdk.java.net/jdk9/dev/nashorn/file/4b118e012ac4/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java#l174
>
> I've filed a bug for this:
> https://bugs.openjdk.java.net/browse/JDK-8156896
>
> Hannes
>
>
>> On Thu, May 12, 2016 at 2:12 PM, Hannes Wallnoefer <
>> hannes.wallnoefer at oracle.com <mailto:hannes.wallnoefer at oracle.com>>
>> wrote:
>>
>>     Hi Vivin,
>>
>>     What you see is some fuzziness in the translation from JS
>>     functions to Java methods and from there to the stack traces you see.
>>
>>     When we compile a JS function, we create a Java method with the
>>     name of the function concatenated to the names of its parent
>>     functions, using '$' as separator. For anonymous functions we use
>>     something like L:123 as name where 123 is the line of code where
>>     the function begins.
>>
>>     This method naming scheme helps a lot in making bytecode easier to
>>     debug, and to create unique method names within a compilation
>>     unit. However, it also leads to the stack traces you see, getting
>>     f$foo in the first case and something like L1:foo in the second
>>     case, which is rendered as <anonymous> in the stack trace.
>>
>>     Ideally we should reverse this when printing stack traces,
>>     displaying only the name of the function itself, e.g. "bar" for
>>     "foo$bar" and "<anonymous>" for "foo$L:3". Unfortunately, "$" is a
>>     valid character in a JS identifier, so it's not that easy,
>>     "foo$bar" may also be the name of the original function.
>>
>>     I'm thinking about how to solve this and will probably file an
>>     issue for it.
>>
>>     Hannes
>>
>>     Am 2016-05-12 um 15:59 schrieb Vivin Suresh Paliath:
>>
>>         I tried this out on in chrome and I get the expected stack
>>         trace there. Is
>>         this a bug?
>>         On May 6, 2016 3:39 PM, "Vivin Suresh Paliath"
>>         <vivin.paliath at gmail.com <mailto:vivin.paliath at gmail.com>>
>>
>>         wrote:
>>
>>             I have the following code:
>>
>>             *var f = (function() {*
>>             *    return function foo() {*
>>             *        try {*
>>             *            throw new Error();*
>>             *        } catch(e) {*
>>             *            print(e.stack);*
>>             *        }*
>>             *    }*
>>             *})();*
>>
>>
>>             When I call the function, I get the following stacktrace
>>             as expected
>>             (mostly; I was expecting *foo* instead of *f$foo*).
>>
>>             *Error*
>>             *        at f$foo (<shell>:1)*
>>             *        at <program> (<shell>:1)*
>>
>>
>>             However, if I dynamically construct the function as follows:
>>
>>             *var f = new Function([], "return function foo() { try {
>>             throw new
>>             Error(); } catch(e) { print(e.stack); } }")()*
>>
>>
>>             I get:
>>
>>
>>             *Error*
>>             *        at <anonymous> (<function>:2)*
>>             *        at <program> (<shell>:1)*
>>
>>
>>             Is there a reason for this discrepancy? Isn't the second
>>             version
>>             effectively the same as the first? Also, why is it *f$foo*
>>             instead of
>>             *foo* in the first case?
>>
>>             I am running jdk8u92.
>>
>>             Thanks!
>>
>>             --
>>             Ruin untold;
>>             And thine own sadness,
>>             Sing in the grass,
>>             When eve has forgot, that no more hear common things that
>>             gleam and pass;
>>             But seek alone to lip, sad Rose of love and ruin untold;
>>             And thine own mother
>>             Can know it as I know
>>             More than another
>>             What makes your own sadness,
>>             Set in her eyes.
>>
>>             map{@n=split//;$j.=$n[0]x$n[1]}split/:/,"01:11:02".
>>             ":11:01:11:02:13:01:11:01:11:01:13:02:12:01:13:01".
>>             ":11:04:11:06:12:04:11:01:12:01:13:02:12:01:14:01".
>>             ":13:01:11:03:12:01:11:04:12:02:11:01:11:01:13:02".
>>             ":11:03:11:06:11:01:11:05:12:02:11:01:11:01:13:02".
>>             ":11:02:12:01:12:04:11:06:12:01:11:04:12:04:11:01".
>>             ":12:03:12:01:12:01:11:01:12:01:12:02:11:01:11:01".
>>             ":13:02:11:01:02:11:01:12:02";map{print chr unpack"
>>             i",pack"B32",$_}$j=~m/.{8}/g
>>
>>
>>
>>
>>
>> --
>> *[vivin.net <http://vivin.net>:: github <http://github.com/vivin>::
>> linkedin <https://www.linkedin.com/in/vivin>]*
>>
>
>


-- 
*[vivin.net <http://vivin.net> :: github <http://github.com/vivin> ::
linkedin <https://www.linkedin.com/in/vivin>]*


More information about the nashorn-dev mailing list