Repository navigation
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a helper method ToDisplayId in DisplayManagerWin32 to convert HMONITOR handles to FlutterEngineDisplayId by truncating them to 32-bit values, which strips sign extension and prevents representation issues in Dart. The display manager, window implementation, and unit tests have been updated to use this method. There are no review comments, and I have no feedback to provide.
|
Marking this as a draft to stay within the two active PR limit while I prioritize another change. Reviews are still welcome, and I will set it back to Ready once the other one lands. |
knopp
left a comment
There was a problem hiding this comment.
I don't know if this is the best fix. I'm looking at dart_converter.h from tonic
// TODO(abarth): The Dart VM API doesn't yet have an entry-point for
// an unsigned 64-bit type. We will need to add a Dart API for
// constructing an integer from uint64_t.
//
// (In the meantime, we have asserts below to check that we're never
// converting values that have the 64th bit set.)
static Dart_Handle ToDart(unsigned long long val) {
TONIC_DCHECK(val <= 0x7fffffffffffffffLL);
return Dart_NewInteger(static_cast<int64_t>(val));
}But Dart also have Dart_NewIntegerFromUint64 and it's been there for a while - seems to me that we should maybe fix this in tonic?
|
Never mind, |
|
This is from /// Display refers to a graphics hardware system consisting of a framebuffer,
/// typically a monitor or a screen. This ID is unique per display and is
/// stable until the Flutter application restarts.
typedef uint64_t FlutterEngineDisplayId;It doesn't mention anything about allowed ranges, so this really seems like a bug in the engine itself rather than windows embedder. |
|
@knopp You're right, this is not a Windows problem, it is the type.
I used the One question before I push: |
|
It seems to me that the existence of As for the Dart DisplayId comment - It is not entirely correct but we do not want users to make assumptions about the DisplayId in general. |
Dart ints are signed 64-bit, so a display ID above INT64_MAX can't be represented in Dart. What actually happened with such an ID depended on the toolchain. tonic's DartConverter<unsigned long long> asserted the range, while every other integer type has no check. So it came down to what size_t is: on MSVC x64 debug builds aborted, on LP64 the same ID silently wrapped negative. This removes the specialization, as suggested by knopp, so all platforms behave the same now: values above INT64_MAX become the corresponding negative Dart integer, distinct values remain distinct. The dropped constants have no other users and nothing relied on the assert. DisplayId itself was size_t, but the ABI says uint64_t, so 32-bit builds truncated IDs at the embedder boundary. It is int64_t now (like FlutterViewId), with one explicit cast at the boundary, and ViewportMetrics::display_id got the same change. The tonic change alone fixes the crash, the typedef fixes the 32-bit narrowing. This replaces the HMONITOR masking this PR originally proposed. Test: EmbedderTest.SetSingleDisplayConfigurationWithDisplayIdAboveInt64Max sends 0xFFFFFFFFE02E16A5, a real sign-extended HMONITOR, and checks it reaches Dart as the negative equivalent through both the display list and the window metrics. Fixes flutter#189564
cf65c53 to
2125d14
Compare
|
Done. Removed the specialization, so unsigned long long converts like every other integer type now and the assert is gone on all platforms. Kept the int64_t typedef as well, 32-bit builds truncated the ID at the embedder boundary before the converter was even reached. The Display.id comment stays as it is. Retitled and pushed. |
Dart ints are signed 64-bit, so a display ID above
INT64_MAXcan't be represented in Dart. What actually happened with such an ID depended on the toolchain.tonic's
DartConverter<unsigned long long>asserted the range, while every other integer type has no check. So it came down to whatsize_tis: on MSVC x64 debug builds aborted, on LP64 the same ID silently wrapped negative. This removes the specialization, as suggested in review, so all platforms behave the same now: values aboveINT64_MAXbecome the corresponding negative Dart integer, distinct values remain distinct. The dropped constants have no other users and nothing relied on the assert.DisplayIditself wassize_t, but the ABI saysuint64_t, so 32-bit builds truncated IDs at the embedder boundary. It isint64_tnow (likeFlutterViewId), with one explicit cast at the boundary, andViewportMetrics::display_idgot the same change. The tonic change alone fixes the crash, the typedef fixes the 32-bit narrowing.This replaces the HMONITOR masking this PR originally proposed.
EmbedderTest.SetSingleDisplayConfigurationWithDisplayIdAboveInt64Maxsends0xFFFFFFFFE02E16A5, a real sign-extended HMONITOR, and checks it reaches Dart as the negative equivalent through both the display list and the window metrics. Without the fix it reproduces the crash from the issue on Windows:On LP64 the old behavior already wrapped to the same value, so there the test pins the behavior down rather than catching a regression.
Fixes #189564
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.