Nashorn's javax.script.ScriptEngineFactory produces wrong code
Edmond Kemokai
ekemokai at gmail.com
Fri Jan 6 16:49:05 UTC 2017
The issue seems to go away after I quote the string. 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>
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/
> 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
> > 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
>> >
>> >
>> >
>> > On 08.12.2016 16:05, Rony G. Flatscher wrote:
>> >> Hi there, was directed to this list to report an error with Nashorn's
>> implementation of
>> >> javax.script.ScriptEngineFactory.getOutputStatement(String toDisplay).
>> >>
>> >> The test is simple: one supplies a string, containing double quotes,
>> and immediately use the Nashort
>> >> script engine to carry out the output statement produced by its
>> factory, yielding a runtime error.
>> >> In order for you to reproduce, I list the Java utility (it lists all
>> available javax.script engines
>> >> and tests them with the -t switch and is a little example of how one
>> can take advantage of
>> >> javax.script very easily) after my signature below to study the code
>> and run it to double-check:
>> >>
>> >> F:\work\svn\bsf4oorexx\trunk\samples\Java\jsr223>java RunScript
>> -t ---> 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! )* 2) testing getMethodCallSyntax(obj,
>> meth, arg...), produced the
>> >> following [ECMAScript] method call statement:
>> object.method(arg1,arg2) 3) testing
>> >> getProgram(String...) produced the following [ECMAScript] program:
>> print(hello world, this is
>> >> "ECMAScript" speaking! );object.method(arg1,arg2); <--- end of
>> testing language [ECMAScript].
>> >> <---------------------------------------- ---> language [ooRexx]:
>> >> ----------------------------------------> ... cut ...
>> >>
>> >> The specification for javax.script created by the Java specification
>> request group 223 (a.k.a.
>> >> JSR-223) can be consulted. BTW, "jrunscript[.exe]" (from the JDK)
>> seems to be broken, it only is be
>> >> able to execute the Nashorn script engine, despite switches that allow
>> other script engines to be
>> >> employed.
>> >>
>> >> ---rony
>> >>
>> >> Code of "RunScript.java" (little utility to list the currently
>> available javax.script languages, run
>> >> any javax.script program, give helpful information about each
>> javax.script engine and test each one
>> >> using its own factory means): just compile it and run it with "java
>> RunScript -t":
>> >>
>> >> ------------------ cut here ------------------
>> >> import java.io.File; import java.io.FileReader; import
>> java.util.ArrayList; import java.util.Arrays;
>> >> import java.util.List; import java.util.HashMap; import
>> java.util.SortedSet; import
>> >> java.util.TreeSet; import javax.script.Bindings; import
>> javax.script.ScriptContext; import
>> >> javax.script.ScriptEngine; import javax.script.ScriptEngineFactory;
>> import
>> >> javax.script.ScriptEngineManager; import
>> javax.script.ScriptException; import
>> >> javax.script.SimpleScriptContext; /* ------------------------ Apache
>> Version 2.0 license
>> >> ------------------------- Copyright 2015-2016 Rony G. Flatscher
>> Licensed under the Apache License,
>> >> Version 2.0 (the "License"); you may not use this file except in
>> compliance with the License. You
>> >> may obtain a copy of the License at http://www.apache.org/licenses
>> /LICENSE-2.0 Unless required by
>> >> applicable law or agreed to in writing, software distributed under the
>> License is distributed on an
>> >> "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
>> express or implied. See the
>> >> License for the specific language governing permissions and
>> limitations under the License.
>> >> -----------------------------------------------------------------------------
>> changed: 2016-12-06,
>> >> rgf: if no argument is given, show the help after the list of
>> currently available javax.script
>> >> engines */ /** A command line Java utility to query, test and evaluate
>> {@link javax.script}
>> >> scripting engines that * gets distributed via the beta BSF4ooRexx
>> package from Sourceforge. * *
>> >> <p>Usage: <code>java RunScript [{-i | -t | -e enginename filename
>> [args...] | filename
>> >> [args...]}]</code> * <br> * <ul> * <li> ... no arguments: lists the
>> currently available
>> >> <code>javax.script</code> engines * * <li> <code>-h</code> ... 'help',
>> lists and briefly explains
>> >> the command line options * * <li> <code>-i</code> ... lists the
>> available <code>javax.script</code>
>> >> engines and informs about their properties * * <li> <code>-t</code>
>> ... lists the available
>> >> <code>javax.script</code> engines and tests evaluating their factory's
>> >> <code>"getOutputStatement(String)"</code> method * * <li>
>> <code>-e enginename filename
>> >> [args...]</code> ... uses <code>"enginename"</code> to
>> evaluate
>> >> <code>"filename"</code> supplying the arguments
>> <code>"args..."</code> * * <li>
>> >> <code>filename [args...]</code> ... the <code>"filename"</code>
>> extension determines the
>> >> script engine to evaluate it, supplying the arguments
>> <code>"args..."</code> * </ul> * * *
>> >> @author Rony G. Flatscher * @since 2015-05-20 */ public class
>> RunScript { public static void
>> >> main(String args[]) { ScriptEngineManager manager = new
>> ScriptEngineManager();
>> >> List<ScriptEngineFactory> factories = manager.getEngineFactories();
>> >> HashMap<String,ScriptEngineFactory> n2sef=new
>> HashMap<String,ScriptEngineFactory> ();
>> >> HashMap<String,ScriptEngine> n2se =new HashMap<String,ScriptEngine>
>> (); // create the Maps for
>> >> (ScriptEngineFactory factory : factories) { String
>> name=factory.getLanguageName(); // String
>> >> name=factory.getEngineName(); n2sef.put(name, factory); n2se
>> .put(name, factory.getScriptEngine());
>> >> } // create a sorted set of key names SortedSet<String> keys = new
>> TreeSet<String>(n2sef.keySet());
>> >> int argsStartAt=-1; // arguments - if any - for filenmae to execute
>> start at this position
>> >> ScriptEngine scriptEngineToUse=null; String filename=null; if
>> (args.length==0) // list all available
>> >> javax.script engines { System.out.println("The following javax.script
>> engines are currently
>> >> available:\n"); for (String key : keys) {
>> System.out.println('\t'+key); } System.out.println();
>> >> showHelp(); return; } else // process the first argument to decide
>> what we need to do { String
>> >> firstWord=args[0]; // get first value if (firstWord.startsWith("-")==true)
>> // a switch at hand! { if
>> >> (firstWord.length()!=2) // oops an error, we need excactly two chars
>> (-i, -t, -e) { throw new
>> >> IllegalArgumentException("switch '-' must be followed by one of the
>> letters 'i', 't', or 'e'"); }
>> >> String uSwitch=firstWord.substring(1).toUpperCase(); // get switch in
>> uppercase if
>> >> (uSwitch.equals("I")) // list all engines, list all their standard
>> properties { for (String key :
>> >> keys) // list all engines in order{ { showEngineProperties(key,
>> n2sef.get(key)); } return; } else if
>> >> (uSwitch.equals("T")) // list all engines, test them { for (String key
>> : keys) // list all engines
>> >> in order{ { testEngine(key, n2sef.get(key), n2se.get(key)); } return;
>> } else if
>> >> (uSwitch.equals("H")) // -h ... help text { showHelp(); return; } else
>> if (uSwitch.equals("E")) //
>> >> -e engineName fileName [arg... ] { if (args.length<3) { throw new
>> IllegalArgumentException("too few
>> >> command line arguments ("+args.length+"), minimum needed is 3: \"-e
>> enginename filename\""); } //
>> >> check whether engine is available, if so, then load it
>> filename=args[2]; // assign filename String
>> >> errMsg="no \""+args[1]+"\" javax.script engine available"; try {
>> >> scriptEngineToUse=manager.getEngineByName(args[1]); // fetch script
>> engine } catch (Exception exc) {
>> >> throw new IllegalArgumentException(errMsg); } if
>> (scriptEngineToUse==null) { throw new
>> >> IllegalArgumentException(errMsg); } argsStartAt=3; // fourth
>> argument! } else // unknown switch {
>> >> throw new IllegalArgumentException("unknown switch '"+firstWord+"',
>> must be followed by one of '-h',
>> >> '-i', '-t', or '-e'"); } } else // a filename in hand, check whether
>> we have a suitable engine
>> >> available { // - check whether suitable engine is available, if not
>> raise an exception
>> >> filename=args[0]; // assign filename int lastIdx=filename.lastIndexOf('.');
>> if (lastIdx==0) { throw
>> >> new IllegalArgumentException("filename \"filename\" does not have an
>> extension, cannot determine
>> >> scripting engine"); } String errMsg="cannot determine scripting engine
>> from the filename extension
>> >> in \""+filename+"\""; try { String extension=filename.substring(lastIdx+1);
>> // get extension
>> >> scriptEngineToUse=manager.getEngineByExtension(extension); // fetch
>> script engine } catch (Exception
>> >> exc) // if substring() causes an exception { throw new
>> IllegalArgumentException(errMsg); } if
>> >> (scriptEngineToUse==null) // no scripting engine found { throw new
>> IllegalArgumentException(errMsg);
>> >> } argsStartAt=1; // second argument! } } // now setup the remainder
>> and eval() the "filename" with
>> >> the script engine // - check whether file exists, if not raise an
>> exception File f=null; try { f=new
>> >> File (filename); } catch (Exception exc) { throw new
>> IllegalArgumentException(exc); } if
>> >> (f.exists()==false) { throw new IllegalArgumentException("filename
>> \""+filename+"\" does not
>> >> exist"); } // - supply filename ScriptContext
>> sc=scriptEngineToUse.getContext(); // get the default
>> >> context sc.setAttribute(ScriptEngine.FILENAME, filename,
>> ScriptContext.ENGINE_SCOPE); // - if
>> >> arguments, setup ARGV in ENGINE_SCOPE if (args.length>argsStartAt) //
>> do we have command line
>> >> arguments to supply? { String argArr []=new String
>> [args.length-argsStartAt]; // determine array
>> >> size int k=0; for (int i=argsStartAt; i<args.length; i++, k++) {
>> argArr[k]=args[i]; }
>> >> sc.setAttribute(ScriptEngine.ARGV, argArr,
>> ScriptContext.ENGINE_SCOPE); } // - eval the script try {
>> >> scriptEngineToUse.eval(new FileReader(f)); } catch (Exception exc) {
>> throw new
>> >> IllegalArgumentException(exc); } } // show information about the
>> script engine static void
>> >> showEngineProperties(String name, ScriptEngineFactory sef) {
>> System.out.println(name);
>> >> System.out.print ("\tgetEngineName() : "); try {
>> System.out.println(sef.getEngineName() ); } catch
>> >> (Exception e) { System.out.println("--> FAILED!"); } System.out.print
>> ("\tgetEngineVersion() : ");
>> >> try { System.out.println(sef.getEngineVersion() ); } catch (Exception
>> e) { System.out.println("-->
>> >> FAILED!"); } System.out.print ("\tgetExtensions() : "); try {
>> System.out.println(sef.getExtensions
>> >> ()); } catch (Exception e) { System.out.println("--> FAILED!"); }
>> System.out.print
>> >> ("\tgetLanguageName() : "); try { System.out.println(sef.getLanguageName
>> () ); } catch (Exception e)
>> >> { System.out.println("--> FAILED!"); } System.out.print
>> ("\tgetLanguageVersion() : "); try {
>> >> System.out.println(sef.getLanguageVersion()); } catch (Exception e) {
>> System.out.println("-->
>> >> FAILED!"); } System.out.print ("\tgetMimeTypes() : "); try {
>> System.out.println(sef.getMimeTypes
>> >> ()); } catch (Exception e) { System.out.println("--> FAILED!"); }
>> System.out.print ("\tgetNames() :
>> >> "); try { System.out.println(sef.getNames() ); } catch (Exception e)
>> { System.out.println("-->
>> >> FAILED!"); } System.out.print ("\tgetParameter(\"THREADING\"): ");
>> try {
>> >> System.out.println(sef.getParameter("THREADING")); } catch (Exception
>> e) { System.out.println("-->
>> >> FAILED!"); } } // create an output statement and execute output
>> statement for each available 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"); } // allow us to call
>> this from different parts
>> >> static void showHelp() { System.out.println("usage: java RunScript
>> [{-i | -t | -e enginename
>> >> filename [args...] | filename [args...]}]\n"); System.out.println("
>> ... no arguments lists the
>> >> available javax.script engines"); System.out.println(" -h ... 'help',
>> gives this usage text");
>> >> System.out.println(" -i ... lists the available javax.script engines
>> and informs about their
>> >> properties"); System.out.println(" -t ... lists the available
>> javax.script engines and tests
>> >> evaluating their \"getOutputStatement(String)\" method");
>> System.out.println(" -e enginename
>> >> filename [args...] ... uses \"enginename\" to evaluate \"filename\"
>> supplying the arguments
>> >> \"args...\""); System.out.println(" filename [args...] ... the
>> \"filename\" extension determines the
>> >> script engine to evaluate it, supplying the arguments \"args...\"");
>> return; } } ------------------
>> >> cut here ------------------
>> >>
>> >>
>>
>>
>
More information about the nashorn-dev
mailing list