Skip to content

Commit 07cfcfc

Browse files
committed
WebClient.setJavaScriptTimeout(timeout) stops most JavaScript immediately fixed
1 parent e02561e commit 07cfcfc

File tree

5 files changed

+49
-8
lines changed

5 files changed

+49
-8
lines changed

src/changes/changes.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88

99
<body>
1010
<release version="4.19.0" date="November xx, 2025" description="Chrome/Edge 142, Bugfixes">
11+
<action type="update" dev="rbri">
12+
JavaScript timeout messages slightly improved.
13+
</action>
14+
<action type="fix" dev="rbri" issue="#1057">
15+
WebClient.setJavaScriptTimeout(timeout) stops most JavaScript immediately. This is a regression compared to version 4.18.0.
16+
</action>
1117
<action type="update" dev="rbri">
1218
neko: improve spec conformance of comment end detection
1319
</action>
@@ -2846,7 +2852,7 @@
28462852
<release version="3.0.0" date="March 19, 2023" description="htmlunit.org, Chrome/Edge 110, Firefox 110, HTML parser improved, Bugfixes">
28472853
<action type="update" dev="rbri">
28482854
INCOMPATIBLE CHANGE: Value processing for input controls changed; typing now ONLY changes the value
2849-
but not the value attribute. As consequence all calls to setValueAttribute(..) hve to be replaced by setValue() or type().
2855+
but not the value attribute. As consequence all calls to setValueAttribute(..) have to be replaced by setValue() or type().
28502856
</action>
28512857
<action type="update" dev="rbri">
28522858
INCOMPATIBLE CHANGE: HtmlButton.getAttribute() now returns the plain attribute value also for 'type' attribute

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,19 @@ protected Object doTopCall(final Callable callable,
298298
return super.doTopCall(callable, cx, scope, thisObj, args);
299299
}
300300

301+
/**
302+
* {@inheritDoc}
303+
*/
304+
@Override
305+
protected Object doTopCall(final Script script,
306+
final Context cx, final Scriptable scope,
307+
final Scriptable thisObj) {
308+
309+
final TimeoutContext tcx = (TimeoutContext) cx;
310+
tcx.startClock();
311+
return super.doTopCall(script, cx, scope, thisObj);
312+
}
313+
301314
/**
302315
* Same as {@link ContextFactory}{@link #call(ContextAction)} but with handling
303316
* of some exceptions.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class TimeoutError extends Error {
2626

2727
TimeoutError(final long allowedTime, final long executionTime) {
2828
super("Javascript execution takes too long (allowed: " + allowedTime
29-
+ ", already elapsed: " + executionTime + ")");
29+
+ "ms, already elapsed: " + executionTime + "ms)");
3030
allowedTime_ = allowedTime;
3131
executionTime_ = executionTime;
3232
}

src/test/java/org/htmlunit/WebClientTest.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import org.htmlunit.util.NameValuePair;
5555
import org.htmlunit.util.UrlUtils;
5656
import org.htmlunit.xml.XmlPage;
57+
import org.junit.jupiter.api.Assertions;
5758
import org.junit.jupiter.api.Test;
5859

5960
/**
@@ -1700,8 +1701,6 @@ public void javaScriptTimeout() throws Exception {
17001701
client.setJavaScriptTimeout(timeout);
17011702

17021703
try {
1703-
client.getOptions().setThrowExceptionOnScriptError(false);
1704-
17051704
final String content = DOCTYPE_HTML + "<html><body><script>while(1) {}</script></body></html>";
17061705
final MockWebConnection webConnection = new MockWebConnection();
17071706
webConnection.setDefaultResponse(content);
@@ -1727,7 +1726,19 @@ public void run() {
17271726
runner.interrupt();
17281727
fail("Script was still running after timeout");
17291728
}
1730-
assertNull(exceptions[0]);
1729+
1730+
Assertions.assertTrue(exceptions[0] instanceof RuntimeException, exceptions[0].getMessage());
1731+
final Throwable cause = exceptions[0].getCause();
1732+
String msg = cause.getMessage();
1733+
Assertions.assertTrue(cause.getMessage().startsWith(
1734+
"Javascript execution takes too long (allowed: 2000ms, already elapsed: "), cause.getMessage());
1735+
1736+
msg = msg.substring(msg.indexOf("already elapsed: ") + 17);
1737+
msg = msg.substring(0, msg.indexOf("ms"));
1738+
final long execTime = Long.parseLong(msg);
1739+
1740+
Assertions.assertTrue(execTime >= timeout, "execTime: " + execTime);
1741+
Assertions.assertTrue(execTime < (timeout + 2), "execTime: " + execTime);
17311742
}
17321743
finally {
17331744
client.setJavaScriptTimeout(oldTimeout);

src/test/java/org/htmlunit/javascript/JavaScriptEngineTest.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import org.htmlunit.junit.annotation.Alerts;
5353
import org.htmlunit.util.NameValuePair;
5454
import org.htmlunit.util.UrlUtils;
55+
import org.junit.jupiter.api.Assertions;
5556
import org.junit.jupiter.api.Test;
5657

5758
/**
@@ -799,8 +800,6 @@ public void timeout() throws Exception {
799800
client.setJavaScriptTimeout(timeout);
800801

801802
try {
802-
client.getOptions().setThrowExceptionOnScriptError(false);
803-
804803
final String content = DOCTYPE_HTML + "<html><body><script>while(1) {}</script></body></html>";
805804
final MockWebConnection webConnection = new MockWebConnection();
806805
webConnection.setDefaultResponse(content);
@@ -826,7 +825,19 @@ public void run() {
826825
runner.interrupt();
827826
fail("Script was still running after timeout");
828827
}
829-
assertNull(exceptions[0]);
828+
829+
Assertions.assertTrue(exceptions[0] instanceof RuntimeException, exceptions[0].getMessage());
830+
final Throwable cause = exceptions[0].getCause();
831+
String msg = cause.getMessage();
832+
Assertions.assertTrue(cause.getMessage().startsWith(
833+
"Javascript execution takes too long (allowed: 2000ms, already elapsed: "), cause.getMessage());
834+
835+
msg = msg.substring(msg.indexOf("already elapsed: ") + 17);
836+
msg = msg.substring(0, msg.indexOf("ms"));
837+
final long execTime = Long.parseLong(msg);
838+
839+
Assertions.assertTrue(execTime >= timeout, "execTime: " + execTime);
840+
Assertions.assertTrue(execTime < (timeout + 2), "execTime: " + execTime);
830841
}
831842
finally {
832843
client.setJavaScriptTimeout(oldTimeout);

0 commit comments

Comments
 (0)