On 20/02/15 11:48, A. Sundararajan wrote:
Unlike TypeError or ReferenceError or any other execution error from
eval'ed code, SyntaxError is thrown "up front". It is an "early
error" as defined in "Clause 16" of ES 5.1 spec
(https://es5.github.io/#x16). If we set evaluated code's file name and
line number of syntax error, that would seem to imply that the
execution reached that line and resulted in error. But, that is not
the case here - execution of eval'ed code is yet to start. Error was
detected during "compilation" and thrown from the "eval line" itself.
Also, if there are nested eval calls and deepest one resulted in
SyntaxError, we want to know which eval attempted to eval code with
the syntax error.
The "message" property of SyntaxError does contain the file
I don't think it contains the correct fileName (as set by sourceURL), it
always seems to be "<eval>"- I assume because the parsing fails before
it reaches the sourceURL directive at the end of the eval'd scriptlet :(
If I just pass the SyntaxError from Nashorn directly to the user it's
highly confusing - they don't see a stack that points to their code
(although it is there, buried two layers deep in an internal API - but
surely we shouldn't expect users to navigate a non public API just to
retrieve basic exception information) nor do they see the name of the
script that caused the error (just "<eval>"), this makes it really hard
for the user to fix their code.
As discussed earlier it isn't an option for me to create my own
SyntaxError instance with the useful values, as any values I set are
ignored if thrown to Java code, without delving into a non public API to
retrieve the JS values...
So right now, I'm at a loss how I can make this work to give an
acceptable user experience.
I will keep hacking and see if I can come up with something...
Thanks for your continuing help though :)
and line (like file:N) of the eval-ed code that caused syntax error.
-Sundar
On Friday 20 February 2015 03:11 PM, Tim Fox wrote:
HI Sundar -
On 20/02/15 08:09, A. Sundararajan wrote:
* SyntaxError constructor accepting extra arguments apart from
message is not as per ECMAScript standard. That one is
Firefox/Mozilla specific extension. We try to *add* properties,
functions for extension - try not to modify/extend standard defined
functions, constructors.
* User can fileName, lineNumber and columnNumber of constructed
SyntaxError instance.
* On the java side, the NashornException and ScriptException's file,
line, column use the actual throw point from the script source.
While this can read the values from SyntaxError or any Error for
that matter, there is a problem. fileName, lineNumber, columnNumber
could be set to any value in script. These have to be converted to
String, int, int respectively. Conversion means calling
[[DefaultValue]] with String, Number hint - which is calling out to
script code. This process can itself throw exception!! All this may
destroy info. on where exactly the underlying exception was thrown.
* There is clear workaround. Script code can always read SyntaxError
instance's fileName, lineNumber etc. - which can be set to anything
post construction. Java code can get underling ECMA error instance
via NashornException.getEcmaError - which would return a
ScriptObjectMirror. Java code can call
ScriptObjectMirror.getMember("fileName") etc. to retrieve properties
set by user's script.
I've tried what you suggest, it seems to work (ish), but I end up
with seriously grungy code that relies on casting and non public APIs
that (I guess) could be changed without warning in any release, so I
don't think I'd be happy doing this in Vert.x. Here's an example:
(Yikes!)
https://gist.github.com/purplefox/003fae1e32fd44368ffa
So.... rewinding a bit here. The only reason I find myself shaving
this particular Yak is because syntax errors thrown from evals()
aren't reported by Nashorn with the fileName and lineNumber of the
_eval_, instead they are reported with the fileName/lineNumber of
where the eval was executed.
I mentioned this in a previous post, but here is the gist again that
demonstrates the issue:
https://gist.github.com/purplefox/7ba0d87d2d1670b871a4
This means I have to manually catch SyntaxErrors in our require()
implementation. Fill in the correct fileName, lineNumber etc and
rethrow as new SyntaxError instances. But, as we discussed in this
thread, that doesn't seem to work easily as I can't set fileName,
lineNumber etc when constructing an instance in Nashorn, and if I set
it afterwards those values aren't visible in Java (at least not in a
portable way that doesn't rely on hacky reliance on non public APIs).
If I don't do this, our users see a pretty useless error message when
there's a syntax error in their module and it all leads to a very
poor user experience.
Imho, a better way to solve this would be for Nashorn to create
syntax error instances when doing evals() that properly reflect the
lineNumber and fileName of the _eval_ not of the place the eval was
executed. This seems a far more intuitive way to do it and it would
be consistent with the way other Error types are thrown from code in
evals (e.g. TypeError, RangeError etc) which *do* reflect the correct
line in the eval where the error occurred. Fundamentally a user is
not going to care about the lineNumber where the eval was executed,
they want to know where in the actual code the syntax error is -
that's the useful information which is currently being obscured.
So, any chance of changing/fixing the current behaviour? Doing that
would mean I wouldn't have to little our code with piles of Yak hair
trying to get the important information out of private classes, and I
think it would lead to a better and more intuitive user experience :)
Hope this helps,
-Sundar
On Wednesday 18 February 2015 08:29 PM, Tim Fox wrote:
Hi all,
I've started a new thread for this, so as not to clutter the
previous thread on exceptions.
I've come across a possible issue with creating SyntaxError objects
(and potentially other exceptions although I haven't tested them).
https://gist.github.com/purplefox/dfe30a38098c1708e24b
In the above gist I create a SyntaxError specifying message,
fileName, and lineNumber.
However fileName and lineNumber appear to be ignored, and instead
the SyntaxError fileName and lineNumber are set to the fileName of
the file where it was created and the lineNumber of the creation.
I'm not sure if I'm doing something wrong, but according to
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError
I should be able to create SyntaxError objects like this.
There appears to be a further issue. If I then throw the syntax
error from the JS script, and catch it in Java like this:
try {
engine.eval(script);
} catch (ScriptException e) {
System.out.println("message:" + e.getMessage());
System.out.println("fileName:" + e.getFileName());
System.out.println("lineNumber:" + e.getLineNumber());
}
Then the message, fileName and lineNumber always correspond to
place where the object was created, not to the subsequently set
values.
In other words, I can't figure out a way of creating a SyntaxError
object in JS with my own values of fileName and lineNumber and have
those values available in Java when caught.
Any ideas from the experts? :)