Works properly with html4j revision 6fbd66b88cf6 NbHtml4J
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 09 Jan 2014 11:55:01 +0100
branchNbHtml4J
changeset 1423237dbcd482dc
parent 1422 44330e2e9daa
child 1424 095ce896e094
Works properly with html4j revision 6fbd66b88cf6
ko/fx/src/test/java/org/apidesign/bck2brwsr/kofx/JavaScriptBodyFXBrwsrTest.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/OnMessage.java
launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Run.java
launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsMethods.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ko/fx/src/test/java/org/apidesign/bck2brwsr/kofx/JavaScriptBodyFXBrwsrTest.java	Thu Jan 09 11:55:01 2014 +0100
     1.3 @@ -0,0 +1,36 @@
     1.4 +/**
     1.5 + * Back 2 Browser Bytecode Translator
     1.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     1.7 + *
     1.8 + * This program is free software: you can redistribute it and/or modify
     1.9 + * it under the terms of the GNU General Public License as published by
    1.10 + * the Free Software Foundation, version 2 of the License.
    1.11 + *
    1.12 + * This program is distributed in the hope that it will be useful,
    1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 + * GNU General Public License for more details.
    1.16 + *
    1.17 + * You should have received a copy of the GNU General Public License
    1.18 + * along with this program. Look for COPYING file in the top folder.
    1.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    1.20 + */
    1.21 +package org.apidesign.bck2brwsr.kofx;
    1.22 +
    1.23 +import org.apidesign.bck2brwsr.vmtest.VMTest;
    1.24 +import org.apidesign.html.json.tck.JavaScriptTCK;
    1.25 +import org.apidesign.html.json.tck.KOTest;
    1.26 +import org.testng.annotations.Factory;
    1.27 +
    1.28 +/**
    1.29 + *
    1.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    1.31 + */
    1.32 +public class JavaScriptBodyFXBrwsrTest extends JavaScriptTCK {
    1.33 +    @Factory public static Object[] create() {
    1.34 +        return VMTest.newTests().
    1.35 +            withLaunchers("fxbrwsr").
    1.36 +            withClasses(testClasses()).
    1.37 +            withTestAnnotation(KOTest.class).build();
    1.38 +    }
    1.39 +}
     2.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java	Thu Jan 09 08:21:39 2014 +0100
     2.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java	Thu Jan 09 11:55:01 2014 +0100
     2.3 @@ -25,8 +25,8 @@
     2.4  import java.lang.reflect.Modifier;
     2.5  import java.net.URL;
     2.6  import java.util.Enumeration;
     2.7 +import net.java.html.js.JavaScriptBody;
     2.8  import netscape.javascript.JSObject;
     2.9 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
    2.10  
    2.11  /**
    2.12   *
    2.13 @@ -60,8 +60,7 @@
    2.14      }
    2.15      
    2.16      private static void beginTest(Case c) {
    2.17 -        Object[] arr = new Object[2];
    2.18 -        beginTest(c.getClassName() + "." + c.getMethodName(), c, arr);
    2.19 +        Object[] arr = beginTest(c.getClassName() + "." + c.getMethodName(), c, new Object[2]);
    2.20          textArea = arr[0];
    2.21          statusArea = arr[1];
    2.22      }
    2.23 @@ -102,23 +101,23 @@
    2.24          + "ul.appendChild(li);\n"
    2.25          + "arr[0] = pre;\n"
    2.26          + "arr[1] = status;\n"
    2.27 +        + "return arr;"
    2.28      )
    2.29 -    private static native void beginTest(String test, Case c, Object[] arr);
    2.30 +    private static native Object[] beginTest(String test, Case c, Object[] arr);
    2.31      
    2.32 -    @JavaScriptBody(args = { "url", "callback", "arr" }, body =
    2.33 +    @JavaScriptBody(args = { "url", "callback" }, javacall = true, body =
    2.34            "var request = new XMLHttpRequest();\n"
    2.35          + "request.open('GET', url, true);\n"
    2.36          + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n"
    2.37          + "request.onreadystatechange = function() {\n"
    2.38          + "  if (this.readyState!==4) return;\n"
    2.39          + " try {\n"
    2.40 -        + "  arr[0] = this.responseText;\n"
    2.41 -        + "  callback.run();\n"
    2.42 +        + "  callback.@org.apidesign.bck2brwsr.launcher.fximpl.OnMessage::onMessage(Ljava/lang/String;)(this.responseText);\n"
    2.43          + " } catch (e) { alert(e); }\n"
    2.44          + "};\n"
    2.45          + "request.send();\n"
    2.46      )
    2.47 -    private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
    2.48 +    private static native void loadText(String url, OnMessage callback) throws IOException;
    2.49      
    2.50      public static void runHarness(String url) throws IOException {
    2.51          new Console().harness(url);
    2.52 @@ -129,7 +128,7 @@
    2.53          Request r = new Request(url);
    2.54      }
    2.55      
    2.56 -    private static class Request implements Runnable {
    2.57 +    private static class Request implements Runnable, OnMessage {
    2.58          private final String[] arr = { null };
    2.59          private final String url;
    2.60          private Case c;
    2.61 @@ -137,11 +136,17 @@
    2.62  
    2.63          private Request(String url) throws IOException {
    2.64              this.url = url;
    2.65 -            loadText(url, new Run(this), arr);
    2.66 +            loadText(url, this);
    2.67          }
    2.68          private Request(String url, String u) throws IOException {
    2.69              this.url = url;
    2.70 -            loadText(u, new Run(this), arr);
    2.71 +            loadText(u, this);
    2.72 +        }
    2.73 +
    2.74 +        @Override
    2.75 +        public void onMessage(String msg) {
    2.76 +            arr[0] = msg;
    2.77 +            run();
    2.78          }
    2.79          
    2.80          @Override
    2.81 @@ -177,7 +182,7 @@
    2.82              } catch (Exception ex) {
    2.83                  if (ex instanceof InterruptedException) {
    2.84                      log("Re-scheduling in 100ms");
    2.85 -                    schedule(new Run(this), 100);
    2.86 +                    schedule(this, 100);
    2.87                      return;
    2.88                  }
    2.89                  log(ex.getClass().getName() + ":" + ex.getMessage());
    2.90 @@ -250,7 +255,11 @@
    2.91      private static void turnAssetionStatusOn() {
    2.92      }
    2.93  
    2.94 -    @JavaScriptBody(args = { "r", "time" }, body = "return window.setTimeout(function() { r.run(); }, time);")
    2.95 +    @JavaScriptBody(args = { "r", "time" }, javacall = true, body = 
    2.96 +        "return window.setTimeout(function() { "
    2.97 +        + "r.@java.lang.Runnable::run()(); "
    2.98 +        + "}, time);"
    2.99 +    )
   2.100      private static native Object schedule(Runnable r, int time);
   2.101      
   2.102      private static final class Case {
     3.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java	Thu Jan 09 08:21:39 2014 +0100
     3.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java	Thu Jan 09 11:55:01 2014 +0100
     3.3 @@ -25,6 +25,10 @@
     3.4  import java.util.Collection;
     3.5  import java.util.List;
     3.6  import java.util.TooManyListenersException;
     3.7 +import java.util.concurrent.Executor;
     3.8 +import java.util.logging.Level;
     3.9 +import java.util.logging.Logger;
    3.10 +import javafx.application.Platform;
    3.11  import javafx.beans.value.ChangeListener;
    3.12  import javafx.scene.web.WebEngine;
    3.13  import netscape.javascript.JSObject;
    3.14 @@ -37,6 +41,8 @@
    3.15   * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.16   */
    3.17  public final class JVMBridge {
    3.18 +    static final Logger LOG = Logger.getLogger(JVMBridge.class.getName());
    3.19 +    
    3.20      private final WebEngine engine;
    3.21      private final ClassLoader cl;
    3.22      private final WebPresenter presenter;
    3.23 @@ -74,7 +80,8 @@
    3.24          return Class.forName(name, true, cl);
    3.25      }
    3.26      
    3.27 -    private final class WebPresenter implements FindResources, Fn.Presenter {
    3.28 +    private final class WebPresenter 
    3.29 +    implements FindResources, Fn.Presenter, Fn.ToJavaScript, Executor {
    3.30          @Override
    3.31          public void findResources(String name, Collection<? super URL> results, boolean oneIsEnough) {
    3.32              if (ldrs != null) for (ClassLoader l : ldrs) {
    3.33 @@ -87,6 +94,9 @@
    3.34  
    3.35          @Override
    3.36          public Fn defineFn(String code, String... names) {
    3.37 +            return defineJSFn(code, names);
    3.38 +        }
    3.39 +        private JSFn defineJSFn(String code, String... names) {
    3.40              StringBuilder sb = new StringBuilder();
    3.41              sb.append("(function() {");
    3.42              sb.append("  return function(");
    3.43 @@ -122,6 +132,86 @@
    3.44              }
    3.45              engine.executeScript(sb.toString());
    3.46          }
    3.47 +
    3.48 +        @Override
    3.49 +        public Object toJavaScript(Object toReturn) {
    3.50 +            if (toReturn instanceof Object[]) {
    3.51 +                return convertArrays((Object[]) toReturn);
    3.52 +            }
    3.53 +            return toReturn;
    3.54 +        }
    3.55 +
    3.56 +        @Override
    3.57 +        public void execute(Runnable command) {
    3.58 +            if (Platform.isFxApplicationThread()) {
    3.59 +                command.run();
    3.60 +            } else {
    3.61 +                Platform.runLater(command);
    3.62 +            }
    3.63 +        }
    3.64 +        
    3.65 +        final JSObject convertArrays(Object[] arr) {
    3.66 +            for (int i = 0; i < arr.length; i++) {
    3.67 +                if (arr[i] instanceof Object[]) {
    3.68 +                    arr[i] = convertArrays((Object[]) arr[i]);
    3.69 +                }
    3.70 +            }
    3.71 +            final JSObject wrapArr = (JSObject) wrapArrFn().call("array", arr); // NOI18N
    3.72 +            return wrapArr;
    3.73 +        }
    3.74 +
    3.75 +        private JSObject wrapArrImpl;
    3.76 +
    3.77 +        private final JSObject wrapArrFn() {
    3.78 +            if (wrapArrImpl == null) {
    3.79 +                try {
    3.80 +                    wrapArrImpl = (JSObject) defineJSFn("  var k = {};"
    3.81 +                        + "  k.array= function() {"
    3.82 +                        + "    return Array.prototype.slice.call(arguments);"
    3.83 +                        + "  };"
    3.84 +                        + "  return k;"
    3.85 +                    ).invokeImpl(null, false);
    3.86 +                } catch (Exception ex) {
    3.87 +                    throw new IllegalStateException(ex);
    3.88 +                }
    3.89 +            }
    3.90 +            return wrapArrImpl;
    3.91 +        }
    3.92 +
    3.93 +        final Object checkArray(Object val) {
    3.94 +            int length = ((Number) arraySizeFn().call("array", val, null)).intValue();
    3.95 +            if (length == -1) {
    3.96 +                return val;
    3.97 +            }
    3.98 +            Object[] arr = new Object[length];
    3.99 +            arraySizeFn().call("array", val, arr);
   3.100 +            return arr;
   3.101 +        }
   3.102 +        private JSObject arraySize;
   3.103 +
   3.104 +        private final JSObject arraySizeFn() {
   3.105 +            if (arraySize == null) {
   3.106 +                try {
   3.107 +                    arraySize = (JSObject) defineJSFn("  var k = {};"
   3.108 +                        + "  k.array = function(arr, to) {"
   3.109 +                        + "    if (to === null) {"
   3.110 +                        + "      if (Object.prototype.toString.call(arr) === '[object Array]') return arr.length;"
   3.111 +                        + "      else return -1;"
   3.112 +                        + "    } else {"
   3.113 +                        + "      var l = arr.length;"
   3.114 +                        + "      for (var i = 0; i < l; i++) to[i] = arr[i];"
   3.115 +                        + "      return l;"
   3.116 +                        + "    }"
   3.117 +                        + "  };"
   3.118 +                        + "  return k;"
   3.119 +                    ).invokeImpl(null, false);
   3.120 +                } catch (Exception ex) {
   3.121 +                    throw new IllegalStateException(ex);
   3.122 +                }
   3.123 +            }
   3.124 +            return arraySize;
   3.125 +        }
   3.126 +        
   3.127      }
   3.128      
   3.129      private static final class JSFn extends Fn {
   3.130 @@ -134,12 +224,29 @@
   3.131  
   3.132          @Override
   3.133          public Object invoke(Object thiz, Object... args) throws Exception {
   3.134 +            return invokeImpl(thiz, true, args);
   3.135 +        }
   3.136 +
   3.137 +        final Object invokeImpl(Object thiz, boolean arrayChecks, Object... args) throws Exception {
   3.138              try {
   3.139                  List<Object> all = new ArrayList<Object>(args.length + 1);
   3.140                  all.add(thiz == null ? fn : thiz);
   3.141 -                all.addAll(Arrays.asList(args));
   3.142 +                for (int i = 0; i < args.length; i++) {
   3.143 +                    if (arrayChecks && args[i] instanceof Object[]) {
   3.144 +                        Object[] arr = (Object[]) args[i];
   3.145 +                        Object conv = ((WebPresenter) presenter()).convertArrays(arr);
   3.146 +                        args[i] = conv;
   3.147 +                    }
   3.148 +                    all.add(args[i]);
   3.149 +                }
   3.150                  Object ret = fn.call("call", all.toArray()); // NOI18N
   3.151 -                return ret == fn ? null : ret;
   3.152 +                if (ret == fn) {
   3.153 +                    return null;
   3.154 +                }
   3.155 +                if (!arrayChecks) {
   3.156 +                    return ret;
   3.157 +                }
   3.158 +                return ((WebPresenter) presenter()).checkArray(ret);
   3.159              } catch (Error t) {
   3.160                  t.printStackTrace();
   3.161                  throw t;
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/OnMessage.java	Thu Jan 09 11:55:01 2014 +0100
     4.3 @@ -0,0 +1,26 @@
     4.4 +/**
     4.5 + * Back 2 Browser Bytecode Translator
     4.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.7 + *
     4.8 + * This program is free software: you can redistribute it and/or modify
     4.9 + * it under the terms of the GNU General Public License as published by
    4.10 + * the Free Software Foundation, version 2 of the License.
    4.11 + *
    4.12 + * This program is distributed in the hope that it will be useful,
    4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.15 + * GNU General Public License for more details.
    4.16 + *
    4.17 + * You should have received a copy of the GNU General Public License
    4.18 + * along with this program. Look for COPYING file in the top folder.
    4.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    4.20 + */
    4.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
    4.22 +
    4.23 +/**
    4.24 + *
    4.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    4.26 + */
    4.27 +interface OnMessage {
    4.28 +    public void onMessage(String msg);
    4.29 +}
     5.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Run.java	Thu Jan 09 08:21:39 2014 +0100
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,35 +0,0 @@
     5.4 -/**
     5.5 - * Back 2 Browser Bytecode Translator
     5.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.7 - *
     5.8 - * This program is free software: you can redistribute it and/or modify
     5.9 - * it under the terms of the GNU General Public License as published by
    5.10 - * the Free Software Foundation, version 2 of the License.
    5.11 - *
    5.12 - * This program is distributed in the hope that it will be useful,
    5.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 - * GNU General Public License for more details.
    5.16 - *
    5.17 - * You should have received a copy of the GNU General Public License
    5.18 - * along with this program. Look for COPYING file in the top folder.
    5.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
    5.20 - */
    5.21 -
    5.22 -package org.apidesign.bck2brwsr.launcher.fximpl;
    5.23 -
    5.24 -/**
    5.25 - *
    5.26 - * @author Jaroslav Tulach <jtulach@netbeans.org>
    5.27 - */
    5.28 -public final class Run implements Runnable {
    5.29 -    private final Runnable r;
    5.30 -    Run(Runnable r) {
    5.31 -        this.r = r;
    5.32 -    }
    5.33 -
    5.34 -    @Override
    5.35 -    public void run() {
    5.36 -        r.run();
    5.37 -    }
    5.38 -}
     6.1 --- a/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsMethods.java	Thu Jan 09 08:21:39 2014 +0100
     6.2 +++ b/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsMethods.java	Thu Jan 09 11:55:01 2014 +0100
     6.3 @@ -17,7 +17,7 @@
     6.4   */
     6.5  package org.apidesign.bck2brwsr.launcher.fximpl;
     6.6  
     6.7 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
     6.8 +import net.java.html.js.JavaScriptBody;
     6.9  
    6.10  /**
    6.11   *