Skip to content

Conversation

@HeikoKlare
Copy link
Contributor

Edge compares the result of WebView initialization with an HRESULT created from a Windows error code via the HRESULT_FROM_WIN32 macro. The actual result in that initialization callback is a long while the HRESULT returned from the macro is represented as integer in SWT. The current comparison of long and integer does not take into account that the values are signed. In this specific case, the actual HRESULT to compare against is 2147947423 while the HRESULT_FROM_WIN32 macro returns the signed value -2147019873. The actual result needs to be converted into a signed integer as well, as otherwise it will be considered as 2147947423, thus never matching the expected HRESULT value.

This change converts the processed result into an integer to correct the comparison.

@HeikoKlare
Copy link
Contributor Author

Issue became obivous in this build, which shows that the comparison should have yielded "true" but did not: https://github.com/eclipse-platform/eclipse.platform.swt/actions/runs/13056049227/job/36427241188?pr=1706

[2025-01-30 16:00:29 +0000] org.eclipse.swt.tests.junit.Test_org_eclipse_swt_browser_Browser.test_BrowserFunction_callback_afterPageReload[browser flags: 0]() failed:
org.eclipse.swt.SWTError: Unspecified error Aborting Edge initialiation after 5 retries with result 2147947423
	at org.eclipse.swt.SWT.error(SWT.java:4957)
	at org.eclipse.swt.browser.Edge.lambda$15(Edge.java:632)
	at org.eclipse.swt.browser.Edge.lambda$5(Edge.java:237)
	at org.eclipse.swt.internal.win32.OS.DispatchMessage(Native Method)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3688)
	at org.eclipse.swt.browser.Edge.processOSMessagesUntil(Edge.java:467)
	at org.eclipse.swt.browser.Edge$WebViewProvider.getWebViewWrapper(Edge.java:369)
	at org.eclipse.swt.browser.Edge$WebViewProvider.getWebView(Edge.java:380)
	at org.eclipse.swt.browser.Edge.getUrl(Edge.java:891)
	at org.eclipse.swt.browser.Browser.getUrl(Browser.java:771)
	at org.eclipse.swt.tests.junit.Test_org_eclipse_swt_browser_Browser.createBrowser(Test_org_eclipse_swt_browser_Browser.java:307)
	at org.eclipse.swt.tests.junit.Test_org_eclipse_swt_browser_Browser.setUp(Test_org_eclipse_swt_browser_Browser.java:190)

" Edge instance with same data folder but different environment options already exists");
}
switch ((int) result) {
switch (result) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it is a long, maybe just use a switch here and instead if/else chain would be more future proof?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that we use integers to represent HRESULT values in SWT all over the place. This also includes the "improper" signing of these values, as in the Windows API they have always been unsigned values (which Java is not able to represent). That's why we also have constants (like E_ABORT used in this switch) represented as signed integer values.

For that reason, I would propose to stick to integer in all the result code processing for now. As a separate topic, I would be in favor of completely replacing all tretments of HRESULT as integer in the OS APIs and constants with long values.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also includes the "improper" signing of these values, as in the Windows API they have always been unsigned values (which Java is not able to represent).

I don't think this is particular true. Java can represent an "unsigned" long but one has to be careful when comparing them or perform math, beside from that you can do whatever you want with them (including equals comparison).

Also I'm not sure that "because we do it everywhere" is a good argument here ... maybe this is a good reason to start with something new, e.g. make a HRESULT(long) record and use that whenever possible with a HRESULT#match(...) that makes sure one do no "illegal" operations on this here (like using it as a long).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As said: I agree that there is some need for general improvement and I will create an issue for that. But starting with some locally introduced improvement for HRESULT processing that is incompatible with the OS APIs (that currently treat HRESULT as int) does not make sense to me. The current assumption is that HRESULT is an int, so we need to treat it like that. If we want to replace that (of which I would be in favor), we need to do that everywhere.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 31, 2025

Test Results

   494 files  ±0     494 suites  ±0   10m 52s ⏱️ - 1m 18s
 4 333 tests ±0   4 320 ✅ ±0   13 💤 ±0  0 ❌ ±0 
16 574 runs  ±0  16 466 ✅ ±0  108 💤 ±0  0 ❌ ±0 

Results for commit e677954. ± Comparison against base commit 3e45b23.

♻️ This comment has been updated with latest results.

};
return newCallback((result, pv) -> {
return newCallback((resultAsLong, pv) -> {
int result = (int) resultAsLong;
Copy link
Contributor

@laeubi laeubi Jan 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int result = (int) resultAsLong;
int result = (int) resultAsLong & 0xFFFFFF;

I think this would be the correct way to truncate an unsigned long to an int (in java).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resultAsLong is a value passed via JNI that was converted from native unsigned long to jint. I have no idea how to best truncate that to Java int, but as said above: this all should be revised independently. The change in this PR just sticks to existing conversion behavior (for which we know it worked expect for this line that did a wrong comparison).
So would not be in favor of changing conversion here with no real gain and in the worst case the risk of a regression.

Edge compares the result of WebView initialization with an HRESULT
created from a Windows error code via the HRESULT_FROM_WIN32 macro. The
actual result in that initialization callback is a long while the
HRESULT returned from the macro is represented as integer in SWT. The
current comparison of long and integer does not take into account that
the values are signed. In this specific case, the actual HRESULT to
compare against is 2147947423 while the HRESULT_FROM_WIN32 macro returns
the signed value -2147019873. The actual result needs to be converted
into a signed integer as well, as otherwise it will be considered as
2147947423, thus never matching the expected HRESULT value.

This change converts the processed result into an integer to correct the
comparison.
@HeikoKlare
Copy link
Contributor Author

Summarizing: In order to keep the conversion of long result values to int result values consistent with other places in the SWT Win32 implementation and thus avoid confusion due to inconsistent processing of the same kind of data, I keep the implementation as is. and focus on the bugfix here. I leave it up for future, holistic refactoring to clean up all places doing this kind of conversion.

The validation failures are unrelated and known.

@HeikoKlare HeikoKlare merged commit b0a1fb7 into eclipse-platform:master Jan 31, 2025
10 of 14 checks passed
@HeikoKlare HeikoKlare deleted the edge_hresult_int branch January 31, 2025 17:56
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.

2 participants