ADDITIONAL SYSTEM INFORMATION :
Ubuntu 25.04 x86_64 OpenJDK 25.0.1
Windows 11 x86_64 OpenJDK 25.0.1
A DESCRIPTION OF THE PROBLEM :
WebView#loadContent does not execute inline module scripts, neither in the head, nor the body. WebView#load executes the scripts, as do browsers.
I am not sure if this is a bug or a CORS related feature.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Load an HTML file with inline module scripts (see e.g. provided example file) into a WebView using #loadContent
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The scripts in head and body should be executed.
ACTUAL -
The scripts are not executed.
---------- BEGIN SOURCE ----------
// --- Demo application loading an HTML file using #load and #loadContent side-by-side
package com.airhack;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class Demo extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
/*
* Shows two WebViews side-by-side. The left view loads the content from a file via WebView#load,
* while the right view loads the content of the same file via WebView#loadContent.
*
* Script blocks of type "module" are executed when loaded via #load, but not when
* loaded via #loadContent.
*
* Both scripts are executed when opening the file in a browser.
*/
// Left WebView using #load
final var htmlFile = getClass().getClassLoader().getResource("hello.html").toExternalForm();
final var leftView = new WebView();
leftView.getEngine().load(htmlFile);
// Right WebView using #loadContent
final var rightView = new WebView();
try (final var inputStream = getClass().getClassLoader().getResourceAsStream("hello.html");
final var reader = new BufferedReader(new InputStreamReader(inputStream))) {
final var htmlContent = reader.lines().collect(Collectors.joining("\n"));
rightView.getEngine().loadContent(htmlContent);
}
final var hbox = new HBox(leftView, rightView);
hbox.setSpacing(10);
final var scene = new Scene(hbox, 750, 750);
stage.setScene(scene);
stage.show();
}
}
// --- Demo HTML file containing inline module scripts in head and body, should display
// "script in body - all good" and "script in header - all good"
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<!-- This mimics the real use-case of loading a Vue application, inlined via vite-plugin-singlefile -->
<script type="module">
const contentNode = document.createElement("div");
contentNode.textContent = "script in head - all good";
document.addEventListener("DOMContentLoaded", () => { document.body.appendChild(contentNode); });
</script>
</head>
<body>
<h1>Content added via script:</h1>
<script type="module">
const normalScriptNode = document.createElement("div");
normalScriptNode.textContent = "script in body - all good";
document.body.appendChild(normalScriptNode);
</script>
</body>
</html>
Workaround:
Write the HTML content into a temporary file and use WebView#load
---------- END SOURCE ----------
Ubuntu 25.04 x86_64 OpenJDK 25.0.1
Windows 11 x86_64 OpenJDK 25.0.1
A DESCRIPTION OF THE PROBLEM :
WebView#loadContent does not execute inline module scripts, neither in the head, nor the body. WebView#load executes the scripts, as do browsers.
I am not sure if this is a bug or a CORS related feature.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Load an HTML file with inline module scripts (see e.g. provided example file) into a WebView using #loadContent
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The scripts in head and body should be executed.
ACTUAL -
The scripts are not executed.
---------- BEGIN SOURCE ----------
// --- Demo application loading an HTML file using #load and #loadContent side-by-side
package com.airhack;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class Demo extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
/*
* Shows two WebViews side-by-side. The left view loads the content from a file via WebView#load,
* while the right view loads the content of the same file via WebView#loadContent.
*
* Script blocks of type "module" are executed when loaded via #load, but not when
* loaded via #loadContent.
*
* Both scripts are executed when opening the file in a browser.
*/
// Left WebView using #load
final var htmlFile = getClass().getClassLoader().getResource("hello.html").toExternalForm();
final var leftView = new WebView();
leftView.getEngine().load(htmlFile);
// Right WebView using #loadContent
final var rightView = new WebView();
try (final var inputStream = getClass().getClassLoader().getResourceAsStream("hello.html");
final var reader = new BufferedReader(new InputStreamReader(inputStream))) {
final var htmlContent = reader.lines().collect(Collectors.joining("\n"));
rightView.getEngine().loadContent(htmlContent);
}
final var hbox = new HBox(leftView, rightView);
hbox.setSpacing(10);
final var scene = new Scene(hbox, 750, 750);
stage.setScene(scene);
stage.show();
}
}
// --- Demo HTML file containing inline module scripts in head and body, should display
// "script in body - all good" and "script in header - all good"
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<!-- This mimics the real use-case of loading a Vue application, inlined via vite-plugin-singlefile -->
<script type="module">
const contentNode = document.createElement("div");
contentNode.textContent = "script in head - all good";
document.addEventListener("DOMContentLoaded", () => { document.body.appendChild(contentNode); });
</script>
</head>
<body>
<h1>Content added via script:</h1>
<script type="module">
const normalScriptNode = document.createElement("div");
normalScriptNode.textContent = "script in body - all good";
document.body.appendChild(normalScriptNode);
</script>
</body>
</html>
Workaround:
Write the HTML content into a temporary file and use WebView#load
---------- END SOURCE ----------