Skip to content

Commit fb0209a

Browse files
committed
WebClient waitForBackgroundJavaScript(long), waitForBackgroundJavaScriptStartingBefore(long), and waitForBackgroundJavaScriptStartingBefore(long, long) no longer marked as experimental
1 parent 69acf97 commit fb0209a

2 files changed

Lines changed: 157 additions & 65 deletions

File tree

src/changes/changes.xml

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

99
<body>
1010
<release version="4.16.0" date="August 17, 2025" description="StringUtils, Brotli, Bugfixes">
11+
<action type="update" dev="rbri">
12+
WebClient waitForBackgroundJavaScript(long), waitForBackgroundJavaScriptStartingBefore(long), and
13+
waitForBackgroundJavaScriptStartingBefore(long, long) no longer marked as experimental.
14+
</action>
1115
<action type="update" dev="rbri" issue="#1009">
12-
Use our own 'fork' of the current brotli source code.
16+
Use our own 'fork' of the current brotli source code. This makes some fixes available that are
17+
done in the code base but not release so far.
1318
</action>
1419
<action type="update" dev="rbri">
1520
Use our own StringUtils at more places to be comptible with older commons lang versions.

src/main/java/org/htmlunit/WebClient.java

Lines changed: 151 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,24 +2413,46 @@ public void reset() {
24132413
}
24142414

24152415
/**
2416-
* <p><span style="color:red">Experimental API: May be changed in next release
2417-
* and may not yet work perfectly!</span></p>
2418-
*
2419-
* <p>This method blocks until all background JavaScript tasks have finished executing. Background
2420-
* JavaScript tasks are JavaScript tasks scheduled for execution via <code>window.setTimeout</code>,
2421-
* <code>window.setInterval</code> or asynchronous <code>XMLHttpRequest</code>.</p>
2422-
*
2423-
* <p>If a job is scheduled to begin executing after <code>(now + timeoutMillis)</code>, this method will
2424-
* wait for <code>timeoutMillis</code> milliseconds and then return a value greater than <code>0</code>. This
2425-
* method will never block longer than <code>timeoutMillis</code> milliseconds.</p>
2426-
*
2427-
* <p>Use this method instead of {@link #waitForBackgroundJavaScriptStartingBefore(long)} if you
2428-
* don't know when your background JavaScript is supposed to start executing, but you're fairly sure
2429-
* that you know how long it should take to finish executing.</p>
2430-
*
2431-
* @param timeoutMillis the maximum amount of time to wait (in milliseconds)
2432-
* @return the number of background JavaScript jobs still executing or waiting to be executed when this
2433-
* method returns; will be <code>0</code> if there are no jobs left to execute
2416+
* <p>Blocks until all background JavaScript tasks have finished executing or until the specified
2417+
* timeout is reached, whichever occurs first. Background JavaScript tasks include:</p>
2418+
* <ul>
2419+
* <li>JavaScript scheduled via <code>window.setTimeout()</code></li>
2420+
* <li>JavaScript scheduled via <code>window.setInterval()</code></li>
2421+
* <li>Asynchronous <code>XMLHttpRequest</code> operations</li>
2422+
* <li>Other asynchronous JavaScript operations across all windows managed by this WebClient</li>
2423+
* </ul>
2424+
*
2425+
* <p><strong>Timeout Behavior:</strong> If background tasks are scheduled to execute after
2426+
* <code>(now + timeoutMillis)</code>, this method will wait for the full timeout duration
2427+
* and then return the number of remaining jobs. The method guarantees it will never block
2428+
* longer than the specified timeout.</p>
2429+
*
2430+
* <p><strong>Use Case:</strong> Use this method when you don't know the exact timing of when
2431+
* background JavaScript will start, but you have a reasonable estimate of how long all
2432+
* tasks should take to complete. For scenarios where you know when tasks should start
2433+
* executing, consider using {@link #waitForBackgroundJavaScriptStartingBefore(long)} instead.</p>
2434+
*
2435+
* <p><strong>Thread Safety:</strong> This method is thread-safe and handles concurrent
2436+
* modifications to the internal job manager list gracefully.</p>
2437+
*
2438+
* <p><strong>Example Usage:</strong></p>
2439+
* <pre><code>
2440+
* // Wait up to 5 seconds for all background JavaScript to complete
2441+
* int remainingJobs = webClient.waitForBackgroundJavaScript(5000);
2442+
* if (remainingJobs == 0) {
2443+
* log("All background JavaScript completed");
2444+
* } else {
2445+
* log("Timeout reached, " + remainingJobs + " jobs still pending");
2446+
* }
2447+
* </code></pre>
2448+
*
2449+
* @param timeoutMillis the maximum amount of time to wait in milliseconds; must be positive
2450+
* @return the number of background JavaScript jobs still executing or waiting to be executed
2451+
* when this method returns; returns <code>0</code> if all jobs completed successfully
2452+
* within the timeout period
2453+
* @throws IllegalArgumentException if timeoutMillis is negative
2454+
* @see #waitForBackgroundJavaScriptStartingBefore(long)
2455+
* @see #waitForBackgroundJavaScriptStartingBefore(long, long)
24342456
*/
24352457
public int waitForBackgroundJavaScript(final long timeoutMillis) {
24362458
int count = 0;
@@ -2463,58 +2485,123 @@ public int waitForBackgroundJavaScript(final long timeoutMillis) {
24632485
}
24642486

24652487
/**
2466-
* <p><span style="color:red">Experimental API: May be changed in next release
2467-
* and may not yet work perfectly!</span></p>
2468-
*
2469-
* <p>This method blocks until all background JavaScript tasks scheduled to start executing before
2470-
* <code>(now + delayMillis)</code> have finished executing. Background JavaScript tasks are JavaScript
2471-
* tasks scheduled for execution via <code>window.setTimeout</code>, <code>window.setInterval</code> or
2472-
* asynchronous <code>XMLHttpRequest</code>.</p>
2473-
*
2474-
* <p>If there is no background JavaScript task currently executing, and there is no background JavaScript
2475-
* task scheduled to start executing within the specified time, this method returns immediately -- even
2476-
* if there are tasks scheduled to be executed after <code>(now + delayMillis)</code>.</p>
2477-
*
2478-
* <p>Note that the total time spent executing a background JavaScript task is never known ahead of
2479-
* time, so this method makes no guarantees as to how long it will block.</p>
2480-
*
2481-
* <p>Use this method instead of {@link #waitForBackgroundJavaScript(long)} if you know roughly when
2482-
* your background JavaScript is supposed to start executing, but you're not necessarily sure how long
2483-
* it will take to execute.</p>
2484-
*
2485-
* @param delayMillis the delay which determines the background tasks to wait for (in milliseconds)
2486-
* @return the number of background JavaScript jobs still executing or waiting to be executed when this
2487-
* method returns; will be <code>0</code> if there are no jobs left to execute
2488+
* <p>Blocks until all background JavaScript tasks scheduled to start executing before
2489+
* <code>(now + delayMillis)</code> have finished executing. Background JavaScript tasks include:</p>
2490+
* <ul>
2491+
* <li>JavaScript scheduled via <code>window.setTimeout()</code></li>
2492+
* <li>JavaScript scheduled via <code>window.setInterval()</code></li>
2493+
* <li>Asynchronous <code>XMLHttpRequest</code> operations</li>
2494+
* <li>Other asynchronous JavaScript operations across all windows managed by this WebClient</li>
2495+
* </ul>
2496+
*
2497+
* <p><strong>Method Behavior:</strong></p>
2498+
* <ul>
2499+
* <li>If no background JavaScript tasks are currently executing and none are scheduled
2500+
* to start within <code>delayMillis</code>, this method returns immediately</li>
2501+
* <li>Tasks scheduled to execute after <code>(now + delayMillis)</code> are ignored
2502+
* and do not affect the waiting behavior</li>
2503+
* <li>The method waits for tasks to complete execution, not just to start</li>
2504+
* <li>This method waits indefinitely for qualifying tasks to complete (no timeout)</li>
2505+
* </ul>
2506+
*
2507+
* <p><strong>Use Case:</strong> This method is ideal when you know approximately when
2508+
* background JavaScript should start executing but are uncertain about execution duration.
2509+
* Use this when you don't need a timeout and want to ensure all relevant tasks complete.
2510+
* For scenarios where you need to wait for all background tasks regardless of timing,
2511+
* use {@link #waitForBackgroundJavaScript(long)} instead. For timeout control, use
2512+
* {@link #waitForBackgroundJavaScriptStartingBefore(long, long)} instead.</p>
2513+
*
2514+
* <p><strong>Thread Safety:</strong> This method is thread-safe and handles concurrent
2515+
* modifications to the internal job manager list gracefully.</p>
2516+
*
2517+
* <p><strong>Example Usage:</strong></p>
2518+
* <pre><code>
2519+
* // Wait indefinitely for JavaScript tasks starting within 1 second
2520+
* int remainingJobs = webClient.waitForBackgroundJavaScriptStartingBefore(1000);
2521+
* if (remainingJobs == 0) {
2522+
* log("All relevant background JavaScript completed");
2523+
* } else {
2524+
* log("Some tasks may still be pending: " + remainingJobs + " jobs");
2525+
* }
2526+
*
2527+
* // Common pattern: wait for tasks that should start soon
2528+
* // (useful after triggering an action that schedules JavaScript)
2529+
* webClient.waitForBackgroundJavaScriptStartingBefore(500);
2530+
* </code></pre>
2531+
*
2532+
* @param delayMillis the delay which determines the background tasks to wait for (in milliseconds);
2533+
* must be non-negative
2534+
* @return the number of background JavaScript jobs still executing or waiting to be executed
2535+
* when this method returns; returns <code>0</code> if all qualifying jobs completed
2536+
* successfully
2537+
* @see #waitForBackgroundJavaScript(long)
2538+
* @see #waitForBackgroundJavaScriptStartingBefore(long, long)
24882539
*/
24892540
public int waitForBackgroundJavaScriptStartingBefore(final long delayMillis) {
24902541
return waitForBackgroundJavaScriptStartingBefore(delayMillis, -1);
24912542
}
24922543

24932544
/**
2494-
* <p><span style="color:red">Experimental API: May be changed in next release
2495-
* and may not yet work perfectly!</span></p>
2496-
*
2497-
* <p>This method blocks until all background JavaScript tasks scheduled to start executing before
2498-
* <code>(now + delayMillis)</code> have finished executing. Background JavaScript tasks are JavaScript
2499-
* tasks scheduled for execution via <code>window.setTimeout</code>, <code>window.setInterval</code> or
2500-
* asynchronous <code>XMLHttpRequest</code>.</p>
2501-
*
2502-
* <p>If there is no background JavaScript task currently executing, and there is no background JavaScript
2503-
* task scheduled to start executing within the specified time, this method returns immediately -- even
2504-
* if there are tasks scheduled to be executed after <code>(now + delayMillis)</code>.</p>
2505-
*
2506-
* <p>Note that the total time spent executing a background JavaScript task is never known ahead of
2507-
* time, so this method makes no guarantees as to how long it will block.</p>
2508-
*
2509-
* <p>Use this method instead of {@link #waitForBackgroundJavaScript(long)} if you know roughly when
2510-
* your background JavaScript is supposed to start executing, but you're not necessarily sure how long
2511-
* it will take to execute.</p>
2512-
*
2513-
* @param delayMillis the delay which determines the background tasks to wait for (in milliseconds)
2514-
* @param timeoutMillis the maximum amount of time to wait (in milliseconds); this has to be larger than
2515-
* the delayMillis parameter, otherwise the timeout is ignored
2516-
* @return the number of background JavaScript jobs still executing or waiting to be executed when this
2517-
* method returns; will be <code>0</code> if there are no jobs left to execute
2545+
* <p>Blocks until all background JavaScript tasks scheduled to start executing before
2546+
* <code>(now + delayMillis)</code> have finished executing, or until the specified timeout
2547+
* is reached, whichever occurs first. Background JavaScript tasks include:</p>
2548+
* <ul>
2549+
* <li>JavaScript scheduled via <code>window.setTimeout()</code></li>
2550+
* <li>JavaScript scheduled via <code>window.setInterval()</code></li>
2551+
* <li>Asynchronous <code>XMLHttpRequest</code> operations</li>
2552+
* <li>Other asynchronous JavaScript operations across all windows managed by this WebClient</li>
2553+
* </ul>
2554+
*
2555+
* <p><strong>Method Behavior:</strong></p>
2556+
* <ul>
2557+
* <li>If no background JavaScript tasks are currently executing and none are scheduled
2558+
* to start within <code>delayMillis</code>, this method returns immediately</li>
2559+
* <li>Tasks scheduled to execute after <code>(now + delayMillis)</code> are ignored
2560+
* and do not affect the waiting behavior</li>
2561+
* <li>The method waits for tasks to complete execution, not just to start</li>
2562+
* </ul>
2563+
*
2564+
* <p><strong>Timeout Behavior:</strong></p>
2565+
* <ul>
2566+
* <li>If <code>timeoutMillis</code> is negative or less than <code>delayMillis</code>,
2567+
* the timeout is ignored and the method waits indefinitely</li>
2568+
* <li>When a valid timeout is specified, the method will never block longer than
2569+
* <code>timeoutMillis</code> milliseconds</li>
2570+
* <li>The timeout applies to the total waiting time, not per task</li>
2571+
* </ul>
2572+
*
2573+
* <p><strong>Use Case:</strong> This method is ideal when you know approximately when
2574+
* background JavaScript should start executing but are uncertain about execution duration.
2575+
* For scenarios where you need to wait for all background tasks regardless of timing,
2576+
* use {@link #waitForBackgroundJavaScript(long)} instead.</p>
2577+
*
2578+
* <p><strong>Thread Safety:</strong> This method is thread-safe and handles concurrent
2579+
* modifications to the internal job manager list gracefully.</p>
2580+
*
2581+
* <p><strong>Example Usage:</strong></p>
2582+
* <pre><code>
2583+
* // Wait for JavaScript tasks starting within 1 second, with 10 second max timeout
2584+
* int remainingJobs = webClient.waitForBackgroundJavaScriptStartingBefore(1000, 10000);
2585+
* if (remainingJobs == 0) {
2586+
* log("All relevant background JavaScript completed");
2587+
* } else {
2588+
* log("Timeout reached or tasks still pending: " + remainingJobs + " jobs");
2589+
* }
2590+
*
2591+
* // Wait indefinitely for tasks starting within 500ms (timeout ignored)
2592+
* webClient.waitForBackgroundJavaScriptStartingBefore(500, 100); // timeout < delay
2593+
* </code></pre>
2594+
*
2595+
* @param delayMillis the delay which determines the background tasks to wait for (in milliseconds);
2596+
* must be non-negative
2597+
* @param timeoutMillis the maximum amount of time to wait (in milliseconds); if negative or
2598+
* less than <code>delayMillis</code>, the timeout is ignored and the method
2599+
* waits indefinitely for qualifying tasks to complete
2600+
* @return the number of background JavaScript jobs still executing or waiting to be executed
2601+
* when this method returns; returns <code>0</code> if all qualifying jobs completed
2602+
* successfully within the specified constraints
2603+
* @see #waitForBackgroundJavaScript(long)
2604+
* @see #waitForBackgroundJavaScriptStartingBefore(long)
25182605
*/
25192606
public int waitForBackgroundJavaScriptStartingBefore(final long delayMillis, final long timeoutMillis) {
25202607
int count = 0;

0 commit comments

Comments
 (0)