# HG changeset patch # User Jaroslav Tulach # Date 1389264901 -3600 # Node ID 237dbcd482dc72b720edd4be98e0631fb0fab6d0 # Parent 44330e2e9daa171c4cf8cf6347642ae53a624896 Works properly with html4j revision 6fbd66b88cf6 diff -r 44330e2e9daa -r 237dbcd482dc ko/fx/src/test/java/org/apidesign/bck2brwsr/kofx/JavaScriptBodyFXBrwsrTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ko/fx/src/test/java/org/apidesign/bck2brwsr/kofx/JavaScriptBodyFXBrwsrTest.java Thu Jan 09 11:55:01 2014 +0100 @@ -0,0 +1,36 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.kofx; + +import org.apidesign.bck2brwsr.vmtest.VMTest; +import org.apidesign.html.json.tck.JavaScriptTCK; +import org.apidesign.html.json.tck.KOTest; +import org.testng.annotations.Factory; + +/** + * + * @author Jaroslav Tulach + */ +public class JavaScriptBodyFXBrwsrTest extends JavaScriptTCK { + @Factory public static Object[] create() { + return VMTest.newTests(). + withLaunchers("fxbrwsr"). + withClasses(testClasses()). + withTestAnnotation(KOTest.class).build(); + } +} diff -r 44330e2e9daa -r 237dbcd482dc launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java Thu Jan 09 08:21:39 2014 +0100 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java Thu Jan 09 11:55:01 2014 +0100 @@ -25,8 +25,8 @@ import java.lang.reflect.Modifier; import java.net.URL; import java.util.Enumeration; +import net.java.html.js.JavaScriptBody; import netscape.javascript.JSObject; -import org.apidesign.bck2brwsr.core.JavaScriptBody; /** * @@ -60,8 +60,7 @@ } private static void beginTest(Case c) { - Object[] arr = new Object[2]; - beginTest(c.getClassName() + "." + c.getMethodName(), c, arr); + Object[] arr = beginTest(c.getClassName() + "." + c.getMethodName(), c, new Object[2]); textArea = arr[0]; statusArea = arr[1]; } @@ -102,23 +101,23 @@ + "ul.appendChild(li);\n" + "arr[0] = pre;\n" + "arr[1] = status;\n" + + "return arr;" ) - private static native void beginTest(String test, Case c, Object[] arr); + private static native Object[] beginTest(String test, Case c, Object[] arr); - @JavaScriptBody(args = { "url", "callback", "arr" }, body = + @JavaScriptBody(args = { "url", "callback" }, javacall = true, body = "var request = new XMLHttpRequest();\n" + "request.open('GET', url, true);\n" + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n" + "request.onreadystatechange = function() {\n" + " if (this.readyState!==4) return;\n" + " try {\n" - + " arr[0] = this.responseText;\n" - + " callback.run();\n" + + " callback.@org.apidesign.bck2brwsr.launcher.fximpl.OnMessage::onMessage(Ljava/lang/String;)(this.responseText);\n" + " } catch (e) { alert(e); }\n" + "};\n" + "request.send();\n" ) - private static native void loadText(String url, Runnable callback, String[] arr) throws IOException; + private static native void loadText(String url, OnMessage callback) throws IOException; public static void runHarness(String url) throws IOException { new Console().harness(url); @@ -129,7 +128,7 @@ Request r = new Request(url); } - private static class Request implements Runnable { + private static class Request implements Runnable, OnMessage { private final String[] arr = { null }; private final String url; private Case c; @@ -137,11 +136,17 @@ private Request(String url) throws IOException { this.url = url; - loadText(url, new Run(this), arr); + loadText(url, this); } private Request(String url, String u) throws IOException { this.url = url; - loadText(u, new Run(this), arr); + loadText(u, this); + } + + @Override + public void onMessage(String msg) { + arr[0] = msg; + run(); } @Override @@ -177,7 +182,7 @@ } catch (Exception ex) { if (ex instanceof InterruptedException) { log("Re-scheduling in 100ms"); - schedule(new Run(this), 100); + schedule(this, 100); return; } log(ex.getClass().getName() + ":" + ex.getMessage()); @@ -250,7 +255,11 @@ private static void turnAssetionStatusOn() { } - @JavaScriptBody(args = { "r", "time" }, body = "return window.setTimeout(function() { r.run(); }, time);") + @JavaScriptBody(args = { "r", "time" }, javacall = true, body = + "return window.setTimeout(function() { " + + "r.@java.lang.Runnable::run()(); " + + "}, time);" + ) private static native Object schedule(Runnable r, int time); private static final class Case { diff -r 44330e2e9daa -r 237dbcd482dc launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java Thu Jan 09 08:21:39 2014 +0100 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java Thu Jan 09 11:55:01 2014 +0100 @@ -25,6 +25,10 @@ import java.util.Collection; import java.util.List; import java.util.TooManyListenersException; +import java.util.concurrent.Executor; +import java.util.logging.Level; +import java.util.logging.Logger; +import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.scene.web.WebEngine; import netscape.javascript.JSObject; @@ -37,6 +41,8 @@ * @author Jaroslav Tulach */ public final class JVMBridge { + static final Logger LOG = Logger.getLogger(JVMBridge.class.getName()); + private final WebEngine engine; private final ClassLoader cl; private final WebPresenter presenter; @@ -74,7 +80,8 @@ return Class.forName(name, true, cl); } - private final class WebPresenter implements FindResources, Fn.Presenter { + private final class WebPresenter + implements FindResources, Fn.Presenter, Fn.ToJavaScript, Executor { @Override public void findResources(String name, Collection results, boolean oneIsEnough) { if (ldrs != null) for (ClassLoader l : ldrs) { @@ -87,6 +94,9 @@ @Override public Fn defineFn(String code, String... names) { + return defineJSFn(code, names); + } + private JSFn defineJSFn(String code, String... names) { StringBuilder sb = new StringBuilder(); sb.append("(function() {"); sb.append(" return function("); @@ -122,6 +132,86 @@ } engine.executeScript(sb.toString()); } + + @Override + public Object toJavaScript(Object toReturn) { + if (toReturn instanceof Object[]) { + return convertArrays((Object[]) toReturn); + } + return toReturn; + } + + @Override + public void execute(Runnable command) { + if (Platform.isFxApplicationThread()) { + command.run(); + } else { + Platform.runLater(command); + } + } + + final JSObject convertArrays(Object[] arr) { + for (int i = 0; i < arr.length; i++) { + if (arr[i] instanceof Object[]) { + arr[i] = convertArrays((Object[]) arr[i]); + } + } + final JSObject wrapArr = (JSObject) wrapArrFn().call("array", arr); // NOI18N + return wrapArr; + } + + private JSObject wrapArrImpl; + + private final JSObject wrapArrFn() { + if (wrapArrImpl == null) { + try { + wrapArrImpl = (JSObject) defineJSFn(" var k = {};" + + " k.array= function() {" + + " return Array.prototype.slice.call(arguments);" + + " };" + + " return k;" + ).invokeImpl(null, false); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + return wrapArrImpl; + } + + final Object checkArray(Object val) { + int length = ((Number) arraySizeFn().call("array", val, null)).intValue(); + if (length == -1) { + return val; + } + Object[] arr = new Object[length]; + arraySizeFn().call("array", val, arr); + return arr; + } + private JSObject arraySize; + + private final JSObject arraySizeFn() { + if (arraySize == null) { + try { + arraySize = (JSObject) defineJSFn(" var k = {};" + + " k.array = function(arr, to) {" + + " if (to === null) {" + + " if (Object.prototype.toString.call(arr) === '[object Array]') return arr.length;" + + " else return -1;" + + " } else {" + + " var l = arr.length;" + + " for (var i = 0; i < l; i++) to[i] = arr[i];" + + " return l;" + + " }" + + " };" + + " return k;" + ).invokeImpl(null, false); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } + return arraySize; + } + } private static final class JSFn extends Fn { @@ -134,12 +224,29 @@ @Override public Object invoke(Object thiz, Object... args) throws Exception { + return invokeImpl(thiz, true, args); + } + + final Object invokeImpl(Object thiz, boolean arrayChecks, Object... args) throws Exception { try { List all = new ArrayList(args.length + 1); all.add(thiz == null ? fn : thiz); - all.addAll(Arrays.asList(args)); + for (int i = 0; i < args.length; i++) { + if (arrayChecks && args[i] instanceof Object[]) { + Object[] arr = (Object[]) args[i]; + Object conv = ((WebPresenter) presenter()).convertArrays(arr); + args[i] = conv; + } + all.add(args[i]); + } Object ret = fn.call("call", all.toArray()); // NOI18N - return ret == fn ? null : ret; + if (ret == fn) { + return null; + } + if (!arrayChecks) { + return ret; + } + return ((WebPresenter) presenter()).checkArray(ret); } catch (Error t) { t.printStackTrace(); throw t; diff -r 44330e2e9daa -r 237dbcd482dc launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/OnMessage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/OnMessage.java Thu Jan 09 11:55:01 2014 +0100 @@ -0,0 +1,26 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.launcher.fximpl; + +/** + * + * @author Jaroslav Tulach + */ +interface OnMessage { + public void onMessage(String msg); +} diff -r 44330e2e9daa -r 237dbcd482dc launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Run.java --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Run.java Thu Jan 09 08:21:39 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/** - * Back 2 Browser Bytecode Translator - * Copyright (C) 2012 Jaroslav Tulach - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. Look for COPYING file in the top folder. - * If not, see http://opensource.org/licenses/GPL-2.0. - */ - -package org.apidesign.bck2brwsr.launcher.fximpl; - -/** - * - * @author Jaroslav Tulach - */ -public final class Run implements Runnable { - private final Runnable r; - Run(Runnable r) { - this.r = r; - } - - @Override - public void run() { - r.run(); - } -} diff -r 44330e2e9daa -r 237dbcd482dc launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsMethods.java --- a/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsMethods.java Thu Jan 09 08:21:39 2014 +0100 +++ b/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsMethods.java Thu Jan 09 11:55:01 2014 +0100 @@ -17,7 +17,7 @@ */ package org.apidesign.bck2brwsr.launcher.fximpl; -import org.apidesign.bck2brwsr.core.JavaScriptBody; +import net.java.html.js.JavaScriptBody; /** *