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