Skip to content

[Edge] Use getWebView(false) in registerFunctionScript to avoid pumping past NavigationCompleted#3256

Draft
HeikoKlare wants to merge 1 commit intoeclipse-platform:masterfrom
HeikoKlare:fix/edge-registerFunctionScript-getWebView
Draft

[Edge] Use getWebView(false) in registerFunctionScript to avoid pumping past NavigationCompleted#3256
HeikoKlare wants to merge 1 commit intoeclipse-platform:masterfrom
HeikoKlare:fix/edge-registerFunctionScript-getWebView

Conversation

@HeikoKlare
Copy link
Copy Markdown
Contributor

Problem

registerFunctionScript called getWebView(true), which pumps the event loop via processOSMessagesUntil until all pending WebView2 tasks in lastWebViewTask are done. When createFunction() is called after setUrl(), the pending tasks include the Navigate call scheduled by setUrl. Pumping until that task completes gives WebView2 enough time to also fire NavigationCompleted — before the caller of createFunction() has had a chance to register a ProgressListener.

As a result, the NavigationCompleted event is dispatched and lost inside registerFunctionScript, the ProgressListener never fires, and any test that registers a ProgressListener after creating a BrowserFunction will time out. This manifested as a flaky failure of test_BrowserFunction_availableOnLoad_concurrentInstances_issue20 in CI builds (see issue #3254).

The asyncExec deferral in createFunction does not help in this scenario because it only triggers when createFunction is called from inside a WebView2 callback (inCallback > 0). When called from regular Java code, inCallback == 0 and registerFunctionScript is entered synchronously.

Fix

Change getWebView(true) to getWebView(false) in registerFunctionScript. getWebView(false) limits the event loop pump to waiting only for WebView2 initialization (webViewWrapperFuture::isDone). The Navigate call is chained on the ForkJoinPool after initialization completes and cannot have executed yet when getWebView(false) returns, so NavigationCompleted cannot fire during registerFunctionScript. AddScriptToExecuteOnDocumentCreated is still called on a fully initialized WebView2 instance, so the behaviour is otherwise identical.

The currently loaded document is not affected by this change: super.createFunction() already injects the function script into the current document via nonBlockingExecute() before registerFunctionScript is entered.

Related

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 19, 2026

Test Results (win32)

   29 files     29 suites   4m 31s ⏱️
4 640 tests 4 567 ✅ 72 💤 0 ❌ 1 🔥
1 170 runs  1 148 ✅ 21 💤 0 ❌ 1 🔥

For more details on these errors, see this check.

Results for commit a07954a.

♻️ This comment has been updated with latest results.

…ng past NavigationCompleted

Previously, registerFunctionScript called getWebView(true), which pumps
the event loop until all pending WebView2 tasks in lastWebViewTask are
done — including any Navigate call scheduled by a preceding setUrl().
This caused NavigationCompleted to fire during the pump, before the
caller of createFunction() had a chance to register a ProgressListener.
The NavigationCompleted event was therefore lost and the ProgressListener
never fired, causing tests that register the listener after creating a
BrowserFunction to time out.

Using getWebView(false) limits the pump to waiting only for WebView2
initialization (webViewWrapperFuture::isDone). The Navigate call is
chained on the ForkJoinPool after initialization completes and cannot
have run yet when getWebView(false) returns, so NavigationCompleted
cannot fire during registerFunctionScript. AddScriptToExecuteOnDocumentCreated
is still called on a fully initialized WebView2 instance.

The currently loaded document is not affected: super.createFunction()
already injects the function script into it via nonBlockingExecute()
before registerFunctionScript is entered.

See eclipse-platform#3254

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@HeikoKlare
Copy link
Copy Markdown
Contributor Author

This change (though probably reasonable) does not fix the actual issue. The latest CI run shows the test failure that was supposed to be fixed:

options is not defined
org.eclipse.swt.SWTException: options is not defined
	at org.eclipse.swt.browser.Edge.evaluateInternal(Edge.java:1003)
	at org.eclipse.swt.browser.Edge.evaluate(Edge.java:976)
	at org.eclipse.swt.browser.WebBrowser.evaluate(WebBrowser.java:405)
	at org.eclipse.swt.browser.Browser.evaluate(Browser.java:735)
	at org.eclipse.swt.browser.Browser.evaluate(Browser.java:684)
	at org.eclipse.swt.tests.junit.Test_org_eclipse_swt_browser_Browser.lambda$156(Test_org_eclipse_swt_browser_Browser.java:3008)
	at org.eclipse.swt.browser.ProgressListener$2.completed(ProgressListener.java:97)
	at org.eclipse.swt.browser.Edge.lambda$44(Edge.java:1218)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:40)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:131)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4136)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3752)
	at org.eclipse.swt.tests.junit.Test_org_eclipse_swt_browser_Browser.waitForPassCondition(Test_org_eclipse_swt_browser_Browser.java:3139)
	at org.eclipse.swt.tests.junit.Test_org_eclipse_swt_browser_Browser.waitForPassCondition(Test_org_eclipse_swt_browser_Browser.java:3105)
	at org.eclipse.swt.tests.junit.Test_org_eclipse_swt_browser_Browser.test_BrowserFunction_availableOnLoad_concurrentInstances_issue20(Test_org_eclipse_swt_browser_Browser.java:3035)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Test_org_eclipse_swt_browser_Browser.test_BrowserFunction_availableOnLoad_concurrentInstances_issue20 failed on Win32 in I20260418-1800

1 participant