FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(macos): Stop two native-peer use-after-free crashes in CI by MartinZikmund · Pull Request #24112 · unoplatform/uno · GitHub

fix(macos): Stop two native-peer use-after-free crashes in CI - #24112

Merged
MartinZikmund merged 7 commits into
feature/breakingchangesfrom
dev/mazi/flakiness
Aug 23, 2026
Merged

fix(macos): Stop two native-peer use-after-free crashes in CI#24112
MartinZikmund merged 7 commits into
feature/breakingchangesfrom
dev/mazi/flakiness

Conversation

MartinZikmund commented Aug 19, 2026
edited
Loading

Copy link
Copy Markdown
Member

GitHub Issue: closes #24111

PR Type:

🐞 Bugfix

What changed? 🚀

macOS native-peer lifetime defects that take down the whole Tests - Desktop Skia macOS job with a SIGSEGV, losing the results of every other test in the run.

Scope: macOS only. The default test-body timeout moved to #24162 and the Hot Reload test fixes to #24125, so each change set stands on its own.

Root cause: native peers were created unowned

uno_webview_create, uno_mediaplayer_create_view and uno_native_create_sample all end in objc_autoreleaseReturnValue — confirmed by disassembling the shipped dylib, not by reading the source. The handle they hand back to managed code is owned by nothing but the current autorelease pool. The native side only took a strong reference later, at uno_native_attach, which adds the view to the elements set.

So any element that is never attached, or whose attach lands in a later run-loop turn than its creation, is already deallocated. Both uno_native_attach and uno_native_dispose begin with an ARC objc_retain of their parameter, so the next call takes the process down at +0x1f.

Three CI core dumps from this branch all fault at the same image offset, which symbolizes to uno_native_dispose retaining a freed NSView.

Fix: uno_native_track takes the strong reference at creation. Ownership is now continuous — transients from birth, elements while attached, back to transients on detach — until uno_native_dispose drops both and deallocates.

Peers no longer die on a reparent

MacOSNativeElement destroyed its NSView from Unloaded, but Unloaded also fires on a reparent and the framework re-enters the very same element through AttachNativeElement. A WebView2 removed from and re-added to the tree came back dead — which is what failed When_WebMessageReceived_After_RemoveAdd. Neither the X11 nor the Win32 hosting extension destroys its peer on unload.

The peer's lifetime now follows the managed wrapper: the finalizer releases it, dispatched to the main thread since AppKit is main-thread only. The disposed-handle guards stay as hardening — they can no longer be reached through a reparent.

addScriptMessageHandler:name: raises on a name that is already registered, and the WKWebView now survives the round trip, so registration removes the previous handler first and OnUnloaded unregisters symmetrically with OnLoaded. The stale private _webview shadow copy of the handle is gone; every call resolves through TryGetHandle.

A dropped frame no longer stops rendering permanently

drawInMTKView: returned without calling managed code when currentDrawable was nil. The view runs with enableSetNeedsDisplay, so AppKit had already cleared needsDisplay to make that call, and the managed side latches its own request: CompositionTarget.RequestNewFrame sets RenderRequested and only clears it from OnNativePlatformFrameRequested, which the dropped frame never reaches. Every later RequestNewFrame then coalesced into an invalidation that had already been consumed, so a single nil drawable stopped that window rendering for good. It now re-arms needsDisplay on a later main-queue turn. The software path never had the defect — it calls the managed callback before its own early return.

Validation

Change Evidence
Unowned native peer Runtime. Reproduced against the exact dylib CI built, using uno_mediaplayer_create_view (no arguments): create → drain the pool → uno_native_dispose gives Segmentation fault: 11, exit 139 — the same exit code CI reported. The fixed dylib survives, exit 0.
Reparent survival Runtime. When_WebMessageReceived_After_RemoveAdd passes on macOS Skia; Given_WebView2 9/9.
No regression Runtime. Given_WebView2 + Given_MediaPlayerElement + Given_ContentPresenter: 278 passed, 0 failed, clean exit.
Nil-drawable re-arm Code review only. A nil drawable cannot be forced on a healthy Mac, so the latch is established by inspection of both sides rather than by a repro. Given_ListViewBase shows no regression (144/146; the one failure, When_ThemeChange, fails identically without this change).

One claim to correct from an earlier revision of this description: the nil-drawable fix was described as the cause of the macOS 60-minute job hangs. That is not established. UITestHelper.WaitForRender does have a 1000 ms bound, and NativeDispatcher.TryGetRenderAction consumes a render action one-shot, so a dead render loop makes a test fail in about a second rather than hang. The latch is a genuine defect worth fixing on its own terms; it is not the hang's explanation. The hang reproduces on feature/breakingchanges without any of this PR's code and is tracked separately.

PR Checklist ✅

  • 🧪 Added Runtime tests, UI tests, or a manual test sample (for bug fixes / features, if applicable)
    • When_WebMessageReceived_After_RemoveAdd already existed and is the fail-before/pass-after case for the reparent fix. The ownership defect is covered by a native repro described above; there is no managed harness that can reach it.
  • 📚 Docs have been added/updated following the documentation template (for bug fixes / features)
    • Not applicable: no public API or user-facing behaviour change.
  • 🖼️ Validated PR Screenshots Compare Test Run results.
  • ❗ Contains NO breaking changes
  • 👀 Reviewed 2 other open pull requests (optional but appreciated!)

🤖 Generated with Claude Code

https://claude.ai/code/session_014LKUHFiW2J8nNFy7FmuCsd

github-actions Bot added platform/macos 🍏 Categorizes an issue or PR as relevant to the macOS platform area/automation Categorizes an issue or PR as relevant to project automation labels Aug 19, 2026

github-actions Bot commented Aug 19, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 5m 9s —— View job


Code Review

  • Load tools
  • Read changed files
  • Review UnitTestsControl.cs (default timeout)
  • Review MacOSNativeElementHostingExtension.cs (dangling handle fix)
  • Review UNONative.m (ObjC entry-point guards)
  • Review Given_ClientHotReloadProcessor.cs (RID oracle)
  • Review Given_HotReloadWorkspace.cs (workspace scenario)
  • Post inline comments
  • Write summary

Overall verdict: ✅ Approve with minor concerns

All four changes address real, well-evidenced CI reliability defects. The root causes are correctly identified, the fixes are narrowly scoped, and the PR description is unusually thorough. No blocking issues.

1 medium finding, 3 minor findings posted as inline comments:

# Severity File Issue
1 Medium MacOSNativeElementHostingExtension.cs:85 LogLevel.Error for the expected reparent-after-dispose path will fire on every arrange/attach/detach/measure call on a reparented native element (e.g., each MediaPlayerElement full-window toggle). Should be LogLevel.Warning to match "known degraded path" semantics.
2 Minor UnitTestsControl.cs:1364 When UNO_TEST_DEFAULT_TIMEOUT_SECONDS is set to an invalid value (e.g. "5m", a typo), the fallback is applied silently — no log, no indication the env var was ignored. Makes misconfiguration hard to diagnose on CI.
3 Minor MacOSNativeElementHostingExtension.cs:43 If NativeHandle is 0 at disposal time (peer never assigned), uno_native_dispose(0) is called unnecessarily. The ObjC guard catches it safely, but a if (handle != 0) short-circuit would clarify intent.
4 Minor Given_HotReloadWorkspace.cs:101 The bare filter == nameof(When_HotReloadScenario) and EndsWith("." + nameof(...)) predicates could theoretically strip an HRApp test with the same method name. Very low practical risk; noted for awareness as the HRApp suite grows.

Cross-cutting notes

UNONative.m — The null guard is correctly placed only on uno_native_dispose, which is the only entry point callable with a zero handle from C# (via DisposeNativePeer without going through TryGetLiveElement). All other native functions are gated by TryGetLiveElement on the C# side. The asymmetry is intentional and correct.

Given_ClientHotReloadProcessor.cs — The RID-to-platform mapping is clean: only recognized prefixes are mapped, the null oracle path adds a non-empty-platform assertion rather than a hard equality check, and the test is correctly void (no await). The removal of the [PlatformCondition(Exclude, SkiaAndroid)] workaround is correctly motivated.

Timeout cancellation pattern (UnitTestsControl.cs:1025-1039) — The using var timeoutCts + timeoutCts.Cancel() before the using block exits is the correct pattern: the delay task is cancelled when the test finishes first (no lingering timer per test), and a cancelled Task.Delay becomes TaskStatus.Canceled (not faulted), so no unobserved-exception risk.

DisposeNativePeer ordering — Capturing the handle before setting Disposed = true and zeroing NativeHandle is correct: the guard runs first, the state transition is atomic enough on the UI thread, and the native call uses the captured (non-zero) pointer.

Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24112/wasm-skia-net9/index.html

MartinZikmund requested a review from Xiaoy312 August 19, 2026 07:54

github-actions Bot commented Aug 19, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 4m 49s —— View job


Code Review

  • Read changed files
  • Review UnitTestsControl.cs (default timeout)
  • Review MacOSNativeElementHostingExtension.cs (dangling handle fix)
  • Review UNONative.m (ObjC entry-point guards)
  • Review Given_ClientHotReloadProcessor.cs (RID oracle)
  • Review Given_HotReloadWorkspace.cs (workspace scenario)
  • Review HotReloadHelper.cs (fail-fast guard, new commit)
  • Review Given_HotReloadResilience.cs (element-name fix, new commit)
  • Post inline comments
  • Write summary

Overall verdict: ✅ Approve with minor concerns

Two new commits were added since the previous review. Both are correct and clean.

Commit test(hotreload): Assert on page content that exists (Given_HotReloadResilience.cs) — Straightforward fix: the page declares FirstPageTextBlock (Text="First page"), not tb1/tb/Hello. Both tests now reference the element and text that actually exist in HR_Frame_Pages_Page1. No issues.

Commit test(hotreload): Fail fast when a file edit matches nothing (HotReloadHelper.cs) — The EnsureOriginalTextIsPresent guard is well-placed (called after both early-return guards, only when a message will actually be sent). The edited = false flag pattern in both UpdateProjectFileAndRevert and UpdateServerFileAndRevert correctly prevents a double-throw when the initial edit failed. The finally-block in When_VisualTree_Paused_Then_ReloadCompleted_StillFires remains safe: the outer try-finally is never entered if UpdateServerFile throws inside the using block, so no unintended revert can fire.

One pre-existing issue worth noting (not in this PR's diff, so no inline comment): UpdateServerFile(string filePathInProject, …) at line ~110 has if (message is null) { return; } on a value that can never be null (new UpdateSingleFileRequest { … }). This is a copy-paste artifact from the generic UpdateServerFile<T> overload where CreateUpdateFileMessage CAN return null. Harmless dead code, but worth cleaning up separately.

Outstanding findings (from previous review, still open)

The four findings from the previous review pass are not addressed in the two new commits:

# Severity File Finding
1 Medium MacOSNativeElementHostingExtension.cs:84 LogLevel.Error fires on every arrange/attach/measure on any reparented native element (the known "MediaPlayerElement full-window toggle" path). Should be LogLevel.Warning.
2 Minor UnitTestsControl.cs:1364 Invalid UNO_TEST_DEFAULT_TIMEOUT_SECONDS (e.g. "5m") silently falls back — no log, no diagnostic on CI.
3 Minor MacOSNativeElementHostingExtension.cs:43 uno_native_dispose(0) called when NativeHandle was never assigned; ObjC guard is safe but a if (handle != 0) short-circuit clarifies intent.
4 Minor Given_HotReloadWorkspace.cs:101 IsOuterTestFilter bare-name check could theoretically strip an HRApp test whose method is literally named When_HotReloadScenario; very low practical risk.

github-actions Bot commented Aug 19, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 6m 20s —— View job


Code Review

  • Load tools
  • Read changed files
  • Review UnitTestsControl.cs (default timeout)
  • Review MacOSNativeElementHostingExtension.cs (dangling handle fix)
  • Review UNONative.m (ObjC entry-point guards)
  • Review hot-reload test files (prior commits, covered by prior review passes)
  • Post inline comments
  • Write summary

Overall verdict: ✅ Approve with minor concerns

This review covers the two commits in this synchronize: fix(macos) and test: Bound every runtime test body. Both are correct and address real CI reliability defects with well-evidenced root causes. No new blocking issues.

4 outstanding findings from prior review passes remain unaddressed:

# Severity File Issue
1 Medium MacOSNativeElementHostingExtension.cs:82 LogLevel.Error fires on every layout/attach/measure call after any reparent (e.g., each MediaPlayerElement full-window toggle). The PR description calls this path a "known design defect"; it should be LogLevel.Warning so log aggregation can distinguish it from unexpected errors.
2 Minor UnitTestsControl.cs:1362 Invalid UNO_TEST_DEFAULT_TIMEOUT_SECONDS (non-integer, e.g. "5m") silently falls back to the default with no log entry — the misconfiguration is invisible on CI.
3 Minor MacOSNativeElementHostingExtension.cs:45 uno_native_dispose(handle) is called even when NativeHandle was never assigned (handle == 0). The ObjC nil-guard handles it safely; an if (handle != 0) short-circuit would clarify intent.
4 Minor Given_HotReloadWorkspace.cs:61 The bare-name and EndsWith predicates that strip the outer test from the filter could theoretically match an HRApp test with the same method name. Very low practical risk; documented for awareness as the HRApp suite grows.

Cross-cutting notes on the new commits:

fix(macos) — MacOSNativeElementHostingExtension.cs + UNONative.m

The root-cause analysis is correct: Unloaded fires on reparent, the old code called uno_native_dispose and walked away leaving NativeHandle stale, and the subsequent uno_native_attach on the freed pointer caused ARC to retain freed memory. The fix is properly terminal on both sides:

  • The C# wrapper zeroes NativeHandle, sets Disposed, and gates every subsequent operation through TryGetLiveElement.
  • The ObjC side removes from both elements and transients so a disposed view cannot be resurrected through either strong-reference set. The comment at line 155–158 of UNONative.m correctly explains why both are needed.
  • The if (!element) guard is correctly placed only on uno_native_dispose, the only entry point reachable with a zero handle from C# (other entry points are gated by TryGetLiveElement first). The asymmetry is intentional.

test: Bound every runtime test body — UnitTestsControl.cs

The using var timeoutCts + timeoutCts.Cancel() before the WhenAny result is inspected is the correct pattern: the delay task is cancelled as soon as the test body finishes (no lingering timer per test), and a cancelled Task.Delay becomes TaskStatus.Canceled (not faulted), so no unobserved-exception risk. The DEBUG/release split (null vs 5 min) and the UNO_TEST_DEFAULT_TIMEOUT_SECONDS override path are clean.

MartinZikmund changed the title fix: CI reliability — dangling macOS native handle, unbounded test bodies, two tests that cannot fail fix: CI reliability — dangling macOS native handle, unbounded test bodies Aug 19, 2026

Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24112/wasm-skia-net9/index.html

Copy link
Copy Markdown
Contributor

The build 228603 found UI Test snapshots differences: skia-linux-screenshots: 73, skia-windows-screenshots: 135

Details
  • skia-linux-screenshots: 73 changed over 2366

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • CalendarView_Theming.png-dark
    • DropDownButtonPage.png-dark
    • ExpanderColorValidationPage.png-dark
    • ExpanderColorValidationPage.png
    • Gamepad_CurrentReading.png-dark
    • Gamepad_CurrentReading.png
    • Gamepad_Enumeration.png-dark
    • DynamicFont.png
    • Examples.png
    • Image_Margin_Large.png
    • ImageIconPage.png-dark
    • ImageIconPage.png
    • ImageBrush_Stretch.png
    • Buttons.png
    • ElementLevelTheme.png-dark
    • ElementLevelTheme.png
    • ImageBrushInList.png-dark
    • ImageBrushInList.png
  • skia-windows-screenshots: 135 changed over 2366

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Basics Pivot Test.png-dark
    • Basics Pivot Test.png
    • Battery.png
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • CameraCaptureUISample.png-dark
    • CameraCaptureUISample.png
    • ContentPresenter_Template.png-dark
    • ContentPresenter_Template.png
    • EmailManagerTests.png-dark
    • EmailManagerTests.png
    • Examples.png
    • Haptics.VibrationDevice.png-dark
    • Haptics.VibrationDevice.png
    • AuthenticationBroker_Demo.png-dark
    • CalendarView_Theming.png-dark
    • CalendarView_Theming.png
    • Contacts_Pick.png-dark
    • Contacts_Pick.png
    • DamageRegion_Shadow.png-dark

github-actions Bot commented Aug 20, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 2m 56s —— View job


Code Review

  • Load tools
  • Read changed files
  • Review UnitTestsControl.cs (default timeout)
  • Review MacOSNativeElementHostingExtension.cs (dangling handle fix)
  • Review UNONative.m (ObjC entry-point guards)
  • Post inline comments
  • Write summary

Overall verdict: ⚠️ Fix before merge

This review covers the current state of the 3 changed files (UnitTestsControl.cs, MacOSNativeElementHostingExtension.cs, UNONative.m). The Hot Reload test files are correctly scoped out to #24125.

1 new medium finding posted as an inline comment. 3 prior findings remain unaddressed.

Outstanding findings

# Severity File Issue Status
1 Medium MacOSNativeElementHostingExtension.cs:182 Size.Empty returns (-∞, -∞) — layout system throws for negative infinity on the disposed-peer path, defeating the "logged no-op" intent. Fix: return new Size(0, 0). 🆕 New
2 Medium MacOSNativeElementHostingExtension.cs:82 LogLevel.Error fires on every arrange/attach/measure call after a reparent (e.g. each MediaPlayerElement full-window toggle). The PR describes this as a "known design defect"; use LogLevel.Warning so log aggregation can distinguish it from unexpected errors. Prior review
3 Minor UnitTestsControl.cs:1364 When UNO_TEST_DEFAULT_TIMEOUT_SECONDS is set to an invalid value (e.g. "5m"), the fallback is applied silently — no log, invisible misconfiguration on CI. A warning log at the parse-failure branch would help diagnose bad CI config. Prior review
4 Minor MacOSNativeElementHostingExtension.cs:43 uno_native_dispose(handle) is called even when NativeHandle was never assigned (handle == 0). The ObjC null guard catches it safely; an if (handle != 0) short-circuit clarifies intent. Prior review

What's correct

  • UNONative.m — null guard only on uno_native_dispose, which is the only entry point reachable with a zero handle from C#. Removal from both elements and transients is correct and necessary; the comment explains why both are needed.
  • DisposeNativePeer ordering — handle captured before Disposed = true / NativeHandle = 0, state transition is correct on the UI thread, native call uses the captured non-zero pointer.
  • Timeout cancellation — using var timeoutCts + timeoutCts.Cancel() before the WhenAny result is inspected correctly prevents lingering per-test timers. Cancelled Task.Delay is TaskStatus.Canceled, not faulted — no unobserved-exception risk.
  • TryGetLiveElement guards — correctly gates all five native entry points (arrange, attach, detach, measure, is-attached) through a single, consistent check.

Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24112/wasm-skia-net9/index.html

Copy link
Copy Markdown
Contributor

The build 228879 found UI Test snapshots differences: skia-linux-screenshots: 73, skia-windows-screenshots: 195

Details
  • skia-linux-screenshots: 73 changed over 2366

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Focus_FocusVisual_Properties.png-dark
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • ContextRequested.png-dark
    • DynamicFont.png
    • DisplayInformation.png-dark
    • DisplayInformation.png
    • ImageBrushInList.png-dark
    • ImageBrushInList.png
    • Image_Margin_Large.png
    • DropDownButtonPage.png-dark
    • ExpanderColorValidationPage.png-dark
    • ExpanderColorValidationPage.png
    • ImageBrush_Stretch.png
    • ImageIconPage.png-dark
    • ImageIconPage.png
    • ClipboardTests.png-dark
    • ClipboardTests.png
    • Buttons.png
    • Examples.png
  • skia-windows-screenshots: 195 changed over 2368

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • ClipboardTests.png-dark
    • ExpanderColorValidationPage.png-dark
    • Examples.png
    • FocusManagerTest.png-dark
    • FocusManagerTest.png
    • Hyperlink_Disabled.png-dark
    • Battery.png-dark
    • DropDownButtonPage.png-dark
    • Focus_FocusState.png-dark
    • Focus_FocusState.png
    • CalendarView_Theming.png-dark
    • CalendarView_Theming.png
    • EllipsemaskingEllipseGrid.png
    • ContentPresenter_NativeEmbedding_Android_FillType.png
    • BitmapImage_vs_SvgImageSource.png
    • ImageBrushInList.png-dark
    • ImageBrushInList.png
    • ImageBrushLocalAsset.png-dark
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png

github-actions Bot commented Aug 21, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 2m 45s —— View job


Code Review

  • Load tools
  • Read changed files
  • Review UnitTestsControl.cs (default timeout)
  • Review MacOSNativeElementHostingExtension.cs (dangling handle fix)
  • Review UNONative.m (ObjC entry-point guards)
  • Post inline comments
  • Write summary

Overall verdict: ⚠️ Fix before merge

This review covers the current state of the 3 changed files (UnitTestsControl.cs, MacOSNativeElementHostingExtension.cs, UNONative.m). The commits are unchanged since the prior review pass — all 4 outstanding findings remain unaddressed.

Outstanding findings (all from prior passes, no new issues found)

# Severity File Issue
1 Medium MacOSNativeElementHostingExtension.cs:182 Size.Empty is {-∞, -∞} (confirmed: src/Uno.Foundation/Size.cs:31). When TryGetLiveElement rejects a disposed element, this flows into Layouter.MeasureCore, which throws InvalidOperationException for any infinity (lines 108–116) — turning the "logged no-op" into a managed exception. Fix: return new Size(0, 0);
2 Medium MacOSNativeElementHostingExtension.cs:82 LogLevel.Error fires on every arrange/attach/detach/measure call after a reparent (e.g. each MediaPlayerElement full-window toggle). The PR description calls this path a "known design defect" and a "logged no-op" — use LogLevel.Warning so log aggregation can distinguish it from unexpected errors.
3 Minor UnitTestsControl.cs:1364 When UNO_TEST_DEFAULT_TIMEOUT_SECONDS is set to an invalid value (e.g. "5m"), the parse fails silently and the fallback is applied with no log entry — the misconfiguration is invisible on CI. A warning log in the !int.TryParse branch would help diagnose bad CI config.
4 Minor MacOSNativeElementHostingExtension.cs:45 NativeUno.uno_native_dispose(handle) is called even when NativeHandle was never assigned (handle == 0). The ObjC null guard at the top of uno_native_dispose handles it safely; an if (handle != 0) short-circuit before the P/Invoke would clarify intent.

What is correct

  • UNONative.m — null guard on uno_native_dispose only, which is correct: all other entry points are gated by TryGetLiveElement on the C# side. Removal from both elements and transients is necessary and the comment explains why.
  • DisposeNativePeer ordering — handle captured before Disposed = true / NativeHandle = 0; state transition is correct on the UI thread; native call uses the captured non-zero pointer.
  • Timeout cancellation — using var timeoutCts + timeoutCts.Cancel() before inspecting WhenAny result correctly prevents lingering per-test timers. Cancelled Task.Delay is TaskStatus.Canceled, not faulted — no unobserved-exception risk.
  • TryGetLiveElement guards — consistently gates all five native entry points through a single guard, eliminating the per-method content is MacOSNativeElement cast duplication.

Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24112/wasm-skia-net9/index.html

Copy link
Copy Markdown
Contributor

The build 229240 found UI Test snapshots differences: skia-linux-screenshots: 73, skia-windows-screenshots: 178

Details
  • skia-linux-screenshots: 73 changed over 2366

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • ExpanderColorValidationPage.png-dark
    • ExpanderColorValidationPage.png
    • Attributed_text_FontSize_Changing.png
    • CalendarView_Theming.png-dark
    • DisplayInformation.png-dark
    • DisplayInformation.png
    • ImageBrush_Stretch.png
    • Buttons.png
    • ClipboardTests.png-dark
    • Examples.png
    • ClipboardTests.png
    • ImageIconPage.png-dark
    • ImageIconPage.png
    • DynamicFont.png
    • ElementLevelTheme.png-dark
    • ElementLevelTheme.png
    • ContentControl_Inheritance.png
    • Gamepad_CurrentReading.png-dark
  • skia-windows-screenshots: 178 changed over 2368

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • ButtonClippingTestsControl.png
    • Buttons.png-dark
    • DoubleAnimation_VisualStates.png-dark
    • Grid_Two_bottom_row_Auto__middle_col_auto.png-dark
    • BitmapImage_vs_SvgImageSource.png-dark
    • BitmapImage_vs_SvgImageSource.png
    • ChatBox.png-dark
    • ChatBox.png
    • DoubleTappedEvent.png-dark
    • ImageSourceUrlMsAppDataScheme.png-dark
    • ImageSourceUrlMsAppDataScheme.png
    • Image_Stretch_Algmnt_Inf_Horizontal.png-dark
    • Image_Stretch_Algmnt_Inf_Horizontal.png
    • Battery.png-dark
    • DataTransferManager.png-dark
    • DataTransferManager.png
    • ExpanderColorValidationPage.png-dark
    • Examples.png
    • Haptics.VibrationDevice.png-dark
    • Haptics.VibrationDevice.png

github-actions Bot commented Aug 22, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Claude finished @Xiaoy312's task in 3m 47s —— View job


Code Review

  • Read changed files (new sync includes MacOSNativeWebView.cs)
  • Check if prior outstanding findings were addressed
  • Review MacOSNativeWebView.cs (new in this sync)
  • Investigate Xiaotian Gu's concern about macOS runtime test timeouts
  • Post inline comments
  • Write summary

Overall verdict: ⚠️ Fix before merge

This review covers the new commit fix(macos): Drop the stale WebView2 handle copy (new file MacOSNativeWebView.cs) plus the two commits carried from prior passes. The stale-handle fix is correct and clean. 4 findings from prior passes remain unaddressed; 1 new finding and 1 follow-up concern added.

Outstanding findings from prior passes (all still open)

# Sev File Issue
1 Medium MacOSNativeElementHostingExtension.cs:82 LogLevel.Error fires on every layout/arrange/measure call after any reparent. PR calls this path a "known design defect" and a "logged no-op" — use LogLevel.Warning.
2 Medium MacOSNativeElementHostingExtension.cs:182 Size.Empty is {-∞, -∞}. When TryGetLiveElement rejects a disposed element, negative-infinity propagates into Layouter.MeasureCore and throws, turning the "logged no-op" into a managed layout exception. Fix: return new Size(0, 0);
3 Minor UnitTestsControl.cs:1364 When UNO_TEST_DEFAULT_TIMEOUT_SECONDS is set to a non-integer (e.g. "5m", a typo), the fallback is applied silently with no log entry — invisible misconfiguration on CI.
4 Minor MacOSNativeElementHostingExtension.cs:43 uno_native_dispose(handle) called even when NativeHandle was never assigned (handle == 0). ObjC null guard is safe; an if (handle != 0) short-circuit would clarify intent.

New findings (this pass)

# Sev File Issue
5 Minor MacOSNativeWebView.cs:81 LogLevel.Error in TryGetHandle — same issue as finding #1. Dispose fires on Unloaded which fires on reparent; every subsequent WebView operation logs an error. Should be LogLevel.Warning. Posted inline.
6 Note MacOSNativeWebView.cs:200 InvokeScriptAsync awaits inside the using (token.Register(...)) block (correct — cancellation stays wired), but ExecuteScriptAsync awaits outside (cancellation unregistered before the result arrives). The inconsistency is pre-existing, not introduced here, but worth aligning as a follow-up. Posted inline.

Xiaotian Gu's concern — synchronous tests not covered by the timeout

The new 5-minute timeout in UnitTestsControl.cs only applies to Task-returning test methods (line 1017: if (test.Method.ReturnType == typeof(Task))). Synchronous void tests that deadlock or spin are still unguarded and can hold the macOS CI job for the full 6 hours observed. If the hung test on macOS is synchronous, this PR's timeout won't catch it. A follow-up should either add a thread-abort/process-kill safety valve for sync tests, or require all new tests on the macOS leg to be async.

What is correct in the new commit

  • TryGetHandle read path — reading NativeHandle directly (which is zeroed by DisposeNativePeer) instead of a stale local copy is the correct fix for the dangling-handle defect.
  • _webViews registration keyed on _registeredHandle — decoupling the map key from the live NativeHandle correctly handles the race where the peer is already disposed when OnUnloaded fires.
  • GCHandle lifetime in ExecuteScriptAsync — the handle is freed in the native callback; a cancelled task doesn't leak because the native side still fires ExecuteScriptCallback.

- Fix TaskCompletionSource<string> to TaskCompletionSource<string?> in
  ExecuteScriptAsync so it matches the callback cast
- Guard content?.GetType() in TryGetLiveElement to avoid NullReferenceException
  when content is null
- Return new Size(0, 0) from MeasureNativeElement for disposed peers instead
  of Size.Empty (-∞, -∞) which caused layout exceptions

Co-authored-by: MartinZikmund <1075116+MartinZikmund@users.noreply.github.com>
auto-merge was automatically disabled August 22, 2026 19:39

Head branch was pushed to by a user without write access

Copilot AI commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

@copilot address pr comments

Addressed in the latest commit:

  1. MacOSNativeWebView.cs:130 — new TaskCompletionSource<string>() changed to new TaskCompletionSource<string?>() to match the gch.Target as TaskCompletionSource<string?> cast in ExecuteScriptCallback.
  2. MacOSNativeElementHostingExtension.cs:69-78 — content.GetType() in the log message guarded as content?.GetType().FullName ?? "null" to prevent NullReferenceException when content is null.
  3. MacOSNativeElementHostingExtension.cs:182 — Size.Empty (-∞,-∞) replaced with new Size(0, 0) so a disposed-peer measure returns a finite zero size rather than causing a layout exception.

CLAassistant commented Aug 22, 2026
edited
Loading

Copy link
Copy Markdown


Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
2 out of 3 committers have signed the CLA.

✅ MartinZikmund
✅ Xiaoy312
❌ Copilot
You have signed the CLA already but the status is still pending? Let us recheck it.

`TryGetLiveElement` and `TryGetHandle` are reached on every arrange, measure,
attach and detach of a reparented element, so `Error` put a per-layout-pass stream
into the channel reserved for genuine faults. The disposed peer is a known
degraded path, not an unexpected state.

Also from review:

- `DisposeNativePeer` skips the P/Invoke when the handle is already zero, which
  happens when the peer was never created.
- `ExecuteScriptAsync` awaits inside the `token.Register` scope, matching
  `InvokeScriptAsync`. It previously disposed the registration before awaiting, so
  a cancel arriving after the P/Invoke never reached the pending task.
- Records why the disposed-peer measure fallback cannot be `Size.Empty`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEzBHbVj75RX9ENGARb6sL

github-actions Bot commented Aug 22, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Claude finished @MartinZikmund's task in 2m 33s —— View job


Code Review

  • Load tools
  • Read changed files
  • Check which prior findings are addressed
  • Review MacOSNativeElementHostingExtension.cs
  • Review MacOSNativeWebView.cs
  • Review UNONative.m
  • Post inline comments
  • Write summary

Overall verdict: ✅ Approve

All six outstanding findings from prior review passes are resolved in the two new commits (d6462d43 by Copilot and f81eec0b by @MartinZikmund). No new issues found. No inline comments to post.

Prior findings — all addressed

# Finding Addressed in
1 LogLevel.Error → LogLevel.Warning in TryGetLiveElement f81eec0b
2 LogLevel.Error → LogLevel.Warning in TryGetHandle f81eec0b
3 uno_native_dispose(0) short-circuit — if (handle != 0) guard f81eec0b
4 Size.Empty (-∞,-∞) → new Size(0, 0) in disposed-peer measure path d6462d43
5 TaskCompletionSource<string> type mismatch with callback cast d6462d43
6 content.GetType() potential NRE in TryGetLiveElement debug log d6462d43

Bonus fix (noted in f81eec0b): ExecuteScriptAsync now awaits inside the using (token.Register(...)) block, matching InvokeScriptAsync. The prior code disposed the CancellationTokenRegistration before the await completed, so cancellation arriving after uno_webview_execute_script dispatched could never reach the pending task. This is now correctly wired for the full async duration.

What is correct across all three files

  • UNONative.m — null guard on uno_native_dispose only; removal from both elements and transients prevents resurrection through either strong-reference set. The comment correctly explains why both are necessary.
  • DisposeNativePeer ordering — handle captured before Disposed = true / NativeHandle = 0; state transition is correct on the UI thread; native call uses the captured non-zero pointer and is skipped when the handle was never assigned.
  • TryGetLiveElement guards — consistently gates all five native entry points through a single guard. The null-safe debug log for non-MacOSNativeElement content (content?.GetType().FullName ?? "null") is correct; the inner warn branch is unreachable with a null content since is not MacOSNativeElement would have returned first.
  • TryGetHandle / _registeredHandle pattern — deleting the _webview shadow field and routing all 15 P/Invokes through TryGetHandle closes the dangling-handle class. Keying _webViews on _registeredHandle correctly handles the unload-ordering race where the peer may already be disposed when OnUnloaded fires.
  • GCHandle lifetime — ExecuteScriptCallback always calls gch.Free() after TrySetResult/TrySetException/TrySetCanceled, so no handle leak when cancellation fires before the callback.
  • TaskCompletionSource<string?> — ExecuteScriptAsync and its static callback (gch.Target as TaskCompletionSource<string?>) now share the same generic type parameter; the cast is no longer silently broken.

Copy link
Copy Markdown
Member Author

🤖 Addressed PR comments up to this point

21 review threads (12 distinct points — the review bot re-posted four of them across three runs). Code in d6462d4 (Copilot agent) and f81eec0.

Fixed

  • MeasureNativeElement returned Size.Empty = (-∞, -∞) for a disposed peer. ContentPresenter clamps only +∞/NaN and Layouter.cs:111 tests double.IsInfinity, so the "logged no-op" was really a layout exception. Now new Size(0, 0). — @morning4coffe-dev
  • Disposed-peer guards log at Warning, not Error: both are reached on every arrange/measure of a reparented element.
  • TryGetLiveElement no longer dereferences a null content while logging its type.
  • DisposeNativePeer skips the P/Invoke on a zero handle.
  • ExecuteScriptAsync awaits inside the token.Register scope, matching InvokeScriptAsync — a cancel after the P/Invoke previously never reached the pending task.

Pushed back

  • The TaskCompletionSource<string> / TaskCompletionSource<string?> cast does not always fail: nullable annotations are erased, so both are the same runtime type. Types aligned anyway for clarity.

Moved out of this PR

Filed for follow-up — from @Xiaoy312's review notes

@Xiaoy312's thread on the 6-hour macOS run is answered but left open — the retry-convergence question is his and @MartinZikmund's call.

@Xiaoy312 your WebView2 commit stays in this PR with authorship intact; it is the direct cause of the second crash signature, so splitting it out would have separated a fix from its evidence.

Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24112/wasm-skia-net9/index.html

Copy link
Copy Markdown
Contributor

The build 229613 found UI Test snapshots differences: skia-linux-screenshots: 73, skia-windows-screenshots: 185

Details
  • skia-linux-screenshots: 73 changed over 2366

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Attributed_text_FontSize_Changing.png
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • DropDownButtonPage.png-dark
    • Focus_FocusVisual_Properties.png-dark
    • ClipboardTests.png-dark
    • ClipboardTests.png
    • Buttons.png
    • DisplayInformation.png-dark
    • DisplayInformation.png
    • ImageBrush_Stretch.png
    • ImageIconPage.png-dark
    • ImageIconPage.png
    • ElementLevelTheme.png-dark
    • ElementLevelTheme.png
    • DynamicFont.png
    • Image_Margin_Large.png
    • CalendarView_Theming.png-dark
    • ContentControl_Inheritance.png
    • ContextRequested.png-dark
  • skia-windows-screenshots: 185 changed over 2368

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Buttons.png-dark
    • BitmapImage_vs_SvgImageSource.png
    • Basics.png-dark
    • Button_Enabled_Control_Disabled.png-dark
    • Button_Enabled_Control_Disabled.png
    • CalendarView_Theming.png-dark
    • CalendarView_Theming.png
    • ClipboardTests.png-dark
    • ContentPresenter_NativeEmbedding_Android_FillType.png
    • Contacts_Pick.png-dark
    • Contacts_Pick.png
    • ExpanderColorValidationPage.png-dark
    • DynamicBrushes_On_Shapes.png
    • DisplayInformation.png-dark
    • Focus_FocusState.png-dark
    • Dopes.png-dark
    • Focus_FocusVisual_Properties.png-dark
    • Focus_FocusState.png
    • Focus_FocusVisual_Properties.png
    • Examples.png

Copy link
Copy Markdown
Contributor

⚠️⚠️ The build 229613 has failed on Uno.UI - CI.

`MacOSNativeElement` destroyed its NSView from `Unloaded`, but `Unloaded` also
fires on a reparent and the framework re-enters the very same element through
`AttachNativeElement`. Every operation on the way back in was then refused, so a
`WebView2` removed from and re-added to the tree came back dead — which is why
`When_WebMessageReceived_After_RemoveAdd` failed the macOS runtime-test job. The
X11 and Win32 hosting extensions never destroyed their peer on unload either.

Root-cause fix: the peer's lifetime follows the managed wrapper. The finalizer
releases it, dispatched to the main thread since AppKit is main-thread only, and
`uno_native_attach` drops the strong reference `uno_native_detach` took so
`transients` holds only genuinely detached views. The disposed-handle guards stay
as hardening — they can no longer be reached through a reparent.

`addScriptMessageHandler:name:` raises on a name that is already registered, and
the WKWebView now survives the round trip, so registration removes the previous
handler first and `OnUnloaded` unregisters symmetrically with `OnLoaded`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014LKUHFiW2J8nNFy7FmuCsd

github-actions Bot commented Aug 23, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24112/wasm-skia-net9/index.html

Copy link
Copy Markdown
Contributor

The build 229653 found UI Test snapshots differences: skia-linux-screenshots: 73, skia-windows-screenshots: 170

Details
  • skia-linux-screenshots: 73 changed over 2366

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • DisplayInformation.png-dark
    • DisplayInformation.png
    • ContextRequested.png-dark
    • ContentControl_Inheritance.png
    • Gamepad_CurrentReading.png-dark
    • Gamepad_CurrentReading.png
    • Gamepad_Enumeration.png-dark
    • Examples.png
    • ImageBrushInList.png-dark
    • ImageBrushInList.png
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • ImageBrush_Stretch.png
    • Attributed_text_FontSize_Changing.png
    • DropDownButtonPage.png-dark
    • ExpanderColorValidationPage.png-dark
    • ExpanderColorValidationPage.png
    • CalendarView_Theming.png-dark
    • ClipboardTests.png-dark
    • ClipboardTests.png
  • skia-windows-screenshots: 170 changed over 2368

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Buttons.png
    • Focus_FocusState.png-dark
    • Focus_FocusState.png
    • ButtonClippingTestsControl.png-dark
    • CalendarView_Theming.png-dark
    • CalendarView_Theming.png
    • Gamepad_CurrentReading.png-dark
    • Gamepad_Enumeration.png-dark
    • Gamepad_Enumeration.png
    • BitmapImage_vs_SvgImageSource.png-dark
    • BitmapImage_vs_SvgImageSource.png
    • ClipboardTests.png-dark
    • ClipboardTests.png
    • ElementLevelTheme.png-dark
    • ButtonClippingTestsControl.png
    • Buttons.png-dark
    • ImageBrushInList.png-dark
    • ImageBrushInList.png
    • ContentPresenter_Template.png-dark
    • ContentPresenter_Template.png

Copy link
Copy Markdown
Contributor

⚠️⚠️ The build 229653 has failed on Uno.UI - CI.

`uno_webview_create`, `uno_mediaplayer_create_view` and `uno_native_create_sample`
all end in `objc_autoreleaseReturnValue` (confirmed in the shipped dylib), so the
handle they hand back is owned by nothing but the current autorelease pool. The
native side only took a strong reference at `uno_native_attach`, which adds the
view to `elements`. Any element that is never attached, or whose attach lands in a
later run-loop turn than its creation, is therefore already deallocated — and both
`uno_native_attach` and `uno_native_dispose` begin with an ARC `objc_retain` of
their parameter, so the next call takes the process down at `+0x1f`.

That is the SIGSEGV the macOS runtime-test job keeps hitting: three CI core dumps
from this branch all fault at the same image offset, which symbolizes to
`uno_native_dispose` retaining a freed NSView.

`uno_native_track` takes the strong reference at creation instead. The peer is now
owned continuously — `transients` from creation, `elements` while attached, back to
`transients` on detach — until `uno_native_dispose` drops both and deallocates it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014LKUHFiW2J8nNFy7FmuCsd

github-actions Bot commented Aug 23, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24112/wasm-skia-net9/index.html

Copy link
Copy Markdown
Contributor

The build 229659 found UI Test snapshots differences: skia-linux-screenshots: 73, skia-windows-screenshots: 191

Details
  • skia-linux-screenshots: 73 changed over 2366

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • DropDownButtonPage.png-dark
    • Focus_FocusVisual_Properties.png-dark
    • Attributed_text_FontSize_Changing.png
    • Buttons.png
    • ContentControl_Inheritance.png
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • CalendarView_Theming.png-dark
    • ContextRequested.png-dark
    • Examples.png
    • DynamicFont.png
    • ExpanderColorValidationPage.png-dark
    • ExpanderColorValidationPage.png
    • Gamepad_CurrentReading.png-dark
    • Gamepad_CurrentReading.png
    • Gamepad_Enumeration.png-dark
    • Image_Margin_Large.png
    • DisplayInformation.png-dark
    • DisplayInformation.png
    • ImageBrushInList.png-dark
  • skia-windows-screenshots: 191 changed over 2368

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • BitmapImage_vs_SvgImageSource.png
    • Buttons.png-dark
    • DataTemplate_Update_Sample.png-dark
    • DataTemplate_Update_Sample.png
    • Elevation.png-dark
    • Elevation.png
    • ElevationView_Clipping.png-dark
    • ElevationView_Clipping.png
    • ExpanderColorValidationPage.png-dark
    • Focus_FocusState.png-dark
    • Focus_FocusState.png
    • GridViewVariableItemHeight.png-dark
    • Focus_FocusVisual_Properties.png-dark
    • Focus_FocusVisual_Properties.png
    • Image_With_RotateTransform.png-dark
    • Attributed_text_FontSize_Changing.png
    • BitmapImage_vs_SvgImageSource.png-dark
    • Basics Pivot Test.png
    • ChatBox.png-dark
    • ChatBox.png

`drawInMTKView:` returned without calling managed code when `currentDrawable` was
nil. The view runs with `enableSetNeedsDisplay`, so AppKit had already cleared
`needsDisplay` to make that call, and the managed side latches its own request:
`CompositionTarget.RequestNewFrame` sets `RenderRequested` and only clears it from
`OnNativePlatformFrameRequested`, which the dropped frame never reaches. Every
later `RequestNewFrame` then coalesced into an invalidation that had already been
consumed, so a single nil drawable stopped the window rendering permanently.

Anything awaiting a frame after that waits forever — `UITestHelper.WaitForRender`
has no timeout of its own — which is how one macOS test takes the whole 60-minute
job down with it and publishes no results.

The nil case now re-arms `needsDisplay` on a later main-queue turn, so the frame
request survives. The software path never had the defect: it calls the managed
callback before its own early return.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014LKUHFiW2J8nNFy7FmuCsd

github-actions Bot commented Aug 23, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

Copy link
Copy Markdown
Contributor

🤖 Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-24112/wasm-skia-net9/index.html

Copy link
Copy Markdown
Contributor

The build 229660 found UI Test snapshots differences: skia-linux-screenshots: 73, skia-windows-screenshots: 169

Details
  • skia-linux-screenshots: 73 changed over 2366

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • DisplayInformation.png-dark
    • DisplayInformation.png
    • Buttons.png
    • Focus_FocusVisual_Properties.png-dark
    • Image_Margin_Large.png
    • Examples.png
    • Attributed_text_FontSize_Changing.png
    • ContextRequested.png-dark
    • DropDownButtonPage.png-dark
    • ImageBrush_Stretch.png
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • ImageIconPage.png-dark
    • ImageIconPage.png
    • ElementLevelTheme.png-dark
    • ElementLevelTheme.png
    • ClipboardTests.png-dark
    • ClipboardTests.png
    • Gamepad_CurrentReading.png-dark
    • Gamepad_CurrentReading.png
  • skia-windows-screenshots: 169 changed over 2368

    🚨🚨 Comparison Details (first 20) 🚨🚨
    • Attributed_text_FontSize_Changing.png-dark
    • ButtonClippingTestsControl.png-dark
    • ButtonClippingTestsControl.png
    • DropDownButtonPage.png-dark
    • DropDownButtonPage.png
    • Focus_FocusVisual_Properties.png-dark
    • Focus_FocusVisual_Properties.png
    • DoubleAnimation_VisualStates.png-dark
    • ImageSourceUrlMsAppDataScheme.png-dark
    • ImageSourceUrlMsAppDataScheme.png
    • Image_Stretch_Algmnt_Inf_Horizontal.png-dark
    • Image_Stretch_Algmnt_Inf_Horizontal.png
    • ClipboardTests.png-dark
    • DatePicker_VisualStates.png-dark
    • DynamicFont.png-dark
    • DynamicFont.png
    • Gamepad_CurrentReading.png-dark
    • Gamepad_Enumeration.png-dark
    • ImageBrushLocalAsset.png-dark
    • BitmapImage_vs_SvgImageSource.png

MartinZikmund merged commit 2b3cef7 into feature/breakingchanges Aug 23, 2026
46 of 47 checks passed
MartinZikmund deleted the dev/mazi/flakiness branch August 23, 2026 21:08
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/automation Categorizes an issue or PR as relevant to project automation platform/macos 🍏 Categorizes an issue or PR as relevant to the macOS platform

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants


Back | FazBrowse Home | New Git URL