1.1 --- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Sun Apr 17 08:06:55 2016 +0200
1.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Tue Apr 19 20:31:18 2016 +0200
1.3 @@ -76,6 +76,7 @@
1.4 // transient - e.g. not cloneable
1.5 private JSObject arraySize;
1.6 private JSObject wrapArrImpl;
1.7 + private Object undefined;
1.8
1.9 @Override
1.10 protected AbstractFXPresenter clone() {
1.11 @@ -83,6 +84,7 @@
1.12 AbstractFXPresenter p = (AbstractFXPresenter) super.clone();
1.13 p.arraySize = null;
1.14 p.wrapArrImpl = null;
1.15 + p.undefined = null;
1.16 return p;
1.17 } catch (CloneNotSupportedException ex) {
1.18 throw new IllegalStateException(ex);
1.19 @@ -223,6 +225,13 @@
1.20 return wrapArrImpl;
1.21 }
1.22
1.23 + final Object undefined() {
1.24 + if (undefined == null) {
1.25 + undefined = engine.executeScript("undefined");
1.26 + }
1.27 + return undefined;
1.28 + }
1.29 +
1.30 final Object checkArray(Object val) {
1.31 if (!(val instanceof JSObject)) {
1.32 return val;
1.33 @@ -233,8 +242,22 @@
1.34 }
1.35 Object[] arr = new Object[length];
1.36 arraySizeFn().call("array", val, arr);
1.37 + clearUndefinedArray(arr);
1.38 return arr;
1.39 }
1.40 +
1.41 + private void clearUndefinedArray(Object[] arr) {
1.42 + for (int i = 0; i < arr.length; i++) {
1.43 + if (arr[i] == undefined) {
1.44 + arr[i] = null;
1.45 + continue;
1.46 + }
1.47 + if (arr[i] instanceof Object[]) {
1.48 + clearUndefinedArray((Object[])arr[i]);
1.49 + }
1.50 + }
1.51 + }
1.52 +
1.53 private final JSObject arraySizeFn() {
1.54 if (arraySize == null) {
1.55 try {
1.56 @@ -328,6 +351,7 @@
1.57
1.58 final Object invokeImpl(Object thiz, boolean arrayChecks, Object... args) throws Exception {
1.59 try {
1.60 + final AbstractFXPresenter presenter = (AbstractFXPresenter) presenter();
1.61 if (LOG.isLoggable(Level.FINE)) {
1.62 LOG.log(Level.FINE, "calling {0} function #{1}", new Object[]{++call, id});
1.63 LOG.log(Level.FINER, " thiz : {0}", thiz);
1.64 @@ -340,7 +364,7 @@
1.65 if (arrayChecks) {
1.66 if (args[i] instanceof Object[]) {
1.67 Object[] arr = (Object[]) args[i];
1.68 - conv = ((AbstractFXPresenter)presenter()).convertArrays(arr);
1.69 + conv = presenter.convertArrays(arr);
1.70 }
1.71 if (conv != null && keepAlive != null &&
1.72 !keepAlive[i] && !isJSReady(conv) &&
1.73 @@ -355,13 +379,13 @@
1.74 if (ret instanceof Weak) {
1.75 ret = ((Weak)ret).get();
1.76 }
1.77 - if (ret == fn) {
1.78 + if (ret == fn || ret == presenter.undefined()) {
1.79 return null;
1.80 }
1.81 if (!arrayChecks) {
1.82 return ret;
1.83 }
1.84 - return ((AbstractFXPresenter)presenter()).checkArray(ret);
1.85 + return presenter.checkArray(ret);
1.86 } catch (Error t) {
1.87 t.printStackTrace();
1.88 throw t;
2.1 --- a/boot-script/src/main/java/net/java/html/boot/script/ScriptPresenter.java Sun Apr 17 08:06:55 2016 +0200
2.2 +++ b/boot-script/src/main/java/net/java/html/boot/script/ScriptPresenter.java Tue Apr 19 20:31:18 2016 +0200
2.3 @@ -175,6 +175,7 @@
2.4 fn.invokeImpl(null, false, val, arr);
2.5 return arr;
2.6 }
2.7 +
2.8 private FnImpl arraySize;
2.9 private FnImpl arraySizeFn() {
2.10 if (arraySize == null) {
2.11 @@ -185,7 +186,9 @@
2.12 + " else return -1;\n"
2.13 + "} else {\n"
2.14 + " var l = arr.length;\n"
2.15 - + " for (var i = 0; i < l; i++) to[i] = arr[i];\n"
2.16 + + " for (var i = 0; i < l; i++) {\n"
2.17 + + " to[i] = arr[i] === undefined ? null : arr[i];\n"
2.18 + + " }\n"
2.19 + " return l;\n"
2.20 + "}", new String[] { "arr", "to" }, null
2.21 );
3.1 --- a/boot/src/main/java/net/java/html/js/package.html Sun Apr 17 08:06:55 2016 +0200
3.2 +++ b/boot/src/main/java/net/java/html/js/package.html Tue Apr 19 20:31:18 2016 +0200
3.3 @@ -341,6 +341,29 @@
3.4 to JavaScript by passing it as a parameter of some method
3.5 (like the <code>setValue</code> one) and perform necessary JavaScript
3.6 calls or changes on it.
3.7 +
3.8 + <h3>undefined === null</h3>
3.9 + <a name='undefined'></a>
3.10 +
3.11 + JavaScript recognizes two <em>empty</em> values: <code>null</code> and
3.12 + <code>undefined</code>. Java has just <code>null</code>.
3.13 +
3.14 + For purposes of simplicity and easier inter-operability, <code>undefined</code>
3.15 + values returned from {@link net.java.html.js.JavaScriptBody @JavaScriptBody}
3.16 + annotated methods are converted to <code>null</code>. In the following
3.17 + example both methods return <code>null</code>:
3.18 +<pre>
3.19 + {@link net.java.html.js.JavaScriptBody @JavaScriptBody}(
3.20 + args = {}, body = "var empty = {}; return empty.x;"
3.21 + )
3.22 + <b>private static native</b> Object returnUndefined();
3.23 + {@link net.java.html.js.JavaScriptBody @JavaScriptBody}(
3.24 + args = {}, body = "var empty = {}; empty.x = null; return empty.x;"
3.25 + )
3.26 + <b>private static native</b> Object returnNull();
3.27 +}
3.28 +</pre>
3.29 + This is the behavior since version 1.4.
3.30
3.31 <h3>Post Process Classes</h3>
3.32 <a name="post-process"></a>
4.1 --- a/json-tck/src/main/java/net/java/html/js/tests/Bodies.java Sun Apr 17 08:06:55 2016 +0200
4.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/Bodies.java Tue Apr 19 20:31:18 2016 +0200
4.3 @@ -192,6 +192,32 @@
4.4 )
4.5 static native int gc(double max);
4.6
4.7 + @JavaScriptBody(args = {}, body = ""
4.8 + + "var o = {};\n"
4.9 + + "return o.x;\n"
4.10 + )
4.11 + static native Object unknown();
4.12 +
4.13 + @JavaScriptBody(args = {}, body = ""
4.14 + + "return new Array(2);\n"
4.15 + )
4.16 + static native Object[] unknownArray();
4.17 +
4.18 + @JavaScriptBody(args = { "sum" }, javacall = true, body = ""
4.19 + + "var arr = [];\n"
4.20 + + "arr[1] = null;\n"
4.21 + + "arr[2] = 1;\n"
4.22 + + "return sum.@net.java.html.js.tests.Sum::sumNonNull([Ljava/lang/Object;)(arr);\n"
4.23 + )
4.24 + static native int sumNonNull(Sum sum);
4.25 +
4.26 + @JavaScriptBody(args = { "sum", "p" }, javacall = true, body = ""
4.27 + + "var obj = {};\n"
4.28 + + "obj.x = 1;\n"
4.29 + + "return sum.@net.java.html.js.tests.Sum::checkNonNull(Ljava/lang/Object;)(obj[p]);\n"
4.30 + )
4.31 + static native boolean nonNull(Sum sum, String p);
4.32 +
4.33 @JavaScriptBody(args = {}, javacall = true, body =
4.34 "return @net.java.html.js.tests.Bodies::problematicString()();"
4.35 )
5.1 --- a/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java Sun Apr 17 08:06:55 2016 +0200
5.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/JavaScriptBodyTest.java Tue Apr 19 20:31:18 2016 +0200
5.3 @@ -358,7 +358,42 @@
5.4 String all = Bodies.primitiveTypes(new Sum());
5.5 assertEquals("Ahojfalse12356.07.0 TheEND", all, "Valid return type: " + all);
5.6 }
5.7 +
5.8 + @KOTest public void returnUnknown() {
5.9 + Object o = Bodies.unknown();
5.10 + assertNull(o, "Unknown is converted to null");
5.11 + }
5.12 +
5.13 + @KOTest public void returnUndefinedString() {
5.14 + Object o = Bodies.id("undefined");
5.15 + assertNotNull(o, "String remains string");
5.16 + }
5.17 +
5.18 + @KOTest public void returnUnknownArray() {
5.19 + Object[] arr = Bodies.unknownArray();
5.20 + assertEquals(arr.length, 2, "Two elements");
5.21 + assertNull(arr[0], "1st element is null");
5.22 + assertNull(arr[1], "2nd element is null");
5.23 + }
5.24 +
5.25 + @KOTest public void callbackKnown() {
5.26 + Sum s = new Sum();
5.27 + boolean nonNull = Bodies.nonNull(s, "x");
5.28 + assertTrue(nonNull, "x property exists");
5.29 + }
5.30
5.31 + @KOTest public void callbackUnknown() {
5.32 + Sum s = new Sum();
5.33 + boolean isNull = Bodies.nonNull(s, "y");
5.34 + assertTrue(isNull, "y property doesn't exist");
5.35 + }
5.36 +
5.37 + @KOTest public void callbackUnknownArray() {
5.38 + Sum s = new Sum();
5.39 + int nullAndUnknown = Bodies.sumNonNull(s);
5.40 + assertEquals(nullAndUnknown, 1, "Only one slot");
5.41 + }
5.42 +
5.43 @KOTest public void problematicString() {
5.44 String orig = Bodies.problematicString();
5.45 String js = Bodies.problematicCallback();
6.1 --- a/json-tck/src/main/java/net/java/html/js/tests/Sum.java Sun Apr 17 08:06:55 2016 +0200
6.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/Sum.java Tue Apr 19 20:31:18 2016 +0200
6.3 @@ -60,6 +60,20 @@
6.4 }
6.5 return s;
6.6 }
6.7 +
6.8 + public int sumNonNull(Object[] arr) {
6.9 + int s = 0;
6.10 + for (int i = 0; i < arr.length; i++) {
6.11 + if (arr[i] != null) {
6.12 + s++;
6.13 + }
6.14 + }
6.15 + return s;
6.16 + }
6.17 +
6.18 + public boolean checkNonNull(Object obj) {
6.19 + return obj != null;
6.20 + }
6.21
6.22 public String all(boolean z, byte b, short s, int i, long l, float f, double d, char ch, String str) {
6.23 return "Ahoj" + z + b + s + i + l + f + d + ch + str;
7.1 --- a/src/main/javadoc/overview.html Sun Apr 17 08:06:55 2016 +0200
7.2 +++ b/src/main/javadoc/overview.html Tue Apr 19 20:31:18 2016 +0200
7.3 @@ -75,6 +75,11 @@
7.4 yet the application code can be written in Java.
7.5 </p>
7.6
7.7 + <h3>New features in version 1.4</h3>
7.8 +
7.9 + Both values <code>null</code> and <code>undefined</code> are
7.10 + <a href="net/java/html/js/package-summary.html#undefined">treated as null</a>.
7.11 +
7.12 <h3>Improvements in version 1.3</h3>
7.13
7.14 {@link net.java.html.json.Model Model classes} can have