Initial attempt to implement keepAlive in FX presenter weakfx
authorJaroslav Tulach <jtulach@netbeans.org>
Wed, 17 Dec 2014 07:19:50 +0100
branchweakfx
changeset 907dbd7ab3a4714
parent 906 e1291f7b7626
child 909 4abb0f37d33e
Initial attempt to implement keepAlive in FX presenter
boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java
boot/src/main/java/org/netbeans/html/boot/spi/Fn.java
json-tck/src/main/java/net/java/html/js/tests/GCBodyTest.java
     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) {