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 *