Skip to content

Commit 00ba2ff

Browse files
committed
Small improvements for PostponedActions processing
1 parent 7e164d9 commit 00ba2ff

File tree

6 files changed

+63
-37
lines changed

6 files changed

+63
-37
lines changed

src/changes/changes.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
<body>
1010
<release version="4.11.0" date="March xx, 2025" description="Bugfixes">
11+
<action type="fix" dev="rbri">
12+
Small improvements for PostponedActions processing.
13+
</action>
1114
<action type="fix" dev="rbri">
1215
Fix various event initialization when working with WebSocket's.
1316
</action>

src/main/java/org/htmlunit/html/DomElement.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,6 @@ else if (this instanceof HtmlOption) {
10931093
finally {
10941094
if (blocker != null) {
10951095
blocker.release();
1096-
jsEngine.processPostponedActions();
10971096
}
10981097
}
10991098

src/main/java/org/htmlunit/javascript/AbstractJavaScriptEngine.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,5 +160,7 @@ Object execute(HtmlPage page,
160160
*/
161161
interface PostponedActionsBlocker {
162162
void release();
163+
164+
void postponedActionExecutionBlocked();
163165
}
164166
}

src/main/java/org/htmlunit/javascript/JavaScriptEngine.java

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public class JavaScriptEngine implements AbstractJavaScriptEngine<Script> {
121121

122122
private transient ThreadLocal<Boolean> javaScriptRunning_;
123123
private transient ThreadLocal<List<PostponedAction>> postponedActions_;
124-
private transient boolean holdPostponedActions_;
124+
private transient RootPostponedActionsBlocker postponedActionsBlocker_;
125125
private transient boolean shutdownPending_;
126126

127127
/** The JavaScriptExecutor corresponding to all windows of this Web client */
@@ -702,7 +702,7 @@ public void shutdown() {
702702
if (javaScriptRunning_ != null) {
703703
javaScriptRunning_.remove();
704704
}
705-
holdPostponedActions_ = false;
705+
postponedActionsBlocker_ = null;
706706
}
707707

708708
/**
@@ -893,9 +893,12 @@ public final Object run(final Context cx) {
893893

894894
// doProcessPostponedActions is synchronized
895895
// moved out of the sync block to avoid deadlocks
896-
if (!holdPostponedActions_) {
896+
if (postponedActionsBlocker_ == null) {
897897
doProcessPostponedActions();
898898
}
899+
else {
900+
postponedActionsBlocker_.postponedActionExecutionBlocked();
901+
}
899902
return response;
900903
}
901904
catch (final Exception e) {
@@ -1034,12 +1037,12 @@ protected void handleJavaScriptTimeoutError(final HtmlPage page, final TimeoutEr
10341037
*/
10351038
@Override
10361039
public PostponedActionsBlocker blockPostponedActions() {
1037-
if (holdPostponedActions_) {
1038-
return new LeafPostponedActionsBlocker();
1040+
if (postponedActionsBlocker_ == null) {
1041+
postponedActionsBlocker_ = new RootPostponedActionsBlocker(this);
1042+
return postponedActionsBlocker_;
10391043
}
10401044

1041-
holdPostponedActions_ = true;
1042-
return new RootPostponedActionsBlocker(this);
1045+
return new ChildPostponedActionsBlocker(postponedActionsBlocker_);
10431046
}
10441047

10451048
/**
@@ -1048,7 +1051,12 @@ public PostponedActionsBlocker blockPostponedActions() {
10481051
*/
10491052
@Override
10501053
public void processPostponedActions() {
1051-
doProcessPostponedActions();
1054+
if (postponedActionsBlocker_ == null) {
1055+
doProcessPostponedActions();
1056+
}
1057+
else {
1058+
postponedActionsBlocker_.postponedActionExecutionBlocked();
1059+
}
10521060
}
10531061

10541062
/**
@@ -1062,7 +1070,7 @@ private void readObject(final ObjectInputStream in) throws IOException, ClassNot
10621070
private void initTransientFields() {
10631071
javaScriptRunning_ = new ThreadLocal<>();
10641072
postponedActions_ = new ThreadLocal<>();
1065-
holdPostponedActions_ = false;
1073+
postponedActionsBlocker_ = null;
10661074
shutdownPending_ = false;
10671075
}
10681076

@@ -1394,27 +1402,43 @@ public static String evaluateProxyAutoConfig(final BrowserVersion browserVersion
13941402
*/
13951403
private final class RootPostponedActionsBlocker implements PostponedActionsBlocker {
13961404
private final JavaScriptEngine jsEngine_;
1405+
private boolean postponedActionExecutionBlocked_;
13971406

13981407
private RootPostponedActionsBlocker(final JavaScriptEngine jsEngine) {
13991408
jsEngine_ = jsEngine;
14001409
}
14011410

14021411
@Override
14031412
public void release() {
1404-
jsEngine_.holdPostponedActions_ = false;
1413+
jsEngine_.postponedActionsBlocker_ = null;
1414+
if (postponedActionExecutionBlocked_) {
1415+
jsEngine_.processPostponedActions();
1416+
}
1417+
}
1418+
1419+
@Override
1420+
public void postponedActionExecutionBlocked() {
1421+
postponedActionExecutionBlocked_ = true;
14051422
}
14061423
}
14071424

14081425
/**
14091426
* {@link PostponedActionsBlocker} - noop blocker.
14101427
*/
1411-
private final class LeafPostponedActionsBlocker implements PostponedActionsBlocker {
1428+
private final class ChildPostponedActionsBlocker implements PostponedActionsBlocker {
1429+
private final RootPostponedActionsBlocker rootBlocker_;
14121430

1413-
private LeafPostponedActionsBlocker() {
1431+
private ChildPostponedActionsBlocker(final RootPostponedActionsBlocker blocker) {
1432+
rootBlocker_ = blocker;
14141433
}
14151434

14161435
@Override
14171436
public void release() {
14181437
}
1438+
1439+
@Override
1440+
public void postponedActionExecutionBlocked() {
1441+
rootBlocker_.postponedActionExecutionBlocked();
1442+
}
14191443
}
14201444
}

src/test/java/org/htmlunit/javascript/host/html/HTMLDialogElementTest.java

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -759,18 +759,6 @@ public void returnValueSpecial() throws Exception {
759759
@Test
760760
@Alerts({"false", "true", "false",
761761
"[object Event]", "close", "false", "false", "false", "[object HTMLDialogElement]"})
762-
@HtmlUnitNYI(CHROME = {"false", "true",
763-
"[object Event]", "close", "false", "false", "false", "[object HTMLDialogElement]",
764-
"false"},
765-
EDGE = {"false", "true",
766-
"[object Event]", "close", "false", "false", "false", "[object HTMLDialogElement]",
767-
"false"},
768-
FF = {"false", "true",
769-
"[object Event]", "close", "false", "false", "false", "[object HTMLDialogElement]",
770-
"false"},
771-
FF_ESR = {"false", "true",
772-
"[object Event]", "close", "false", "false", "false", "[object HTMLDialogElement]",
773-
"false"})
774762
public void formClosesDialog() throws Exception {
775763
final String html =
776764
"<html>\n"
@@ -815,18 +803,6 @@ public void formClosesDialog() throws Exception {
815803
@Test
816804
@Alerts({"false", "true", "false",
817805
"[object Event]", "close", "false", "false", "false", "[object HTMLDialogElement]"})
818-
@HtmlUnitNYI(CHROME = {"false", "true",
819-
"[object Event]", "close", "false", "false", "false", "[object HTMLDialogElement]",
820-
"false"},
821-
EDGE = {"false", "true",
822-
"[object Event]", "close", "false", "false", "false", "[object HTMLDialogElement]",
823-
"false"},
824-
FF = {"false", "true",
825-
"[object Event]", "close", "false", "false", "false", "[object HTMLDialogElement]",
826-
"false"},
827-
FF_ESR = {"false", "true",
828-
"[object Event]", "close", "false", "false", "false", "[object HTMLDialogElement]",
829-
"false"})
830806
public void formClosesDialogWithoutJs() throws Exception {
831807
final String html =
832808
"<html>\n"

src/test/java/org/htmlunit/javascript/host/html/HTMLElement2Test.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,4 +2121,26 @@ private void eventHandlerSetterGetterTest(final String eventName) throws Excepti
21212121
loadPageVerifyTitle2(html);
21222122
}
21232123

2124+
/**
2125+
* @throws Exception failure
2126+
*/
2127+
@Test
2128+
@Alerts({"onclick", "listener", "clicked"})
2129+
public void clickJs() throws Exception {
2130+
final String html = "<html><head>\n"
2131+
+ "</head>\n"
2132+
+ "<body>\n"
2133+
+ "<div id='tester' onclick='log(\"onclick\")'></div>\n"
2134+
+ LOG_TEXTAREA
2135+
+ "<script>\n"
2136+
+ LOG_TEXTAREA_FUNCTION
2137+
+ "let elem = document.getElementById('tester');"
2138+
+ "elem.addEventListener('click', (e) => { log('listener'); });"
2139+
+ "document.getElementById('tester').click();\n"
2140+
+ "log('clicked');"
2141+
+ "</script>\n"
2142+
+ "</body></html>";
2143+
2144+
loadPageVerifyTextArea2(html);
2145+
}
21242146
}

0 commit comments

Comments
 (0)