All classes loaded through the 'vm' object will have 'invoke' method that can be used to invoke static methods like main(String[]), so our examples no longer need to rely on initialization in static initializers. closure
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 28 May 2014 10:47:18 +0200
branchclosure
changeset 1609752f48257d4a
parent 1608 5186733b7e07
child 1610 a6f807104d8e
All classes loaded through the 'vm' object will have 'invoke' method that can be used to invoke static methods like main(String[]), so our examples no longer need to rely on initialization in static initializers.
javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java
javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml
rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java
     1.1 --- a/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java	Wed May 28 09:07:48 2014 +0200
     1.2 +++ b/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java	Wed May 28 10:47:18 2014 +0200
     1.3 @@ -39,7 +39,7 @@
     1.4      @Property(name = "history", type = double.class, array = true)
     1.5  })
     1.6  public class Calc {
     1.7 -    static {
     1.8 +    public static void main(String... args) throws Exception {
     1.9          new Calculator().applyBindings().setOperation("plus");
    1.10      }
    1.11      
     2.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml	Wed May 28 09:07:48 2014 +0200
     2.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml	Wed May 28 10:47:18 2014 +0200
     2.3 @@ -92,7 +92,8 @@
     2.4          <script src="bck2brwsr.js"></script>
     2.5          <script>
     2.6              var vm = bck2brwsr('calculator.js');
     2.7 -            vm.loadClass('org.apidesign.bck2brwsr.demo.calc.staticcompilation.Calc');
     2.8 +            var c = vm.loadClass('org.apidesign.bck2brwsr.demo.calc.staticcompilation.Calc');
     2.9 +            c.invoke('main');
    2.10          </script>
    2.11      </body>
    2.12  </html>
     3.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Wed May 28 09:07:48 2014 +0200
     3.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Wed May 28 10:47:18 2014 +0200
     3.3 @@ -26,7 +26,7 @@
     3.4   * be used to bootstrap and load the virtual machine: <pre>
     3.5   * var vm = bck2brwsr();
     3.6   * var main = vm.loadClass('org.your.pkg.Main');
     3.7 - * main.main__V_3Ljava_lang_String_2(null);
     3.8 + * main.invoke('main');
     3.9   * </pre>
    3.10   * In case one wants to initialize the virtual machine with ability to
    3.11   * load classes lazily when needed, one can provide a loader function to
    3.12 @@ -39,15 +39,27 @@
    3.13   * function is asked for its byte code and the system dynamically transforms
    3.14   * it to JavaScript.
    3.15   * <p>
    3.16 - * Instead of a loader function, one can also provide a URL to a JAR file.
    3.17 + * Instead of a loader function, one can also provide a URL to a JAR file
    3.18 + * or a library JavaScript file generated with {@link #library(java.lang.String...)}
    3.19 + * option on.
    3.20   * The <code>bck2brwsr</code> system will do its best to download the file
    3.21 - * and provide loader function for it automatically.
    3.22 + * and provide loader function for it automatically. In order to use
    3.23 + * the JAR file <code>emul.zip</code> module needs to be available in the system.
    3.24   * <p>
    3.25 - * One can provide as many loader functions and JAR URL references as necessary.
    3.26 + * One can provide as many loader functions and URL references as necessary.
    3.27   * Then the initialization code would look like:<pre>
    3.28   * var vm = bck2brwsr(url1, url2, fnctn1, url3, functn2);
    3.29   * </pre>
    3.30   * The provided URLs and loader functions will be consulted one by one.
    3.31 + * <p>
    3.32 + * The initialization of the <b>Bck2Brwsr</b> is done asynchronously since 
    3.33 + * version 0.9. E.g. call to <pre>
    3.34 + * var vm = bck2brwsr('myapp.js');
    3.35 + * var main = vm.loadClass('org.your.pkg.Main');
    3.36 + * main.invoke('main');
    3.37 + * </pre>
    3.38 + * returns immediately and the call to the static main method will happen
    3.39 + * once the virtual machine is initialized and the class available.
    3.40   *
    3.41   * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.42   */
     4.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Wed May 28 09:07:48 2014 +0200
     4.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Wed May 28 10:47:18 2014 +0200
     4.3 @@ -493,14 +493,28 @@
     4.4                  + "    var at = pending.indexOf(ev.target);\n"
     4.5                  + "    pending.splice(at, 1);\n"
     4.6                  + "    if (pending.length === 0) {\n"
     4.7 -                + "      for (var i = 0; i < pendingClasses.length; i += 2) {\n"
     4.8 -                + "        var vm = pendingClasses[i];\n"
     4.9 -                + "        var n = pendingClasses[i + 1];\n"
    4.10 -                + "        vm.loadClass(n);\n"
    4.11 +                + "      for (var i = 0; i < pendingClasses.length; i += 3) {\n"
    4.12 +                + "        invokeMethod(pendingClasses[i], pendingClasses[i + 1], pendingClasses[i + 2]);\n"
    4.13                  + "      }\n"
    4.14                  + "      pendingClasses = [];\n"
    4.15                  + "    }\n"
    4.16                  + "  }\n"
    4.17 +                + "  function invokeMethod(vm, n, args) {\n"
    4.18 +                + "    var clazz = vm.loadClass(n);\n"
    4.19 +                + "    if (args) {\n"
    4.20 +                + "      var seek = args[0];\n"
    4.21 +                + "      var prefix = seek.indexOf('__') == -1 ? seek + '__' : seek;\n"
    4.22 +                + "      args = Array.prototype.slice.call(args, 1);\n"
    4.23 +                + "      var found = '';\n"
    4.24 +                + "      for (var m in clazz) {\n"
    4.25 +                + "        if (m.indexOf(prefix) === 0) {\n"
    4.26 +                + "          return clazz[m].apply(null, args);\n"
    4.27 +                + "        }\n"
    4.28 +                + "        found += m.toString() + '\\n'\n"
    4.29 +                + "      }\n"
    4.30 +                + "      throw 'Cannot find ' + seek + ' in ' + n + ' found:\\n' + found;\n"
    4.31 +                + "    }\n"
    4.32 +                + "  }\n"
    4.33                  + "  function extensionError(ev) {\n"
    4.34                  + "    console.log('error loading ' + ev.target.src);\n"
    4.35                  + "    extensionLoaded(ev);\n"
    4.36 @@ -611,14 +625,29 @@
    4.37                  + "    loader.loadClass = function(name) {\n"
    4.38                  + "      if (pending.length === 0) {\n"
    4.39                  + "        try {\n"
    4.40 -                + "          return loadClass(name);\n"
    4.41 +                + "          var c = loadClass(name);\n"
    4.42 +                + "          c['invoke'] = function() {\n"
    4.43 +                + "            return invokeMethod(vm, name, arguments);\n"
    4.44 +                + "          };\n"
    4.45 +                + "          return c;\n"
    4.46                  + "        } catch (err) {\n"
    4.47                  + "          if (pending.length === 0) throw err;\n"
    4.48                  + "        }\n"
    4.49                  + "      }\n"
    4.50                  + "      pendingClasses.push(vm);\n"
    4.51                  + "      pendingClasses.push(name);\n"
    4.52 -                + "      return null;\n"
    4.53 +                + "      pendingClasses.push(null);\n"
    4.54 +                + "      return {\n"
    4.55 +                + "        'invoke' : function() {\n"
    4.56 +                + "          if (pending.length === 0) {\n"
    4.57 +                + "            invokeMethod(vm, name, arguments);\n"
    4.58 +                + "            return;\n"
    4.59 +                + "          }\n"
    4.60 +                + "          pendingClasses.push(vm);\n"
    4.61 +                + "          pendingClasses.push(name);\n"
    4.62 +                + "          pendingClasses.push(arguments);\n"
    4.63 +                + "        }\n"
    4.64 +                + "      };\n"
    4.65                  + "    }\n"
    4.66                  + "    return loader;\n"
    4.67                  + "  };\n");
     5.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java	Wed May 28 09:07:48 2014 +0200
     5.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java	Wed May 28 10:47:18 2014 +0200
     5.3 @@ -23,7 +23,10 @@
     5.4  import java.io.IOException;
     5.5  import java.io.InputStream;
     5.6  import java.net.URL;
     5.7 +import java.util.ArrayList;
     5.8 +import java.util.Arrays;
     5.9  import java.util.Enumeration;
    5.10 +import java.util.List;
    5.11  import javax.script.Invocable;
    5.12  import javax.script.ScriptContext;
    5.13  import javax.script.ScriptEngine;
    5.14 @@ -60,7 +63,10 @@
    5.15          Object ret = null;
    5.16          try {
    5.17              ret = code.invokeMethod(bck2brwsr, "loadClass", clazz.getName());
    5.18 -            ret = code.invokeMethod(ret, method, args);
    5.19 +            List<Object> ma = new ArrayList<>();
    5.20 +            ma.add(method);
    5.21 +            ma.addAll(Arrays.asList(args));
    5.22 +            ret = code.invokeMethod(ret, "invoke", ma.toArray());
    5.23          } catch (ScriptException ex) {
    5.24              fail("Execution failed in " + dumpJS(codeSeq) + ": " + ex.getMessage(), ex);
    5.25          } catch (NoSuchMethodException ex) {