Nashorn's javax.script.ScriptEngineFactory produces wrong code
Rony G. Flatscher
Rony.Flatscher at wu.ac.at
Sat Jan 7 13:52:33 UTC 2017
Hi Ed,
On 06.01.2017 17:49, Edmond Kemokai wrote:
> The issue seems to go away after I quote the string.
If you supplied a Javascript encoded string to the Nashorn ScriptEngineFactory.getOutputStatement()
you removed the cause of demonstrating that Nashorn ScriptEngineFactory creates wrong output statements!
The problem is that Nashorn's ScriptEngineFactory.getOutputStatement() does not analyze the received
string (which may be any sequence of characters) to see whether escaping needs to take place (e.g.
containing quotes or backslashes) and finally enquoting the received (maybe escape processed) string
to make it acceptable as an argument to its print() function!
The task at hand is to create an output statement that will be able to output the received string as
is (no matter what the string contains), character by character!
---
Background: the JSR-223/javax.script package was *not* created with a specific scripting language in
mind. A scripting factory cannot assume that a supplied string adheres to the specific rules of that
particular scripting language. The getOutputStatement() method is there to get an output statement
adhering to the syntax rules of the script language that outputs (shows) the string exactly as
received, character by character! Each script language may have different syntax, escaping rules
etc., therefore the ScriptEngineFactory knowing its ScriptEngines syntax and rules is asked to
create a proper output statement.
It is the script factory's responsibility to analyze the received string and to escape characters in
order to have the script engine output the string exactly as received, character by character.
To test this, my test program feeds any available javax.script language with a string containing
quotes around the script engine name (to test quote escaping) and has the script engine take its own
medicine by executing the returned output statement.
In the case of Nashorn the script engine is not able to reliably run the output statement generated
by its own ScriptEngineFactory!
So, if getOutputStatement() receives the following string value to output:
abc "def" ghi
it needs to analyze and in this case escape the string first to match the rules of JavaScript:
abc \"def\" ghi
and then produce the output statement by enquoting the escaped string:
print("abc \"def\" ghi")
This way, this statement can be run correctly by Nashorn and it gives exactly the received string as
output:
abc "def" ghi
Also in the case of Nashorn/Javascript I would add a trailing '\n' character as usually script
engine's output statements supply a trailing new line character. However, this is not
defined/mandated and left to the implementation.
---rony
P.S.: The Rexx/ooRexx ScriptEngineFactory would create the following output statement and be able to
successfully run it, yielding exactly the string that was supplied to getOutputStatement():
say "abc ""def"" ghi"
running that statement yields the output:
abc "def" ghi
(The Rexx/ooRexx language escapes quotes in strings by doubling them.)
> You can run the code in the browser by right clicking and choosing "Test" then click "Run". On the
> top right, click the dropdown button and choose "Log Viewer" to see the output.
>
>
>
> Ouput:
>
> INFO Invocation - ---> language [ECMAScript]:
> ---------------------------------------->
>
> INFO Invocation - 1) output statement to process: "hello world, this is
> ECMAScript speaking! "
>
> INFO Invocation - --> testing getOutputStatement(String)
> INFO Invocation - , produced the following [ECMAScript] output statement
>
> print("hello world, this is ECMAScript speaking! ")
>
> INFO Invocation - ... now running "eval(code)" using the scripting engine
> [ECMAScript]:
>
>
> INFO Invocation -
>
> INFO Invocation - 2) testing getMethodCallSyntax(obj, meth, arg...)
> INFO Invocation - , produced the following [ECMAScript] method call statement:
>
> object.method(arg1,arg2)
>
> INFO Invocation - 3) testing getProgram(String...)
> INFO Invocation - produced the following [ECMAScript] program:
>
> print("hello world, this is ECMAScript speaking! ");object.method(arg1,arg2);
>
> INFO Invocation - <--- end of testing language [ECMAScript].
> <----------------------------------------
>
>
>
>
> On Fri, Jan 6, 2017 at 10:21 AM, Rony G. Flatscher <Rony.Flatscher at wu.ac.at
> <mailto:Rony.Flatscher at wu.ac.at>> wrote:
>
> Hi Ed,
>
> On 06.01.2017 16:07, Edmond Kemokai wrote:
>>
>> I am the developer of HiveMind, it is a web app platform that relies entirely on scripting
>> engines via JSR-223.
>>
>> You can access a demo instance: http://demo.crudzilla.com:7000/ <http://demo.crudzilla.com:7000/>
>> Login with: developer/developer
>>
>> I have created a test file in: /com/crudzilla/cloudTest/web/rony-groovy.ste
>>
>> Put your code (the original one you pasted) in there and save, I'll take a look to see what
>> might be missing.
> Done.
>
> After compiling just run it as "java RunScript" (make sure your CLASSPATH picks up the
> directory that contains RunScript.class, which does not define any package name, e.g. "."). It
> will list all JSR-223 scripting languages on your system and give the help. E.g. currently on
> my Windows system:
>
> F:\work\svn\bsf4oorexx\trunk\samples\Java\javax.script>java RunScript
> The following javax.script engines are currently available:
>
> ECMAScript
> ooRexx
>
> usage: java RunScript [{-i | -t | -e enginename filename [args...] | filename [args...]}]
>
> ... no arguments lists the available javax.script engines
> -h ... 'help', gives this usage text
> -i ... lists the available javax.script engines and informs about their properties
> -t ... lists the available javax.script engines and tests evaluating their
> "getOutputStatement(String)" method
> -e enginename filename [args...] ... uses "enginename" to evaluate "filename"
> supplying the arguments "args..."
> filename [args...] ... the "filename" extension determines the script engine to
> evaluate it, supplying the arguments "args..."
>
> Running with the "-t" switch tests the code generated by the script engine's factories by
> letting it eval()'ed.
>
> ---rony
>
>
>
>>
>>
>> On Fri, Jan 6, 2017 at 9:07 AM, Rony G. Flatscher <Rony.Flatscher at wu.ac.at
>> <mailto:Rony.Flatscher at wu.ac.at>> wrote:
>>
>> Besides Java 1.8.0_111 the problem exists in 9ea-+134 (engine version: "9ea", language
>> version:
>> "ECMA 262 - Edition 5.1" ) as well: Nashorn's javax.script factory is used to get an output
>> statement and then it is used to execute it:
>>
>> ---> language [ECMAScript]: ---------------------------------------->
>>
>> 1) output statement to process: hello world, this is "ECMAScript" speaking!
>>
>> --> testing getOutputStatement(String), produced the following [ECMAScript]
>> output statement
>>
>> print(hello world, this is "ECMAScript" speaking! )
>>
>> ... now running "eval(code)" using the scripting engine [ECMAScript]:
>>
>>
>> javax.script.ScriptException: <eval>:1:12 Expected , but found world
>> print(hello world, this is "ECMAScript" speaking! )
>> ^ in <eval> at line number 1 at column number 12 while eval() the code:
>> print(hello
>> world, this is "ECMAScript" speaking! )
>>
>> This time trying to not format the Java code, so hopefully the mailer will not render it
>> illegible:
>>
>> ... cut ...
>>
>> // create an output statement and execute output statement with the script engine
>> static void testEngine(String name, ScriptEngineFactory sef, ScriptEngine se)
>> {
>> System.out.println("---> language ["+name+"]:
>> ---------------------------------------->\n");
>> String text="hello world, this is \""+name+"\" speaking! ";
>> String code=sef.getOutputStatement(text);
>> System.out.println("\t1) output statement to process: "+text+"\n");
>>
>> System.out.print("\t--> testing getOutputStatement(String)");
>> System.out.println(", produced the following ["+name+"] output statement
>> \n\n"+code+"\n");
>> System.out.println("\t... now running \"eval(code)\" using the scripting engine
>> ["+name+"]: \n\n");
>> try
>> {
>> se.eval(code);
>> System.out.println("\n");
>> }
>> catch (ScriptException sexc)
>> {
>> System.err.println(sexc+" while eval() the code: "+code+"\n");
>> }
>>
>> System.out.print("\t2) testing getMethodCallSyntax(obj, meth, arg...)");
>> String methCode=sef.getMethodCallSyntax("object", "method", "arg1", "arg2");
>> System.out.println(", produced the following ["+name+"] method call statement:
>> \n\n"+methCode+"\n");
>>
>> System.out.print("\t3) testing getProgram(String...)");
>> String programCode=sef.getProgram(code, methCode);
>> System.out.println(" produced the following ["+name+"] program:
>> \n\n"+programCode+"\n");
>>
>> System.out.println("<--- end of testing language ["+name+"].
>> <----------------------------------------\n");
>> }
>>
>> ... cut ...
>>
>> If I should file a bug then please advise where and how.
>>
>> ---rony
>>
>>
>> On 08.12.2016 16:17, Rony G. Flatscher wrote:
>> > Unfortunately, the mailing list seems to behave as if it was running in the 1970's such
>> that the
>> > formatted text (indented, partially colorized and formatted to preformat and Courier)
>> has turned to
>> > become illegible, unfortunately (using the Thunderbird e-Mail client)!
>> > :(
>> >
>> > The meat is right in the first two paragraphs and the last paragraph before the
>> signature. Should
>> > anyone be interested in the Java-utility, please drop me a personal e-mail and I will
>> send that Java
>> > program as an attachment to you.
>> >
>> > ---rony
>> >
>> >
>>
More information about the nashorn-dev
mailing list