1.1 --- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Tue Dec 16 21:49:45 2014 +0100
1.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Wed Dec 17 07:19:50 2014 +0100
1.3 @@ -46,6 +46,7 @@
1.4 import java.io.Closeable;
1.5 import java.io.IOException;
1.6 import java.io.Reader;
1.7 +import java.lang.ref.WeakReference;
1.8 import java.net.URL;
1.9 import java.util.ArrayList;
1.10 import java.util.Arrays;
1.11 @@ -54,8 +55,6 @@
1.12 import java.util.logging.Level;
1.13 import java.util.logging.Logger;
1.14 import javafx.application.Platform;
1.15 -import javafx.collections.ObservableList;
1.16 -import javafx.scene.Node;
1.17 import javafx.scene.Parent;
1.18 import javafx.scene.layout.BorderPane;
1.19 import javafx.scene.web.WebEngine;
1.20 @@ -67,8 +66,8 @@
1.21 *
1.22 * @author Jaroslav Tulach
1.23 */
1.24 -public abstract class AbstractFXPresenter
1.25 -implements Fn.Presenter, Fn.ToJavaScript, Fn.FromJavaScript, Executor, Cloneable {
1.26 +public abstract class AbstractFXPresenter implements Fn.Presenter,
1.27 +Fn.KeepAlive, Fn.ToJavaScript, Fn.FromJavaScript, Executor, Cloneable {
1.28 static final Logger LOG = Logger.getLogger(FXPresenter.class.getName());
1.29 protected static int cnt;
1.30 protected Runnable onLoad;
1.31 @@ -92,15 +91,22 @@
1.32
1.33 @Override
1.34 public Fn defineFn(String code, String... names) {
1.35 - return defineJSFn(code, names);
1.36 + return defineJSFn(code, names, null);
1.37 + }
1.38 +
1.39 + @Override
1.40 + public Fn defineFn(String code, String[] names, boolean[] keepAlive) {
1.41 + return defineJSFn(code, names, keepAlive);
1.42 }
1.43
1.44 - final JSFn defineJSFn(String code, String... names) {
1.45 +
1.46 +
1.47 + final JSFn defineJSFn(String code, String[] names, boolean[] keepAlive) {
1.48 StringBuilder sb = new StringBuilder();
1.49 sb.append("(function() {");
1.50 sb.append(" return function(");
1.51 String sep = "";
1.52 - for (String n : names) {
1.53 + if (names != null) for (String n : names) {
1.54 sb.append(sep).append(n);
1.55 sep = ",";
1.56 }
1.57 @@ -115,7 +121,7 @@
1.58 );
1.59 }
1.60 JSObject x = (JSObject) engine.executeScript(sb.toString());
1.61 - return new JSFn(this, x, cnt);
1.62 + return new JSFn(this, x, cnt, keepAlive);
1.63 }
1.64
1.65 @Override
1.66 @@ -208,7 +214,7 @@
1.67 + " k.array= function() {"
1.68 + " return Array.prototype.slice.call(arguments);"
1.69 + " };"
1.70 - + " return k;"
1.71 + + " return k;", null, null
1.72 ).invokeImpl(null, false);
1.73 } catch (Exception ex) {
1.74 throw new IllegalStateException(ex);
1.75 @@ -218,6 +224,9 @@
1.76 }
1.77
1.78 final Object checkArray(Object val) {
1.79 + if (!(val instanceof JSObject)) {
1.80 + return val;
1.81 + }
1.82 int length = ((Number) arraySizeFn().call("array", val, null)).intValue();
1.83 if (length == -1) {
1.84 return val;
1.85 @@ -240,7 +249,7 @@
1.86 + " return l;"
1.87 + " }"
1.88 + " };"
1.89 - + " return k;"
1.90 + + " return k;", null, null
1.91 ).invokeImpl(null, false);
1.92 } catch (Exception ex) {
1.93 throw new IllegalStateException(ex);
1.94 @@ -251,6 +260,9 @@
1.95
1.96 @Override
1.97 public Object toJava(Object jsArray) {
1.98 + if (jsArray instanceof Weak) {
1.99 + jsArray = ((Weak)jsArray).get();
1.100 + }
1.101 return checkArray(jsArray);
1.102 }
1.103
1.104 @@ -300,11 +312,13 @@
1.105 private final JSObject fn;
1.106 private static int call;
1.107 private final int id;
1.108 + private final boolean[] keepAlive;
1.109
1.110 - public JSFn(AbstractFXPresenter p, JSObject fn, int id) {
1.111 + public JSFn(AbstractFXPresenter p, JSObject fn, int id, boolean[] keepAlive) {
1.112 super(p);
1.113 this.fn = fn;
1.114 this.id = id;
1.115 + this.keepAlive = keepAlive;
1.116 }
1.117
1.118 @Override
1.119 @@ -322,14 +336,25 @@
1.120 List<Object> all = new ArrayList<Object>(args.length + 1);
1.121 all.add(thiz == null ? fn : thiz);
1.122 for (int i = 0; i < args.length; i++) {
1.123 - if (arrayChecks && args[i] instanceof Object[]) {
1.124 - Object[] arr = (Object[]) args[i];
1.125 - Object conv = ((AbstractFXPresenter)presenter()).convertArrays(arr);
1.126 - args[i] = conv;
1.127 + Object conv = args[i];
1.128 + if (arrayChecks) {
1.129 + if (args[i] instanceof Object[]) {
1.130 + Object[] arr = (Object[]) args[i];
1.131 + conv = ((AbstractFXPresenter)presenter()).convertArrays(arr);
1.132 + }
1.133 + if (conv != null && keepAlive != null &&
1.134 + !keepAlive[i] && !(conv instanceof JSObject) &&
1.135 + !conv.getClass().getSimpleName().equals("$JsCallbacks$") // NOI18N
1.136 + ) {
1.137 + conv = new Weak(conv);
1.138 + }
1.139 }
1.140 - all.add(args[i]);
1.141 + all.add(conv);
1.142 }
1.143 Object ret = fn.call("call", all.toArray()); // NOI18N
1.144 + if (ret instanceof Weak) {
1.145 + ret = ((Weak)ret).get();
1.146 + }
1.147 if (ret == fn) {
1.148 return null;
1.149 }
1.150 @@ -347,4 +372,10 @@
1.151 }
1.152 }
1.153
1.154 + private static final class Weak extends WeakReference<Object> {
1.155 + public Weak(Object referent) {
1.156 + super(referent);
1.157 + assert !(referent instanceof Weak);
1.158 + }
1.159 + } // end of Weak
1.160 }
2.1 --- a/boot/src/main/java/org/netbeans/html/boot/spi/Fn.java Tue Dec 16 21:49:45 2014 +0100
2.2 +++ b/boot/src/main/java/org/netbeans/html/boot/spi/Fn.java Wed Dec 17 07:19:50 2014 +0100
2.3 @@ -137,7 +137,7 @@
2.4 }
2.5 if (p instanceof KeepAlive) {
2.6 boolean[] arr;
2.7 - if (!keepParametersAlive) {
2.8 + if (!keepParametersAlive && names.length > 0) {
2.9 arr = new boolean[names.length];
2.10 for (int i = 0; i < arr.length; i++) {
2.11 arr[i] = false;
3.1 --- a/json-tck/src/main/java/net/java/html/js/tests/GCBodyTest.java Tue Dec 16 21:49:45 2014 +0100
3.2 +++ b/json-tck/src/main/java/net/java/html/js/tests/GCBodyTest.java Wed Dec 17 07:19:50 2014 +0100
3.3 @@ -85,10 +85,8 @@
3.4 Object obj = assignInst();
3.5 assert ref != null;
3.6
3.7 - Bodies.setX(obj, null);
3.8 - obj = null;
3.9 -
3.10 - assertGC(ref, "Can disappear!");
3.11 + assertGC(ref, "Can disappear as it is keepAlive false!");
3.12 + assert obj != null : "Object is still present";
3.13 }
3.14
3.15 private static Reference<?> sendRunnable(final int[] arr) {