From df05d7c2c6ef64c30018a0769e9f0a9c23dc9e7c Mon Sep 17 00:00:00 2001 From: Simon Rozsival Date: Wed, 13 May 2026 11:57:15 +0200 Subject: [PATCH 01/39] feat: Make HybridWebView JS-to-.NET invocation trimming and AOT safe - Remove HybridWebView feature switch (IsHybridWebViewSupported) entirely - Remove class-level [RequiresUnreferencedCode]/[RequiresDynamicCode] from HybridWebViewHandler and platform classes - Register HybridWebViewHandler and IHybridWebViewTaskManager unconditionally - Add safe SetInvokeJavaScriptTarget(T target, JsonSerializerContext) overload - Mark legacy SetInvokeJavaScriptTarget(T target) as [Obsolete] - Build method cache at registration time with pre-resolved JsonTypeInfos - AOT-safe invocation path: dictionary lookup -> MethodInfo.Invoke -> PropertyInfo.GetValue -> JsonSerializer.Serialize(object, JsonTypeInfo) - Add interceptor source generator that replaces BuildMethodCache with fully typed delegates at compile time - Update tests and sample to use the new safe overload - Add 11 unit tests for BuildMethodCache (method filtering, error handling, delegate invocation) - Add device tests for interceptor-vs-fallback path verification Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/design/FeatureSwitches.md | 7 +- .../Pages/Controls/HybridWebViewPage.xaml.cs | 4 +- .../Microsoft.Maui.Controls.targets | 6 +- .../netstandard2.0/maui-blazor.aotprofile.txt | 1 - .../netstandard2.0/maui-sc.aotprofile.txt | 1 - .../netstandard2.0/maui.aotprofile.txt | 1 - src/Controls/src/Core/Controls.Core.csproj | 6 +- .../Core/Hosting/AppHostBuilderExtensions.cs | 12 +- .../src/Core/HybridWebView/HybridWebView.cs | 79 ++++- .../net-android/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net-ios/PublicAPI.Unshipped.txt | 3 +- .../net-maccatalyst/PublicAPI.Unshipped.txt | 1 + .../net-tizen/PublicAPI.Unshipped.txt | 1 + .../net-windows/PublicAPI.Unshipped.txt | 1 + .../PublicAPI/net/PublicAPI.Unshipped.txt | 1 + .../netstandard/PublicAPI.Unshipped.txt | 1 + .../HybridWebViewTests_ExceptionHandling.cs | 40 ++- .../HybridWebViewTests_InvokeDotNetFails.cs | 10 +- ...dWebViewTests_SetInvokeJavaScriptTarget.cs | 49 ++- src/Core/src/Core.csproj | 1 + src/Core/src/Core/IHybridWebView.cs | 25 +- .../HybridWebViewHandler.Windows.cs | 7 +- .../HybridWebView/HybridWebViewHandler.cs | 275 +++++++++++++--- .../HybridWebView/HybridWebViewHandler.iOS.cs | 11 +- .../Core.HybridWebViewSourceGen.csproj | 33 ++ .../HybridWebViewInvokeTargetGenerator.cs | 306 ++++++++++++++++++ .../src/Platform/Android/MauiHybridWebView.cs | 7 +- .../Android/MauiHybridWebViewClient.cs | 5 - .../src/Platform/Windows/MauiHybridWebView.cs | 7 +- .../net-android/PublicAPI.Unshipped.txt | 3 + .../PublicAPI/net-ios/PublicAPI.Unshipped.txt | 1 + .../net-maccatalyst/PublicAPI.Unshipped.txt | 1 + .../net-tizen/PublicAPI.Unshipped.txt | 3 + .../net-windows/PublicAPI.Unshipped.txt | 3 + .../src/PublicAPI/net/PublicAPI.Unshipped.txt | 7 +- .../netstandard/PublicAPI.Unshipped.txt | 3 + .../netstandard2.0/PublicAPI.Unshipped.txt | 7 +- src/Core/src/RuntimeFeature.cs | 11 - .../HybridWebViewBuildMethodCacheTests.cs | 198 ++++++++++++ 39 files changed, 1001 insertions(+), 138 deletions(-) create mode 100644 src/Core/src/HybridWebViewSourceGen/Core.HybridWebViewSourceGen.csproj create mode 100644 src/Core/src/HybridWebViewSourceGen/HybridWebViewInvokeTargetGenerator.cs create mode 100644 src/Core/tests/UnitTests/HybridWebViewBuildMethodCacheTests.cs diff --git a/docs/design/FeatureSwitches.md b/docs/design/FeatureSwitches.md index 30e82b0b38f5..833c0c5d3a29 100644 --- a/docs/design/FeatureSwitches.md +++ b/docs/design/FeatureSwitches.md @@ -14,7 +14,6 @@ The following switches are toggled for applications running on Mono for `TrimMod | MauiImplicitCastOperatorsUsageViaReflectionSupport | Microsoft.Maui.RuntimeFeature.IsImplicitCastOperatorsUsageViaReflectionSupported | When disabled, MAUI won't look for implicit cast operators when converting values from one type to another. This feature is not trim-compatible. | | _MauiBindingInterceptorsSupport | Microsoft.Maui.RuntimeFeature.AreBindingInterceptorsSupported | When disabled, MAUI won't intercept any calls to `SetBinding` methods and try to compile them. Enabled by default. | | MauiEnableXamlCBindingWithSourceCompilation | Microsoft.Maui.RuntimeFeature.XamlCBindingWithSourceCompilationEnabled | When enabled, MAUI will compile all bindings, including those where the `Source` property is used. | -| MauiHybridWebViewSupported | Microsoft.Maui.RuntimeFeature.IsHybridWebViewSupported | Enables HybridWebView, which makes use of dynamic System.Text.Json serialization features | | MauiNamescopesSupported | Microsoft.Maui.RuntimeFeature.AreNamescopesSupported | Enable support for Namescopes, FindByName if the application uses it, or to keep supporting runtime and XamlC XAML inflators | | EnableDiagnostics | Microsoft.Maui.RuntimeFeature.EnableDiagnostics | Enables diagnostic for the running app | | EnableMauiDiagnostics | Microsoft.Maui.RuntimeFeature.EnableMauiDiagnostics | Enables MAUI specific diagnostics, like VisualDiagnostics and BindingDiagnostics. Defaults to EnableDiagnostics | @@ -100,9 +99,7 @@ This feature is a counterpart of [XAML Compiled bindings](https://learn.microsof It is necessary to use this feature instead of the string-based bindings in NativeAOT apps and in apps with full trimming enabled. -## MauiHybridWebViewSupported - -When this feature is disabled, `HybridWebView` will not be available. This is the default for projects using `TrimMode=full` or `PublishAot=true`. +## MauiEnableXamlCBindingWithSourceCompilation ### Example use-case @@ -124,8 +121,6 @@ Compiled binding in XAML: