Skip to content

chore(automation): Sync master → feature/wasm-mt - #24015

Draft
github-actions[bot] wants to merge 756 commits into
feature/wasm-mtfrom
automation/master-sync/feature/wasm-mt
Draft

chore(automation): Sync master → feature/wasm-mt#24015
github-actions[bot] wants to merge 756 commits into
feature/wasm-mtfrom
automation/master-sync/feature/wasm-mt

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Automated sync — merges the latest master into feature/wasm-mt.

  • Incoming commits from master: 742
  • Range: e3fa152eb9..bfecdcb7e5
  • Merge method: merge commit (preserves ancestry so future syncs stay minimal)

Warning

Merge conflicts — opened as a draft so it cannot auto-merge. Resolve, then mark Ready for review.

Conflicted files:

src/Uno.UI/Generated/3.0.0.0/Microsoft.Web.WebView2.Core/CoreWebView2.cs
src/Uno.UI/Generated/3.0.0.0/Microsoft.Web.WebView2.Core/CoreWebView2Environment.cs
src/Uno.UI/Generated/3.0.0.0/Microsoft.Web.WebView2.Core/CoreWebView2ProcessInfo.cs
src/Uno.UI/Generated/3.0.0.0/Microsoft.Web.WebView2.Core/CoreWebView2Profile.cs

Resolve locally (the merge is already committed with the conflict markers):

git fetch origin
git checkout automation/master-sync/feature/wasm-mt
# Open the conflicted files, resolve all <<<<<<< / ======= / >>>>>>> markers, then:
git add -u
git commit -m 'fix: resolve merge conflicts with master'
git push

Maintained automatically; updates in place. Generated by this run.

ajpinedam and others added 30 commits July 29, 2026 01:16
ApiExtensibility.Register used Dictionary.Add, which throws ArgumentException on a
duplicate contract type. When multiple applications run in a single process and
share this registry — for example a host and a secondary application loaded into a
collectible AssemblyLoadContext that shares Uno.Foundation with the host — each
application's generated startup registers the same framework providers (via
ApiExtensionAttribute). The second application's InitializeComponent then threw a
fatal duplicate-key ArgumentException, terminating the process.

Skip re-registration when the contract type is already registered (first
registration wins), making Register idempotent and safe for shared registries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…idempotency tests

- Fix the builder null-check in both Register overloads to report nameof(builder) (was nameof(type)).
- In Register<TOwner>, check _registrations.ContainsKey before allocating the wrapper lambda so a duplicate (idempotent) registration is truly cheap.
- Add Given_ApiExtensibility: duplicate Register (both overloads) is a no-op and the first registration wins — locks in the new idempotent semantics.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Release process-lifetime static caches that pin a previewed app's collectible
AssemblyLoadContext after unload, for a downstream host that loads previewed
apps into their own collectible AssemblyLoadContexts. On WASM
AssemblyLoadContext.Unloading is never raised, so these are swept from the
existing cleanup hook (Application.CleanupNonDefaultAlcCaches) or via an
ALC-scoped removal on a reachable teardown path.

- ResourceLoader: ClearNonDefaultAlcAssemblies drops app lookup assemblies
- UIElementNativeRegistrar._classNames (WASM): drop collectible Type keys
- AppWindow/ApplicationView/CoreDragDropManager: DestroyForWindowId on close
- CompositionTarget.Rendering (WASM): drop non-default-ALC handlers + reuse
  a per-frame snapshot buffer instead of allocating a List each frame
- Hot-reload client history: release terminal op Type[] (keep curated
  strings) + cap history to a ~100 ring buffer
- PagePool: single lazy instance (no per-Frame orphaned pools + eternal
  scavenger); scavenge only when pooling enabled; sweep collectible page types
- HtmlElementHelper._cache (WASM) + Style.UseUWPDefaultStylesOverride: sweep
  collectible Type keys

Tests (red/green): Given_ResourceLoader_Alc (red proven by neutering),
Given_WindowId_Maps_Alc, Given_ResidualTypeStatics_Alc,
Given_HotReloadClientOperation_Alc. Spec: specs/048-wasm-alc-pin-sweeps.

Closes #23706

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… spec

- List the four red/green tests and which built/passed locally
- Note that browserwasm/desktop workloads are absent locally (NETSDK1139),
  so WASM-only sweeps + the Skia/WASM runtime test are validated on CI

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- CompositionTarget frame dispatch: extract the reused snapshot-buffer
  logic into a platform-neutral CompositionTargetFrameDispatcher and
  clear the whole buffer in a finally, so neither a throwing handler nor
  a shrinking handler list can leave stale delegate references rooted in
  the static buffer (which would pin collectible-ALC objects).
- PagePool: reconcile the Instance doc (eager shared instance, lazy
  scavenger) and stop the scavenger from rescheduling once pooling is
  disabled, honoring the "only runs while pooling is enabled" contract.
- Window ALC close: destroy each per-WindowId registry independently so
  a single throwing DestroyForWindowId no longer skips the siblings and
  leaves the ALC pinned.
- Fix a sentence fragment in the Given_WindowId_Maps_Alc class summary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add Given_CompositionTargetFrameDispatcher asserting the reused snapshot
buffer never roots a handler past its dispatch: after a normal frame, on
a handler that throws, and when the handler list shrinks between frames.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- CompositionTargetFrameDispatcher: the reused buffer holds null in
  cleared slots, so its element type is now EventHandler<object>?[]
  (and the Snapshot seam IReadOnlyList<EventHandler<object>?>),
  correcting the nullability contract; the just-populated slots are
  invoked with an explicit null-forgiving operator.
- PagePool: reset _scavengerStarted in the scavenger catch block so a
  transient failure no longer permanently disables eviction — the next
  EnqueuePage can restart the loop via EnsureScavengerStarted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ClearNonDefaultAlcAssemblies cleared every loader's dictionaries and then
rebuilt from the remaining default-ALC assemblies, but only dropped the
parsed-resource markers of the removed assemblies. ProcessResourceFile
skips any (assembly, fileName) still present in _parsedResources, so the
remaining default-ALC files were skipped and the loaders stayed empty
until the next full reload.

Clear _parsedResources wholesale before re-processing so the remaining
assemblies are re-parsed. Add a red/green regression guard asserting a
default-ALC resource still resolves after the sweep.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The new Tests.AssemblyLoadContext namespace shadows the BCL type
System.Runtime.Loader.AssemblyLoadContext for sibling tests under
Uno.UI.RuntimeTests.Tests that reference it unqualified, producing CS0118
(and cascading CS0234/CS1503) in Given_HotReloadClientOperation_Alc.
Fully-qualify with global:: so resolution bypasses the sibling namespace.
…tem shadow

In the WinUI flavor, the Microsoft.UI.System namespace shadows the global
System namespace, so the unqualified System.Runtime.Loader.AssemblyLoadContext
in HtmlElementHelper.ClearNonDefaultAlcEntries resolved to
Microsoft.UI.System.Runtime and failed the managed-binaries build with CS0234.
Prefix with global:: so it always binds to the BCL type.
- Remove unused System.Linq / System.Text usings from PagePool.
- Mark Frame._pool static field readonly (assigned once to the shared singleton).
- Fix spec test-name references: Given_HotReloadClientOperation_Alc; point
  CompositionTarget row at the actual unit + runtime tests; mark the
  UIElementNativeRegistrar / PagePool WASM caches as pin-guard-covered with
  dedicated unit tests still TBD.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… is torn down

- ElementUpdateAgent.Dispose/HotReloadAgent.Dispose now also clear their
  Type-keyed handler map and cached delta/assembly references in addition
  to detaching the process-wide AppDomain.AssemblyLoad subscription
- ClientHotReloadProcessor arms a best-effort Unloading teardown when its
  copy is owned by a collectible AssemblyLoadContext, disposing the
  processor instance and the shared element-update agent and clearing the
  per-context statics
- Note: AssemblyLoadContext.Unloading is not raised on browser-wasm
  (dotnet/runtime#34153 family; collectible unload unimplemented per
  dotnet/runtime#34072), so hosts needing deterministic release must still
  dispose explicitly — the Dispose-side map clearing makes that effective
- Add HotReloadAgentDisposeTests asserting the load-bearing teardown
  behavior for issue #23704: after Dispose, ElementUpdateAgent clears its
  Type-keyed handler map and HotReloadAgent clears _deltas /
  _appliedAssemblies, so an unloaded collectible context is no longer
  pinned by the client agents.
- Red/green verified: both tests fail against the pre-fix Dispose (which
  only detached the AssemblyLoad subscription) and pass with the fix.
- Add spec 048 documenting the change and the browser-wasm Unloading
  caveat (dotnet/runtime#34072).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ardown

- HotReloadAgent.Dispose now nulls the cached _handlerActions. Its actions are
  delegates built from MethodInfo on handler Types discovered by scanning the
  owning context's assemblies, so leaving the cache populated pins a collectible
  context. Extends HotReloadAgentDisposeTests with a red/green guard.
- TearDownForAlcUnload detaches the ShowDiagnosticsOnFirstActivation handler from
  CurrentWindow.Activated before nulling CurrentWindow. The handler is a static
  method on the collectible-context processor copy; a host Window that outlives
  the context would otherwise keep it (and the context) alive. Guarded HAS_UNO_WINUI
  to match the attach site.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…spose

- extract ReleasePerContextStatics() from TearDownForAlcUnload so both the
  Unloading hook and an explicit Dispose share one idempotent teardown
- ClientHotReloadProcessor.Dispose() now also releases the static element
  agent (and clears _instance) when the owning context is collectible —
  the load-bearing path on browser-wasm where Unloading is never raised
- keep the flow non-recursive: the unload hook detaches _instance before
  disposing it, and Dispose never calls TearDownForAlcUnload
- default-context Dispose behavior unchanged (shared agent never torn down)
- tests: collectible-copy Dispose releases statics (red/green proven),
  default-context guard, AssemblyLoad unsubscription, non-recursive unload

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- LoadCollectibleProcessorCopy now returns its AssemblyLoadContext so both
  callers can Unload() it in a finally after the teardown assertions,
  matching the sibling cross-ALC tests' try/finally idiom
- the context must outlive the asserts (the tests verify what pins it), so
  it is unloaded only after, not disposed with a using
- correct the spec validation section: HotReloadAgentDisposeTests now has
  seven TestMethods (was described as 2/2); document each and the honest
  red/green (five go red when the two agent Dispose bodies are neutered)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
IsSubscribedToAssemblyLoad read a single hard-coded private CoreCLR field
(AssemblyLoadContext.AssemblyLoad), so a runtime field name/layout change
would fail the dispose tests even when the product behaviour is correct.

Probe the known candidate backing-field names, verify the resolved field
is a delegate, and otherwise throw one clear diagnostic (never an NRE)
pointing at the layout change. The assertion still observes real
detachment of the agent's subscription, so the tests stay meaningful.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
In a collectible context Dispose() released the shared per-context
statics (the _elementAgent) unconditionally. Disposing a non-active
processor — e.g. a second RemoteControlClient in the same collectible
context — would therefore tear the shared element agent down from under
the still-live active processor.

Gate ReleasePerContextStatics() so only the active _instance (or a
context whose metadata updater never initialized an instance, where
_instance is null and nothing live depends on the statics) releases
them. Add a red/green regression guard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mbed

Uno.UI.Toolkit.Windows links a subset of the ClientHotReloadProcessor
partial (Common/Status/MetadataUpdate) but not the base file that declares
: IDisposable and Dispose(). The collectible-ALC teardown in Common.cs
called instance?.Dispose() directly, which fails to compile in that embed
(CS1061). Cast through IDisposable so the call binds in the full assembly
and compiles-to-no-op in the embed; the teardown only runs for collectible
contexts, which the embed never has.
The Skia-only override made the TextBox API surface diverge from the
Reference assembly, failing the ReferenceImplComparer package check.
The override now lives in the shared TextBox partial and delegates to a
Skia-implemented partial method, keeping the surface identical across
targets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…device

fix(x11): Stable pointer ids under a WM + DisplayInformation init race
Group the native-resolver flag with _addresses at the top of the class
instead of declaring it mid-file next to ResolveNative.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…warerenderer

fix(skia): Restore Compositor.IsSoftwareRenderer
…selfteardown

fix(hotreload): release collectible-ALC state when the owning context is torn down
Five touch flyout tests failed about half the time on macOS Desktop Skia
only. Build 224362 took eight macOS attempts to go green, roughly half the
remaining set clearing per retry.

The test budget equalled the platform poll interval.
MacOSClipboardExtension.SetContent is fire-and-forget, so the pasteboard
write lands a dispatcher turn later; CanPasteClipboardContent then only
refreshes from Clipboard.ContentChanged, which macOS raises from a 1s
NSTimer poll of NSPasteboard.changeCount (UNOClipboard.m); and the tests
waited on that property with WaitFor's default 1000ms. Windows and Linux do
not poll, so no other shard ever flaked.

Seed the clipboard before focusing instead: focusing runs a live
Clipboard.GetContent() via UpdateCanPasteClipboardContent, so the poll
leaves the critical path entirely and the property can be asserted rather
than waited on. The pre-existing read-only paste test already used this
seed-then-focus order.

SetClipboardText clears first and waits for the OS clipboard to go empty
then non-empty, so stale text from a prior test cannot satisfy it. A late
poll tick mid-gesture is harmless: OnClipboardContentChanged only does a
live-read property refresh, with no UpdateButtons or flyout interaction.

Verified 11/11 on Skia Desktop Windows. Windows has no clipboard poll, so
that proves no regression, not that the macOS flake is gone - the tell is
the macOS stage going green on attempt 1 rather than after 8.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
When_RightClick_Flyout_Copy_Closes_Flyout failed on the iOS Skia shard:
SelectedText was empty after invoking Copy, so "the selection should
survive Copy" tripped. It reproduced when retried in isolation.

This PR did not introduce that. HideAfterPrimaryBarInvoke only fires when
IsButtonInPrimaryCommands(button) is true, and the test itself asserts
Cut/Copy/Paste never reach PrimaryCommands on a mouse-opened flyout. The
same branch previously guarded an UpdateButtons() call, so for a mouse the
Copy path is unchanged. The collapse is pre-existing Skia-iOS behavior that
a new test merely exposed - ForceFocusLoss (which the flyout close does
call) and the iOS EndImeSession were both inspected and neither touches the
selection, so the mechanism is still unnamed and wants its own repro.

Both right-click tests inject a mouse yet were only excluded on SkiaWasm,
so they ran on Skia-iOS and Skia-Android where a mouse is not the real
input device and the default touch selection convention is mobile. Gate
them the way their touch counterpart already is - Desktop for dev plus real
Android. When_RightClick_Over_Selection_Flyout_Includes_Copy is green today
(it only checks command availability, never selection survival) and is
included for consistency.

Verified 3/3 on Skia Desktop Windows, confirming SkiaDesktop still covers
the Win32 host rather than silently skipping.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
In Top mode, selecting an item from the overflow flyout could permanently
collapse the overflow button even though not all items fit. The two-phase
exchange in SelectOverflowItem moved items into the primary list before
moving others out, transiently emptying the overflow list;
OnOverflowItemsSourceCollectionChanged reacted to that transient state by
collapsing the button, and nothing re-showed it afterwards.

Reorder the exchange (move out of primary first) so the overflow list only
becomes empty when it genuinely ends empty. Inherited from WinUI (open
upstream bug microsoft/microsoft-ui-xaml#6626) - native WinAppSDK fails the
same scenario, so the runtime test is Skia-only.

fixes #23903

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ajpinedam and others added 27 commits August 12, 2026 15:10
…PI surface

Replaces the generated NotImplemented stubs for CoreWebView2Environment,
CoreWebView2Profile and CoreWebView2ProcessInfo with hand-written partials, and
adds CoreWebView2.Environment, .Profile and .BrowserProcessId.

The members split across two seams because they have different lifetimes. The
statics answer "which browser is installed" and must work before any WebView
exists, so they resolve through an owner-less ApiExtensibility extension. The
instance members describe a live WebView, so they resolve through opt-in
capability interfaces on INativeWebView, alongside the existing
ISupportsVirtualHostMapping / ISupportsWebResourceRequested.

The capabilities are split three ways rather than bundled, because that split is
the portability documentation: data clearing has a real analogue on every head
(WKWebsiteDataStore, WebKitWebsiteDataManager, Android WebStorage), profile
metadata maps partially, and multi-process diagnostics is Chromium-only. A
second head implements one interface without touching Uno.UI.

The facades hold the owning CoreWebView2 rather than the native view, and
re-resolve on every access: _nativeWebView is assigned in OnOwnerApplyTemplate
and reassigned on every re-template, so a captured reference would go stale.
For the same reason the async path re-resolves after its await, since
EnsureNativeWebViewAsync stays completed across re-templating.

Behavior on every platform is unchanged: with nothing registered, each member
throws the same NotImplementedException as the deleted stubs, with the same
type/member strings so the telemetry key is preserved. ClearBrowsingDataAsync
deliberately throws rather than following the graceful in-memory fallback used
by SetVirtualHostNameToFolderMapping - a host mapping that quietly buffers is
harmless, a data-clearing call that quietly does nothing is a privacy defect.

GetAvailableBrowserVersionString(string, CoreWebView2EnvironmentOptions) stays
NotImplemented: CoreWebView2EnvironmentOptions is itself an unbacked stub whose
getters throw, so the options could not be honored, and ignoring them would
return a confidently wrong answer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… Win32

Backs the new API surface on the WebView2Aot backend: the statics through the
WebView2Loader.dll exports, and the instance members through ICoreWebView2Profile2
and ICoreWebView2Environment11.

The loader probe moves out of Win32NativeAotWebView's static constructor into
Win32WebView2Loader.Ensure(), because the statics must be able to load it with no
WebView ever created. It uses an explicit lock rather than a static constructor
or Lazy: a type initializer caches its failure, so the first DllNotFoundException
would be wrapped in a TypeInitializationException and replayed for the rest of
the process instead of reporting the real error on each attempt.

Win32CoreWebView2EnvironmentStaticsExtension deliberately holds no reference to
Win32NativeAotWebView, so a missing runtime stays a per-call failure rather than
becoming a startup crash for every Win32 app.

Failed HRESULTs from the two statics go through Marshal.ThrowExceptionForHR
rather than DirectN's ThrowOnError. The exception type is part of the contract
here, since these members are how an app detects a missing runtime: the CLR
mapping turns ERROR_FILE_NOT_FOUND into FileNotFoundException, which is what the
WinRT surface Uno mirrors produces. ThrowOnError raises a Win32Exception, which
would silently break a `catch (FileNotFoundException)` written against Windows.
(The WebView2 .NET wrapper used by WinForms/WPF instead raises its own
WebView2RuntimeNotFoundException, but that type is not part of the WinAppSDK
surface and has no Uno counterpart.)

The interfaces are hard-cast: the core WebView is already obtained as
ICoreWebView2_22, which is newer than every interface used here, so any runtime
able to create the WebView at all satisfies them and a version-fallback ladder
would be dead code.

ClearBrowsingDataAsync completes on a TaskCompletionSource created with
RunContinuationsAsynchronously, because the native handler runs while the
WebView2 message loop is being pumped and continuations after clearing routinely
call straight back into the WebView.

The registration is guarded to net10.0 and later: WebView2Aot is only referenced
from net10.0, and on net9.0 the WebView runs on the Microsoft.Web.WebView2
backend, where these members stay NotImplemented.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fixes: #24036

Context: #23966
Context: dotnet/macios#26428
Context: dotnet/cecil#504
Context: jbevain/cecil#982
Context: jbevain/cecil@0.11.4...0.11.6
Context: jbevain/cecil@0.10.1...0.11.6

In The Beginning™ was a simple idea: why don't we have an
iOS+Native AOT test stage?  Thus began #23966, which promptly fell
over, caught on fire, and sank into the swamp.

There are two issues with #23966:

 1. CI was unhappy; it errors out with

        …/Xamarin.Shared.targets(2073,3): error : No valid iOS code signing keys found in keychain. You need to request a codesigning certificate from https://developer.apple.com.

    Not sure what's happening there.  It doesn't happen locally…

 2. It couldn't build locally either!

The initial attempt to build locally would fail in `ilc`:

	# note: using changes from #23966
	% TFM=net11.0-ios \
	  NAOT=1 \
	  BUILD_SOURCESDIRECTORY=`pwd` \
	  BUILD_ARTIFACTSTAGINGDIRECTORY=`pwd`/artifacts \
	  sh build/test-scripts/skia-ios-uitest-build.sh
	…
	    …/unoplatform/uno/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets(487,3): warning Failed to resolve assembly `JetBrains.Annotations, Version=4242.42.42.42, Culture=neutral, PublicKeyToken=1010a0d8d6380325`: Failed to resolve assembly: 'JetBrains.Annotations, Version=4242.42.42.42, Culture=neutral, PublicKeyToken=1010a0d8d6380325'
	    EXEC : error Sequence point value is out of range.
	    $HOME/.nuget/packages/microsoft.dotnet.ilcompiler/11.0.0-preview.6.26359.118/build/Microsoft.NETCore.Native.targets(359,5): error MSB3073: The command ""$HOME/.nuget/packages/runtime.osx-arm64.microsoft.dotnet.ilcompiler/11.0.0-preview.6.26359.118/tools/ilc" @"obj/Release/net11.0-ios/ios-arm64/native/SamplesApp.ilc.rsp"" exited with code 1.

Thus began a fair bit of investigation, some of which is mentioned
in #24036 and dotnet/cecil#504.

What happened was a "failure cascade":

 1. The `<Csc/>` task produced a `.pdb` file.

 2. Uno's `<EmbeddedResourceInjectorTask_v0/>` task would use Cecil
    to process the assembly and `.pdb` file from (1).
    Uno was using, at most, Mono.Cecil 0.11.4, which had a bug around
    the encoding of "compressed" integers within `.pdb` files.

    (This is later fixed in jbevain/cecil#982, and released as part
    of Mono.Cecil 0.11.6.)

    The updated `.pdb` file would contain "Invalid compressed integer"
    values.

 3. Later, `illink` would run, which has it's own separate copy of
    Mono.Cecil -- from dotnet/cecil -- which would *also* update the
    `.pdb` files from (2).  When `illink` ran, any "Invalid compressed
    integer" values would be further corrupted.

 4. Later still, when `ilc` runs, it would process the `.pdb` files
    produced by (3), and at this point instead of "silently corrupting"
    data, it would error out entirely:

        Error: Sequence point value is out of range.
        System.BadImageFormatException: Sequence point value is out of range.
           at System.Reflection.Throw.SequencePointValueOutOfRange() in /_/src/runtime/src/libraries/System.Reflection.Metadata/src/System/Reflection/Throw.cs:line 239
           at System.Reflection.Metadata.SequencePointCollection.Enumerator.MoveNext() in /_/src/runtime/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/PortablePdb/SequencePointCollection.cs:line 86
           at Internal.TypeSystem.Ecma.PortablePdbSymbolReader.<GetSequencePointsForMethod>d__10.MoveNext() in /_/src/runtime/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs:line 147
           at ILCompiler.Logging.MessageOrigin..ctor(MethodIL, Int32) in /_/src/runtime/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/MessageOrigin.cs:line 65

(Failure cascades are fun!)

*Part* of the fix here is to update Uno to use Mono.Cecil 0.11.6,
which contains the fix for reading and writing "compressed" integers
in `.pdb` files.  That is done here.

Updating Cecil will *not* fix #23966, but is a partial prerequisite.
A full fix will require dotnet/cecil#504 to be merged and released,
(currently merged), `illink` updated to use dotnet/cecil#504, and
*then* there's dotnet/macios#26428, in which `clang++` crashes when
trying to link everything even if we get past the whole `.pdb` mess
(which reportedly is fixed in the not-yet-released .NET 11 RC1).

(Aside: the `.pdb` mess can be avoided by NOT USING `.pdb` FILES,
e.g. buil with `-p:DebugType=none`.  However, who wants to do that?)

…which still leaves the original "how do we get this building on CI"
question…

Baby steps!
…rofile

Given_WebView2 cannot host these: its class-level PlatformCondition excludes
SkiaWin32 and is evaluated in a separate IsIgnored call that is OR'd with the
method-level ones, so no method attribute can opt back in.

Given_CoreWebView2Environment needs no WebView in the tree, which is the point:
these members must answer before one exists. Given_CoreWebView2Profile loads a
real WebView2 and resets WindowContent in a finally.

Several assertions are deliberately weaker than they look:

- ClearBrowsingDataAsync has no cheap positive observable, so the honest ceiling
  is "completes without throwing, within a bounded time". The bound turns a
  native hang into one failed test rather than a stalled run. Note that the
  AllProfile case destroys state in the app's own WebView2 user-data folder and,
  unlike PreferredColorScheme, cannot be restored in a finally.
- GetProcessInfos asserts neither a count nor a set of kinds: renderer, GPU and
  utility processes appear asynchronously, and only the browser process is
  guaranteed once the controller exists.
- ProfileName is asserted non-null rather than non-empty. It is genuinely empty
  on Windows because the controller is created without ICoreWebView2ControllerOptions,
  so no profile name is requested even though ProfilePath resolves to "Default".
- PreferredColorScheme is persisted on-disk profile state shared across the run
  and across restarts, so the original is restored in a finally.

The missing-folder test pins FileNotFoundException, since that type is how an app
detects a missing runtime and is what the WinRT surface Uno mirrors produces.

Restricted to SkiaWin32 rather than also NativeWinUI: the Inconclusive guard
treats a null or empty version as "runtime not installed", so adding the WinAppSDK
head before its null-vs-throw behavior is confirmed would make the parity test
pass vacuously on exactly the head it was added for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Covers the statics, the environment and profile of a live WebView2, and the
three ClearBrowsingDataAsync overloads, in two sections so the static half is
usable with no WebView2 present.

Deliberately not gated to non-Windows, unlike WebView2_EnvironmentOptions: these
APIs do exist natively on WinAppSDK, and running the same page on both heads is
the whole parity value. It therefore has to survive targets where every call
throws, so nothing is called from the constructor - every call sits behind a
Click handler that reports the exception type and message.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Lists the newly supported surface and what other targets do, including two
behaviors that are surprising without explanation: ProfileName is always empty
on Windows, and the support is specific to the default WebView2 backend on
net10.0 and later.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The note added in 36869f446e conflated two independent things. The statics are
registered in Win32Host under a plain TFM guard, while the backend is chosen
per-control in Win32NativeWebViewProvider.CreateNativeWebView - nothing connects
them. So on net10.0 the statics work whatever UNO_WEBVIEW2_BACKEND says, and only
Environment, Profile and BrowserProcessId depend on the backend, because only
Win32NativeAotWebView carries the capability interfaces.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…cationbroker.cancel

fix(ios): report UserCancel when web auth sheet is dismissed
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…il-to-0.11.6

chore: use Mono.Cecil 0.11.6
…ssets

fix(msal): Deploy platform MSAL assets under SkiaRenderer
The Win32 WebView2 constructor blocks the UI thread in a nested pump while
the environment and controller are created. On a cold CI agent that stall
consumes the whole 1s WaitForLoaded default, so the first tests of the class
timed out waiting on the Border before reaching any assertion.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- LogExtensionPoint._loggers held a strong Type key, so any type from a
  collectible AssemblyLoadContext that logged once rooted that context's
  LoaderAllocator for the process lifetime
- switch to ConditionalWeakTable<Type, Logger>: the cache is a pure
  memoization, so weak keys make it collectible-safe with no unload hook
- add Given_LogExtensionPoint_Alc covering both the collection of a
  logged-from collectible ALC and the surviving per-type memoization

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bview2-env-n-profile

feat(webview): Implement CoreWebView2Environment and CoreWebView2Profile on Skia Win32
…-alc-cache

fix(logging): weak-key the per-type logger cache so collectible ALCs can unload
chore(docs): External Docs Update - master
chore(docs): External Docs Update - master
…ync/feature/wasm-mt

# Conflicts:
#	src/Uno.UI/Generated/3.0.0.0/Microsoft.Web.WebView2.Core/CoreWebView2.cs
#	src/Uno.UI/Generated/3.0.0.0/Microsoft.Web.WebView2.Core/CoreWebView2Environment.cs
#	src/Uno.UI/Generated/3.0.0.0/Microsoft.Web.WebView2.Core/CoreWebView2ProcessInfo.cs
#	src/Uno.UI/Generated/3.0.0.0/Microsoft.Web.WebView2.Core/CoreWebView2Profile.cs
@github-actions
github-actions Bot marked this pull request as draft August 15, 2026 04:11
auto-merge was automatically disabled August 15, 2026 04:11

Pull request was converted to draft

@github-actions github-actions Bot added the conflicts Automated merge hit conflicts label Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conflicts Automated merge hit conflicts master-sync Automated master→feature sync PR 🤖 Project automation

Projects

None yet

Development

Successfully merging this pull request may close these issues.