You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by jt...@apache.org on 2020/08/09 07:40:08 UTC

[netbeans-html4j] branch master updated: Make sure FXConsole callback never garbage collects when WebView exists

This is an automated email from the ASF dual-hosted git repository.

jtulach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans-html4j.git


The following commit(s) were added to refs/heads/master by this push:
     new 7e90771  Make sure FXConsole callback never garbage collects when WebView exists
7e90771 is described below

commit 7e90771bf338a5d8c8f189cdc4df709d3e0e4697
Author: Jaroslav Tulach <ja...@apidesign.org>
AuthorDate: Sun Aug 9 09:39:42 2020 +0200

    Make sure FXConsole callback never garbage collects when WebView exists
---
 .../java/org/netbeans/html/boot/fx/FXBrwsr.java    | 34 ++-----------
 .../java/org/netbeans/html/boot/fx/FXConsole.java  | 55 +++++++++++++++++-----
 .../org/netbeans/html/boot/fx/FXGCPresenter.java   | 15 +++++-
 .../java/org/netbeans/html/boot/fx/PopupTest.java  |  7 ++-
 .../java/org/netbeans/html/boot/fx/TitleTest.java  | 33 +++++++------
 5 files changed, 84 insertions(+), 60 deletions(-)

diff --git a/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXBrwsr.java b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXBrwsr.java
index a6f96f7..12c73a2 100644
--- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXBrwsr.java
+++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXBrwsr.java
@@ -229,6 +229,7 @@ public class FXBrwsr extends Application {
         }
 
         attachHandlers(view, newStage);
+        final FXConsole fxConsole = new FXConsole(view, newStage);
         bp.setCenter(view);
         final Worker<Void> w = view.getEngine().getLoadWorker();
         w.stateProperty().addListener(new ChangeListener<Worker.State>() {
@@ -238,7 +239,7 @@ public class FXBrwsr extends Application {
             public void changed(ObservableValue<? extends Worker.State> ov, Worker.State t, Worker.State newState) {
                 if (newState.equals(Worker.State.SUCCEEDED)) {
                     if (checkValid()) {
-                        FXConsole.register(view.getEngine());
+                        fxConsole.register(view.getEngine());
                         onLoad.onPageLoad();
                     }
                 }
@@ -257,7 +258,7 @@ public class FXBrwsr extends Application {
             }
 
         });
-        Title.observeView(view, stage);
+        fxConsole.observeWebViewTitle();
         return view;
     }
 
@@ -361,7 +362,8 @@ public class FXBrwsr extends Application {
                 stage.initOwner(owner);
                 final WebView popUpView = new WebView();
                 stage.setScene(new Scene(popUpView));
-                Title.observeView(popUpView, stage);
+                FXConsole fxConsole = new FXConsole(popUpView, stage);
+                fxConsole.observeWebViewTitle();
                 stage.show();
                 return popUpView.getEngine();
             }
@@ -396,30 +398,4 @@ public class FXBrwsr extends Application {
             }
         }
     }
-    private static class Title implements ChangeListener<String> {
-        private String title;
-        private final WebView view;
-        private final Stage stage;
-
-        private Title(WebView view, Stage stage) {
-            super();
-            this.view = view;
-            this.stage = stage;
-        }
-
-        public static void observeView(WebView view, Stage stage) {
-            Title t = new Title(view, stage);
-            view.getEngine().titleProperty().addListener(t);
-            t.changed(null, null, null);
-        }
-
-        @Override
-        public void changed(ObservableValue<? extends String> ov, String t, String t1) {
-            title = view.getEngine().getTitle();
-            if (title != null) {
-                stage.setTitle(title);
-            }
-        }
-    }
-
 }
diff --git a/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXConsole.java b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXConsole.java
index 89f4963..8da7481 100644
--- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXConsole.java
+++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXConsole.java
@@ -18,9 +18,15 @@
  */
 package org.netbeans.html.boot.fx;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
 import javafx.scene.web.WebEngine;
+import javafx.scene.web.WebView;
+import javafx.stage.Stage;
 import netscape.javascript.JSObject;
 
 /** This is an implementation package - just
@@ -31,29 +37,52 @@ import netscape.javascript.JSObject;
  *
  * @author Jaroslav Tulach
  */
-public final class FXConsole {
+public final class FXConsole implements ChangeListener<String> {
     static final Logger LOG = Logger.getLogger(FXConsole.class.getName());
-    
-    private FXConsole() {
+    private String title;
+    final WebView view;
+    final Stage stage;
+
+    private static final List<FXConsole> all = new ArrayList<FXConsole>();
+
+    FXConsole(WebView view, Stage stage) {
+        all.add(this);
+        this.view = view;
+        this.stage = stage;
     }
 
-    static void register(WebEngine eng) {
+    void register(WebEngine eng) {
         JSObject fn = (JSObject) eng.executeScript(""
-            + "(function(attr, l, c) {"
-            + "  window.console[attr] = function(msg) { c.log(l, msg); };"
+            + "(function(attr, l, FXConsole) {\n"
+            + "  window.console[attr] = function(msg) {\n"
+            + "    FXConsole.log(l, msg);\n"
+            + "  };"
             + "})"
         );
-        FXConsole c = new FXConsole();
-        c.registerImpl(fn, "log", Level.INFO);
-        c.registerImpl(fn, "info", Level.INFO);
-        c.registerImpl(fn, "warn", Level.WARNING);
-        c.registerImpl(fn, "error", Level.SEVERE);
+        registerImpl(fn, "log", Level.INFO);
+        registerImpl(fn, "info", Level.INFO);
+        registerImpl(fn, "warn", Level.WARNING);
+        registerImpl(fn, "error", Level.SEVERE);
     }
-    
+
     private void registerImpl(JSObject eng, String attr, Level l) {
         eng.call("call", new Object[] { null, attr, l, this });
     }
-    
+
+    void observeWebViewTitle() {
+        view.getEngine().titleProperty().addListener(this);
+        this.changed(null, null, null);
+    }
+
+    @Override
+    public void changed(ObservableValue<? extends String> ov, String t, String t1) {
+        title = view.getEngine().getTitle();
+        if (title != null) {
+            stage.setTitle(title);
+        }
+    }
+
+    // called from JavaScript
     public void log(Level l, String msg) {
         LOG.log(l, msg);
     }
diff --git a/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXGCPresenter.java b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXGCPresenter.java
index 03f1594..a816725 100644
--- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXGCPresenter.java
+++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXGCPresenter.java
@@ -54,6 +54,15 @@ public final class FXGCPresenter extends AbstractFXPresenter {
         }
     }
 
+    private final WebView[] lastWebView;
+    public FXGCPresenter() {
+        this(null);
+    }
+    
+    FXGCPresenter(WebView[] lastWebView) {
+        this.lastWebView = lastWebView;
+    }
+
     @Override
     void waitFinished() {
         FXBrwsr.waitFinished();
@@ -61,7 +70,11 @@ public final class FXGCPresenter extends AbstractFXPresenter {
 
     @Override
     WebView findView(final URL resource) {
-        return FXBrwsr.findWebView(resource, this);
+        WebView view = FXBrwsr.findWebView(resource, this);
+        if (lastWebView != null) {
+            lastWebView[0] = view;
+        }
+        return view;
     }
 
     @Override
diff --git a/boot-fx/src/test/java/org/netbeans/html/boot/fx/PopupTest.java b/boot-fx/src/test/java/org/netbeans/html/boot/fx/PopupTest.java
index c7676b8..ae52922 100644
--- a/boot-fx/src/test/java/org/netbeans/html/boot/fx/PopupTest.java
+++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/PopupTest.java
@@ -21,6 +21,7 @@ package org.netbeans.html.boot.fx;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
+import javafx.scene.web.WebView;
 import javafx.stage.Stage;
 import net.java.html.BrwsrCtx;
 import net.java.html.boot.BrowserBuilder;
@@ -65,7 +66,8 @@ public class PopupTest {
         }
         WhenInitialized when = new WhenInitialized();
 
-        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(PopupTest.class).
+        final WebView[] lastWebView = { null };
+        final BrowserBuilder bb = BrowserBuilder.newBrowser(new FXGCPresenter(lastWebView)).loadClass(PopupTest.class).
                 loadPage("empty.html").
                 loadFinished(when);
 
@@ -80,7 +82,8 @@ public class PopupTest {
         when.cdl.await();
         if (arr[0] != null) throw arr[0];
 
-        Stage s = FXBrwsr.findStage();
+        assertNotNull(lastWebView[0], "A WebView created");
+        Stage s = (Stage) lastWebView[0].getScene().getWindow();
         assertEquals(s.getTitle(), "FX Presenter Harness");
 
         final Object[] window = new Object[1];
diff --git a/boot-fx/src/test/java/org/netbeans/html/boot/fx/TitleTest.java b/boot-fx/src/test/java/org/netbeans/html/boot/fx/TitleTest.java
index 5eca549..3974c8f 100644
--- a/boot-fx/src/test/java/org/netbeans/html/boot/fx/TitleTest.java
+++ b/boot-fx/src/test/java/org/netbeans/html/boot/fx/TitleTest.java
@@ -23,6 +23,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import javafx.beans.value.ChangeListener;
 import javafx.beans.value.ObservableValue;
+import javafx.scene.web.WebView;
 import javafx.stage.Stage;
 import net.java.html.BrwsrCtx;
 import net.java.html.boot.BrowserBuilder;
@@ -37,32 +38,33 @@ import org.testng.annotations.Test;
  */
 public class TitleTest {
     private static Runnable whenInitialized;
-    
+
     public TitleTest() {
     }
 
     @JavaScriptBody(args = { "a", "b"  }, body = "return a + b;")
     private static native int plus(int a, int b);
-    
+
     @Test public void checkReload() throws Throwable {
         final Throwable[] arr = { null };
-        
-        final BrowserBuilder bb = BrowserBuilder.newBrowser().loadClass(TitleTest.class).
+
+        final WebView[] lastWebView = { null };
+        final BrowserBuilder bb = BrowserBuilder.newBrowser(new FXGCPresenter(lastWebView)).loadClass(TitleTest.class).
                 loadPage("empty.html").
                 invoke("initialized");
-        
+
         class ShowBrowser implements Runnable {
             @Override
             public void run() {
                 bb.showAndWait();
             }
         }
-        
+
         class WhenInitialized implements Runnable {
             CountDownLatch cdl = new CountDownLatch(1);
             AbstractFXPresenter p;
             BrwsrCtx ctx;
-            
+
             @Override
             public void run() {
                 try {
@@ -83,10 +85,11 @@ public class TitleTest {
         Executors.newSingleThreadExecutor().submit(new ShowBrowser());
         when.cdl.await();
         if (arr[0] != null) throw arr[0];
-        
-        Stage s = FXBrwsr.findStage();
+
+        assertNotNull(lastWebView[0], "A WebView created");
+        Stage s = (Stage) lastWebView[0].getScene().getWindow();
         assertEquals(s.getTitle(), "FX Presenter Harness");
-        
+
         final CountDownLatch propChange = new CountDownLatch(1);
         s.titleProperty().addListener(new ChangeListener<String>() {
             @Override
@@ -94,7 +97,7 @@ public class TitleTest {
                 propChange.countDown();
             }
         });
-        
+
         when.ctx.execute(new Runnable() {
             @Override
             public void run() {
@@ -105,17 +108,17 @@ public class TitleTest {
         propChange.await(5, TimeUnit.SECONDS);
         assertEquals(s.getTitle(), "New title");
     }
-    
+
     final void doCheckReload() throws Exception {
         int res = plus(30, 12);
         assertEquals(res, 42, "Meaning of world computed");
     }
-    
+
     public static synchronized void initialized() throws Exception {
         whenInitialized.run();
     }
-    
-    @JavaScriptBody(args = { "s" }, body = 
+
+    @JavaScriptBody(args = { "s" }, body =
         "document.getElementsByTagName('title')[0].innerHTML = s;"
     )
     static native void changeTitle(String s);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists