1.1 --- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Wed Jan 08 12:10:10 2014 +0100
1.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Wed Jan 08 12:24:21 2014 +0100
1.3 @@ -69,6 +69,10 @@
1.4
1.5 @Override
1.6 public Fn defineFn(String code, String... names) {
1.7 + return defineJSFn(code, names);
1.8 + }
1.9 +
1.10 + final JSFn defineJSFn(String code, String... names) {
1.11 StringBuilder sb = new StringBuilder();
1.12 sb.append("(function() {");
1.13 sb.append(" return function(");
1.14 @@ -153,6 +157,66 @@
1.15 protected abstract void waitFinished();
1.16
1.17 protected abstract WebView findView(final URL resource);
1.18 +
1.19 + final JSObject convertArrays(Object[] arr) {
1.20 + for (int i = 0; i < arr.length; i++) {
1.21 + if (arr[i] instanceof Object[]) {
1.22 + arr[i] = convertArrays((Object[]) arr[i]);
1.23 + }
1.24 + }
1.25 + final JSObject wrapArr = (JSObject)wrapArrFn().call("array", arr); // NOI18N
1.26 + return wrapArr;
1.27 + }
1.28 +
1.29 + private JSObject wrapArrImpl;
1.30 + private final JSObject wrapArrFn() {
1.31 + if (wrapArrImpl == null) {
1.32 + try {
1.33 + wrapArrImpl = (JSObject)defineJSFn(" var k = {};"
1.34 + + " k.array= function() {"
1.35 + + " return Array.prototype.slice.call(arguments);"
1.36 + + " };"
1.37 + + " return k;"
1.38 + ).invokeImpl(null, false);
1.39 + } catch (Exception ex) {
1.40 + throw new IllegalStateException(ex);
1.41 + }
1.42 + }
1.43 + return wrapArrImpl;
1.44 + }
1.45 +
1.46 + final Object checkArray(Object val) {
1.47 + int length = ((Number) arraySizeFn().call("array", val, null)).intValue();
1.48 + if (length == -1) {
1.49 + return val;
1.50 + }
1.51 + Object[] arr = new Object[length];
1.52 + arraySizeFn().call("array", val, arr);
1.53 + return arr;
1.54 + }
1.55 + private JSObject arraySize;
1.56 + private final JSObject arraySizeFn() {
1.57 + if (arraySize == null) {
1.58 + try {
1.59 + arraySize = (JSObject)defineJSFn(" var k = {};"
1.60 + + " k.array = function(arr, to) {"
1.61 + + " if (to === null) {"
1.62 + + " if (Object.prototype.toString.call(arr) === '[object Array]') return arr.length;"
1.63 + + " else return -1;"
1.64 + + " } else {"
1.65 + + " var l = arr.length;"
1.66 + + " for (var i = 0; i < l; i++) to[i] = arr[i];"
1.67 + + " return l;"
1.68 + + " }"
1.69 + + " };"
1.70 + + " return k;"
1.71 + ).invokeImpl(null, false);
1.72 + } catch (Exception ex) {
1.73 + throw new IllegalStateException(ex);
1.74 + }
1.75 + }
1.76 + return arraySize;
1.77 + }
1.78
1.79 private static final class JSFn extends Fn {
1.80
1.81 @@ -168,15 +232,32 @@
1.82
1.83 @Override
1.84 public Object invoke(Object thiz, Object... args) throws Exception {
1.85 + return invokeImpl(thiz, true, args);
1.86 + }
1.87 +
1.88 + final Object invokeImpl(Object thiz, boolean arrayChecks, Object... args) throws Exception {
1.89 try {
1.90 if (LOG.isLoggable(Level.FINE)) {
1.91 LOG.log(Level.FINE, "calling {0} function #{1}", new Object[]{++call, id});
1.92 }
1.93 List<Object> all = new ArrayList<Object>(args.length + 1);
1.94 all.add(thiz == null ? fn : thiz);
1.95 - all.addAll(Arrays.asList(args));
1.96 + for (int i = 0; i < args.length; i++) {
1.97 + if (arrayChecks && args[i] instanceof Object[]) {
1.98 + Object[] arr = (Object[]) args[i];
1.99 + Object conv = ((AbstractFXPresenter)presenter()).convertArrays(arr);
1.100 + args[i] = conv;
1.101 + }
1.102 + all.add(args[i]);
1.103 + }
1.104 Object ret = fn.call("call", all.toArray()); // NOI18N
1.105 - return ret == fn ? null : ret;
1.106 + if (ret == fn) {
1.107 + return null;
1.108 + }
1.109 + if (!arrayChecks) {
1.110 + return ret;
1.111 + }
1.112 + return ((AbstractFXPresenter)presenter()).checkArray(ret);
1.113 } catch (Error t) {
1.114 t.printStackTrace();
1.115 throw t;
2.1 --- a/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java Wed Jan 08 12:10:10 2014 +0100
2.2 +++ b/boot/src/main/java/org/apidesign/html/boot/spi/Fn.java Wed Jan 08 12:24:21 2014 +0100
2.3 @@ -189,6 +189,16 @@
2.4 * @throws Exception if something goes wrong, as exception may be thrown
2.5 */
2.6 public abstract Object invoke(Object thiz, Object... args) throws Exception;
2.7 +
2.8 + /** Provides the function implementation access to the presenter provided
2.9 + * in {@link #Fn(org.apidesign.html.boot.spi.Fn.Presenter) the constructor).
2.10 + *
2.11 + * @return presenter passed in in the constructor (may be, but should not be <code>null</code>)
2.12 + * @since 0.7
2.13 + */
2.14 + protected final Presenter presenter() {
2.15 + return presenter;
2.16 + }
2.17
2.18 /** The representation of a <em>presenter</em> - usually a browser window.
2.19 * Should be provided by a library included in the application and registered
3.1 --- a/json-tck/src/main/java/net/java/html/js/tests/Bodies.java Wed Jan 08 12:10:10 2014 +0100
3.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/Bodies.java Wed Jan 08 12:24:21 2014 +0100
3.3 @@ -81,9 +81,15 @@
3.4
3.5 @JavaScriptBody(args = { "arr" }, body = "return arr.length;")
3.6 public static native int length(Object[] arr);
3.7 +
3.8 + @JavaScriptBody(args = { "o" }, body = "return typeof o;")
3.9 + public static native String typeof(Object o);
3.10
3.11 - @JavaScriptBody(args = { "arr", "i", "value" }, body = "arr[i] = value;")
3.12 - public static native void modify(String[] arr, int i, String value);
3.13 + @JavaScriptBody(args = { "o" }, body = "return Array.isArray(o);")
3.14 + public static native boolean isArray(Object o);
3.15 +
3.16 + @JavaScriptBody(args = { "arr", "i", "value" }, body = "arr[i] = value; return arr[i];")
3.17 + public static native String modify(String[] arr, int i, String value);
3.18
3.19 @JavaScriptBody(args = {}, body = "return true;")
3.20 public static native boolean truth();
4.1 --- a/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java Wed Jan 08 12:10:10 2014 +0100
4.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java Wed Jan 08 12:24:21 2014 +0100
4.3 @@ -130,31 +130,49 @@
4.4 assert res == 42 : "Expecting 42";
4.5 }
4.6
4.7 - @KOTest public void selectFromJavaArray() {
4.8 + @KOTest public void selectFromStringJavaArray() {
4.9 String[] arr = { "Ahoj", "World" };
4.10 Object res = Bodies.select(arr, 1);
4.11 assert "World".equals(res) : "Expecting World, but was: " + res;
4.12 }
4.13
4.14 + @KOTest public void selectFromObjectJavaArray() {
4.15 + Object[] arr = { new Object(), new Object() };
4.16 + Object res = Bodies.select(arr, 1);
4.17 + assert arr[1].equals(res) : "Expecting " + arr[1] + ", but was: " + res;
4.18 + }
4.19 +
4.20 @KOTest public void lengthOfJavaArray() {
4.21 String[] arr = { "Ahoj", "World" };
4.22 int res = Bodies.length(arr);
4.23 assert res == 2 : "Expecting 2, but was: " + res;
4.24 }
4.25
4.26 - @KOTest public void javaArrayInOut() {
4.27 + @KOTest public void isJavaArray() {
4.28 + String[] arr = { "Ahoj", "World" };
4.29 + boolean is = Bodies.isArray(arr);
4.30 + assert is: "Expecting it to be an array: " + is;
4.31 + }
4.32 +
4.33 + @KOTest public void javaArrayInOutIsCopied() {
4.34 String[] arr = { "Ahoj", "World" };
4.35 Object res = Bodies.id(arr);
4.36 - assert res == arr : "Expecting same array, but was: " + res;
4.37 + assert res != null : "Non-null is returned";
4.38 + assert res instanceof Object[] : "Returned an array: " + res;
4.39 + assert !(res instanceof String[]) : "Not returned a string array: " + res;
4.40 +
4.41 + Object[] ret = (Object[]) res;
4.42 + assert arr.length == ret.length : "Same length: " + ret.length;
4.43 + assert arr[0].equals(ret[0]) : "Same first elem";
4.44 + assert arr[1].equals(ret[1]) : "Same 2nd elem";
4.45 }
4.46
4.47 -// Modifying an array is a complex operation in the bridge:
4.48 -//
4.49 -// @KOTest public void modifyJavaArray() {
4.50 -// String[] arr = { "Ahoj", "World" };
4.51 -// Bodies.modify(arr, 0, "Hello");
4.52 -// assert "Hello".equals(arr[0]) : "Expecting World, but was: " + arr[0];
4.53 -// }
4.54 + @KOTest public void modifyJavaArrayHasNoEffect() {
4.55 + String[] arr = { "Ahoj", "World" };
4.56 + String value = Bodies.modify(arr, 0, "Hello");
4.57 + assert "Hello".equals(value) : "Inside JS the value is changed: " + value;
4.58 + assert "Ahoj".equals(arr[0]) : "From a Java point of view it remains: " + arr[0];
4.59 + }
4.60
4.61 @KOTest public void truth() {
4.62 assert Bodies.truth() : "True is true";