RFR: 8238080: FXMLLoader: if script engines implement javax.script.Compilable compile scripts
Rony G.Flatscher
github.com+60214806+ronyfla at openjdk.java.net
Tue May 12 16:55:17 UTC 2020
On Sat, 9 May 2020 15:15:52 GMT, Kevin Rushforth <kcr at openjdk.org> wrote:
>> ============================ test units for: compile PI+fallback
>>
>> tests/system/src/testscriptapp2/java/mymod/myapp2/FXMLScriptDeployment2Compile_Off.java
>> ... use compile PI to set off compilation of scripts; each script code starts with "demo_02_"
>>
>> tests/system/src/testscriptapp2/resources/mymod/myapp2/demo_02_off.fxml
>> ... set compilation for scripts off ("<?compile false?>"), therefore no script gets compiled
>>
>> ---
>>
>> tests/system/src/testscriptapp2/java/mymod/myapp2/FXMLScriptDeployment2Compile_Off_On.java
>> ... alternatively uses compile PI to turn compilation off and on; the script code starts alternatively with "demo_02_"
>> and "RgfPseudoCompiledScript.eval(", depending on the state set with the PI
>> tests/system/src/testscriptapp2/resources/mymod/myapp2/demo_02_off_on.fxml
>> ... starts out explicitly with "<?compile false?>" switching the state after each element containing a script
>>
>> ---
>>
>> tests/system/src/testscriptapp2/java/mymod/myapp2/FXMLScriptDeployment2Compile_On.java
>> ... no compile PI given, hence compilation of scripts is on; each script code starts with
>> "RgfPseudoCompiledScript.eval("
>> tests/system/src/testscriptapp2/resources/mymod/myapp2/demo_02_on.fxml
>> ... no compile PI given, starts out to compile scripts by default
>>
>> ---
>>
>> tests/system/src/testscriptapp2/java/mymod/myapp2/FXMLScriptDeployment2Compile_On_Off.java
>> ... alternatively uses compile PI to turn compilation on and off; the script code starts alternatively with
>> "RgfPseudoCompiledScript.eval(", and "demo_02_" depending on the state set with the PI
>> tests/system/src/testscriptapp2/resources/mymod/myapp2/demo_02_on_off.fxml
>> ... starts out explicitly with "<?compile true?>" switching the state after each element containing a script (sometimes
>> using PI "<?compile?>" to test setting it to true)
>> ---
>>
>> tests/system/src/testscriptapp2/java/mymod/myapp2/FXMLScriptDeployment2Compile_Fail_Compilation.java
>> ... although compile scripts is on, none of the scripts get compiled as they all contain the string "FAIL COMPILATION"
>> which causes RgfPseudoScriptEngineCompilable.compile(...) to throw a ScriptException causing the fallback to be used;
>> all scripts therefore start with "demo_03_"
>> tests/system/src/testscriptapp2/resources/mymod/myapp2/demo_03_fail_compile.fxml
>> ... explicitly turns on compilation (which is on by default anyway), adds "FAIL COMPILATION" to all inline scripts and
>> to all external scripts with the filename that starts with "demo_03_"
>
> I think the approach proposed in this PR is the best solution for this enhancement. Go ahead and remove the `WIP` from
> the title, and we can proceed with the review.
> The interface and behavior change will need to be specified in the API docs. This can be done by modifying the
> [Introduction to
> FXML](https://github.com/openjdk/jfx/blob/master/modules/javafx.fxml/src/main/docs/javafx/fxml/doc-files/introduction_to_fxml.html)
> document. I recommend documenting the new behavior and `<?compile>` attribute somewhere in the
> [Scripting](https://github.com/openjdk/jfx/blob/master/modules/javafx.fxml/src/main/docs/javafx/fxml/doc-files/introduction_to_fxml.html#L769)
> section. As discussed on the mailing list, this will need a CSR, which should include the changes to the docs.
Suggested CSR:
Summary
=======
Have javafx.fxml.FXMLLoader compile FXML scripts before evaluating them, if the script engine
implements the javax.script.Compilable interface to speed up execution. In case compilation
throws a javax.script.ScriptException fall back to evaluating the uncompiled script. Allow
control of script compilation with a "compile" PI for FXML files.
Problem
=======
javafx.fxml.FXMLLoader is able to execute scripts in Java script languages
(javax.script.ScriptEngine implementations) referred to or embedded in a FXML file.
If a script engine implements the javax.script.Compilable interface, then such scripts could be
compiled and the resulting javax.script.CompiledScript could be executed instead using its
eval() methods.
Evaluating the javax.script.CompiledScript objects may help speed up the execution of script
invocations, especially for scripts defined for event attributes in FXML elements (e.g. like
onMouseMove) which may be repetitively invoked and evaluated.
Solution
========
Before evaluating the script code test whether the javax.script.ScriptEngine implements
javax.script.Compilable. If so, compile the script to a javax.script.CompiledScript object first
and then use its eval() method to evaluate the script, otherwise continue to use the
javax.script.ScriptEngine's eval() method instead. Should compilation of a script yield
(unexpectedly) a javax.script.ScriptException then fall back to using the
javax.script.ScriptEngine's eval() method. A new process instruction "compile" allows control of
the compilation of scripts ("true" sets compilation on, "false" to set compilation off) in FXML
files.
Specification
=============
If a javax.script.ScriptEngine implements the javax.script.Compilable interface, then use its
compile() method to compile the script to a javax.script.CompiledScript object and use its
eval() method to run the script. In the case that the compilation throws (unexpectedly) a
javax.script.ScriptException log a warning and fall back to using the
javax.script.ScriptEngine's eval() method instead.
To allow setting this feature off and on while processing the FXML file a "compile" process
instruction ("<?compile false?>" or "<?compile true?>") gets defined that allows to turn
compilation off and on throughout a FXML file.
-------------
PR: https://git.openjdk.java.net/jfx/pull/192
More information about the openjfx-dev
mailing list