How to set correct fileName for exceptions thrown from a function in a Function object

Tim Fox timvolpe at gmail.com
Wed Feb 18 14:00:47 UTC 2015


On 18/02/15 13:33, A. Sundararajan wrote:
> So, did you fix "// #sourceURL" to //# sourceURL" ? Note on the 
> whitespace: no whitespace between '//' and '#' and single whitespace 
> after '#' ?

Bingo, that worked :)

So I now have exceptions thrown from evals showing correct lineNumber, 
fileName and stack for all exceptions apart from SyntaxError.

I've created another example here:

https://gist.github.com/purplefox/f99ad4c78d246d2d6aee

In this example, the eval has a Syntax Error (e.g. the user is trying 
require a module with a syntax error in it).

What I see is that the caught exception corresponds to where the eval() 
was _executed_, not to the place in the eval code where the syntax error 
actually is.

Interestingly the correct information *is* available if I do a bit of 
digging - two references deep from the caught exception there's the 
exception that we're actually interested in with the correct lineNumber, 
(but not correct fileName).

I'd expect the caught exception to correspond to the actual SyntaxError 
in the code not to where the eval was invoked - this would be consistent 
with how the other error types are handled, and it would be a lot more 
useful for the user, as what they want to know is where in their code 
the problem actually is.

>
> Release notes page here says the fix is in 8u20. 
> http://www.oracle.com/technetwork/java/javase/2col/8u20-bugfixes-2257730.html. 
> Bug id is http://bugs.java.com/view_bug.do?bug_id=8032068
>
> -Sundar
>
> On Wednesday 18 February 2015 06:58 PM, Tim Fox wrote:
>> On 18/02/15 13:13, A. Sundararajan wrote:
>>>
>>> Hi Tim,
>>>
>>> It was added in 8u20 if I recall right.
>>>
>>> jjs -version
>>> nashorn 1.8.0_40
>>> jjs>
>>> jjs> eval("f() //# sourceURL=t.js")
>>> t.js:1 ReferenceError: "f" is not defined
>>> jjs> eval("g() //@ sourceURL=g.js")
>>> g.js:1 ReferenceError: "g" is not defined
>>>
>>> I think your file has "// #sourceURL=wibble.js". Please try changing 
>>> it as "//# sourceFile=wibble.js"
>>
>> Ok, I am confused now... I have tried both #sourceURL (which most of 
>> the google hits say to use) and #sourceFile and neither seem to work ;)
>>
>> I've also tried @sourceURL which some other links say to use. (Yay 
>> for consistency ;) )
>>
>> Nothing seems to work so far.
>>
>> I am using nashorn 1.8.0_25 which is the latest version in the 
>> production Oracle JDK afaict. Do I have to use OpenJDK to get these 
>> changes? I don't think this will be an option as most of users use 
>> the Oracle JDK.
>>
>>>
>>> See also: 
>>> https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Debug_eval_sources
>>>
>>> -Sundar
>>>
>>> On Wednesday 18 February 2015 06:14 PM, Tim Fox wrote:
>>>> Hi Sundar,
>>>>
>>>> I tried the sourceURL trick:
>>>>
>>>> https://gist.github.com/purplefox/60619067006c3cc3eaee
>>>>
>>>> But it doesn't seem to work. I suspect because the parsing of the 
>>>> eval fails before it gets to the last line (?) :(
>>>>
>>>> I'm going to give a go with load()...
>>>>
>>>> On 18/02/15 10:11, A. Sundararajan wrote:
>>>>> you can use
>>>>>
>>>>> 1) "load" from object - object with name and script properties.
>>>>>
>>>>> 2) or use 'eval' naming // #sourceURL comment
>>>>>
>>>>> as mentioned here:
>>>>>
>>>>> http://mail.openjdk.java.net/pipermail/nashorn-dev/2014-July/003174.html 
>>>>>
>>>>>
>>>>> Can code for body of module function be something like 
>>>>> "eval(readScriptAsText() + "\n// #sourceURL=" + name)" ?
>>>>>
>>>>> Hope this helps,
>>>>> -Sundar
>>>>>
>>>>> On Wednesday 18 February 2015 03:30 PM, Tim Fox wrote:
>>>>>> I've added a simple reproducer that you can run in the repl:
>>>>>>
>>>>>> https://gist.github.com/purplefox/b03a2a6263c26e3206da
>>>>>>
>>>>>> Another observation is that line number is reported as 6, when it 
>>>>>> should be 5 (assuming the first line is line 1 which is normal 
>>>>>> convention afaik)
>>>>>>
>>>>>> On 18/02/15 09:40, Tim Fox wrote:
>>>>>>> Hi all,
>>>>>>>
>>>>>>> I'm currently using a CommonJS/npm modules require 
>>>>>>> implementation (npm-jvm) with Nashorn.
>>>>>>>
>>>>>>> Roughly, the way it works (and I'm sure you're already familiar 
>>>>>>> with this technique) is it takes the JavaScript module and wraps 
>>>>>>> it in a Function object:
>>>>>>>
>>>>>>> var body = readScriptAsText();
>>>>>>> var args   = ['exports', 'module', 'require', '__filename', 
>>>>>>> '__dirname'];
>>>>>>> var func = new Function(args, body);
>>>>>>> func.apply(module, [module.exports, module, module.require, 
>>>>>>> module.filename, dir]); // Execute it - this works fine
>>>>>>>
>>>>>>> Now let's say the actual module (foomodule.js) we are loading 
>>>>>>> contains this:
>>>>>>>
>>>>>>> module.exports = function() {
>>>>>>>     var num = 234;
>>>>>>>     num.substr(1, 1); // Will throw TypeError here
>>>>>>> }
>>>>>>>
>>>>>>> I.e. it simply exports a function, which will throw a TypeError 
>>>>>>> when it's executed.
>>>>>>>
>>>>>>> When the exported function is executed it does indeed throw a 
>>>>>>> TypeError:
>>>>>>>
>>>>>>> var f = require("foomodule");
>>>>>>>
>>>>>>> f(); // Throws TypeError
>>>>>>>
>>>>>>> Unfortunately the fileName field of the TypeError is set to 
>>>>>>> "<function>" not to "foomodule.js", which is unfriendly for the 
>>>>>>> user.
>>>>>>>
>>>>>>> This is understandable as the Function object which wraps the 
>>>>>>> module doesn't know about "foomodule.js".
>>>>>>>
>>>>>>> So.. my question is.. how do I tell the Function object that the 
>>>>>>> "filename" it should use when exceptions are thrown from it is 
>>>>>>> "foomodule.js"?
>>>>>>>
>>>>>>> I have tried the following and none work:
>>>>>>>
>>>>>>> var func = new Function(args, body);
>>>>>>> func.name = "foomodule.js";
>>>>>>> func.fileName = "foomodule.js";
>>>>>>> func.displayName = "foomodule.js";
>>>>>>>
>>>>>>> Any insights would be greatly appreciated.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>



More information about the nashorn-dev mailing list