Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8245873

FXMLLoader: if script engines implement javax.script.Compilable compile scripts

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • jfx15
    • javafx
    • None
    • source, binary, behavioral
    • low
    • Hide
      It is possible that a buggy script engine might misbehave when compiled in such a way that it doesn't fail (and thus doesn't fallback to existing interpreted mode), but that could lead to differences in behavior. To mitigate this, a new processing instruction is added to FXML to optionally disable compilation.
      Show
      It is possible that a buggy script engine might misbehave when compiled in such a way that it doesn't fail (and thus doesn't fallback to existing interpreted mode), but that could lead to differences in behavior. To mitigate this, a new processing instruction is added to FXML to optionally disable compilation.
    • Java API, File or wire format
    • JDK

      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" processing instruction (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 processing 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" processing instruction ("<?compile false?>" or "<?compile true?>") gets defined that allows to turn compilation off and on throughout a FXML file.

      Additions to introduction_to_fxml:

      Event Handling section:

      Note: to turn off automatic compilation of script code place the processing instruction <?compile false?> before the element that contains the script. To turn on compilation of script code again use the processing instruction <?compile true?> (or short: <?compile?>). The compile processing instruction can be used repeatedly to turn compilation of script code off and on.

      Scripting section:

      Scripts are compiled by default, when they are first loaded, if the ScriptEngine implements the javax.script.Compilable interface. If compilation fails, the FXMLLoader will fall back to interpreted mode.

      Note: to turn off automatic compilation of script code place the processing instruction <?compile false?> before the script element. To turn on compilation of script code again use the processing instruction <?compile true?> (or short: <?compile?>). The compile processing instruction can be used repeatedly to turn compilation of script code off and on.

      Spec diffs:

      javafx/fxml/doc-files/introduction_to_fxml.html

      @@ -641,6 +641,8 @@ myText = This is the text!
      
       <p>Note the use of the language processing instruction at the beginning of the code snippet. This PI tells the FXML loader which scripting language should be used to execute the event handler. A page language must be specified whenever inline script is used in an FXML document, and can only be specified once per document. However, this does not apply to external scripts, which may be implemented using any number of supported scripting languages. Scripting is discussed in more detail in the next section.</p>
      
      +<p>Note: to turn off automatic compilation of script code place the processing instruction <span class="code">&lt;?compile false?&gt;</span> before the element that contains the script. To turn on compilation of script code again use the processing instruction <span class="code">&lt;?compile true?&gt;</span> (or short: <span class="code">&lt;?compile?&gt;</span>). The compile processing instruction can be used repeatedly to turn compilation of script code off and on.</p>
      +
       <h4><a id="controller_method_event_handlers">Controller Method Event Handlers</a></h4>
       <p>A controller method event handler is a method defined by a document's "controller". A controller is an object that is associated with the deserialized contents of an FXML document and is responsible for coordinating the behaviors of the objects (often user interface elements) defined by the document.</p>
      
      @@ -770,7 +772,11 @@ attribute must be used.</p>
       <p>
       The <span class="code">&lt;fx:script&gt;</span> tag allows a caller to import scripting code into or embed script within a FXML file. Any JVM scripting language can be used, including JavaScript, Groovy, and Clojure, among others. Script code is often used to define event handlers directly in markup or in an associated source file, since event handlers can often be written more concisely in more loosely-typed scripting languages than they can in a statically-typed language such as Java.</p>
      
      -<p>For example, the following markup defines a function called <span class="code">handleButtonAction()</span> that is called by the action handler attached to the <span class="code">Button</span> element:</p>
      +<p>Scripts are compiled by default, when they are first loaded, if the <span class="code">ScriptEngine</span> implements the <span class="code">javax.script.Compilable</span> interface. If compilation fails, the <span class="code">FXMLLoader</span> will fall back to interpreted mode.</p>
      +
      +<p>Note: to turn off automatic compilation of script code place the processing instruction <span class="code">&lt;?compile false?&gt;</span> before the script element. To turn on compilation of script code again use the processing instruction <span class="code">&lt;?compile true?&gt;</span> (or short: <span class="code">&lt;?compile?&gt;</span>). The compile processing instruction can be used repeatedly to turn compilation of script code off and on.</p>
      +
      +<p>The following example markup defines a function called <span class="code">handleButtonAction()</span> that is called by the action handler attached to the <span class="code">Button</span> element:</p>
      
       <pre class="code">
       &lt;?language javascript?&gt;
      @@ -798,6 +804,8 @@ The <span class="code">&lt;fx:script&gt;</span> tag allows a caller to import sc
      
       <div class="caption">example.fxml</div>
       <pre class="code">
      +&lt;?language javascript?&gt;
      +
       &lt;?import javafx.scene.control.*?&gt;
       &lt;?import javafx.scene.layout.*?&gt;
      

      javafx/fxml/FXMLLoader.java

      +    /**
      +     * The tag name of the compile processing instruction.
      +     * @since 15
      +     */
      +    public static final String COMPILE_PROCESSING_INSTRUCTION = "compile";
      

            kcr Kevin Rushforth
            webbuggrp Webbug Group
            Ajit Ghaisas, Kevin Rushforth
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: