From cfd9ce3ea4163eefd3033d01990c4e60cfe15ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Laban?= <jerome@platform.uno> Date: Wed, 12 Mar 2025 15:16:58 -0400 Subject: [PATCH 1/5] fix(webview2): [wasm] Fix ExecuteScriptAsync --- .../Given_WebView2.cs | 58 +++++++++++++++++++ .../Native/Wasm/NativeWebView.Interop.wasm.cs | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs new file mode 100644 index 000000000000..54629da0d8a6 --- /dev/null +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs @@ -0,0 +1,58 @@ +#if HAS_UNO_WINUI +using System; +using System.Threading.Tasks; +using Private.Infrastructure; +using Microsoft/* UWP don't rename */.UI.Xaml.Controls; +using System.Linq; +using Microsoft.Web.WebView2.Core; +using System.Diagnostics; + +namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls; + +[TestClass] +[RunsOnUIThread] +public class Given_WebView +{ + [TestMethod] + public async Task When_InvokeScriptAsync() + { + var border = new Border(); + var webView = new WebView2(); + webView.Width = 200; + webView.Height = 200; + border.Child = webView; + TestServices.WindowHelper.WindowContent = border; + bool navigated = false; + await TestServices.WindowHelper.WaitForLoaded(border); + webView.NavigationCompleted += (sender, e) => navigated = true; + webView.NavigateToString("<html><body><div id='test' style='width: 100px; height: 100px; background-color: blue;' /></body></html>"); + await TestServices.WindowHelper.WaitFor(() => navigated); + + var sw = Stopwatch.StartNew(); + string color = null; + + do + { + // We need to wait for the element to be available, navigated + // may be set to true too early on wasm. + color = await webView.ExecuteScriptAsync( + """ + let testElement = document.getElementById('test'); + if(testElement){ + return testElement.style.backgroundColor.toString(); + } + return ""; + """); + + } while (sw.Elapsed < TimeSpan.FromSeconds(5) && string.IsNullOrEmpty(color)); + + Assert.AreEqual("blue", color); + + // Change color to red + await webView.ExecuteScriptAsync("document.getElementById('test').style.backgroundColor = 'red'"); + color = await webView.ExecuteScriptAsync("document.getElementById('test').style.backgroundColor.toString()"); + + Assert.AreEqual("red", color); + } +} +#endif diff --git a/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.Interop.wasm.cs b/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.Interop.wasm.cs index d9f7c3ddb4be..a7c2e9a6d118 100644 --- a/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.Interop.wasm.cs +++ b/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.Interop.wasm.cs @@ -20,7 +20,7 @@ internal static partial class NativeMethods [JSImport("globalThis.Microsoft.UI.Xaml.Controls.WebView.goForward")] internal static partial void GoForward(IntPtr htmlId); - [JSImport("globalThis.Microsoft.UI.Xaml.Controls.WebView.executeScriptAsync")] + [JSImport("globalThis.Microsoft.UI.Xaml.Controls.WebView.executeScript")] internal static partial string ExecuteScript(IntPtr htmlId, string script); [JSImport("globalThis.Microsoft.UI.Xaml.Controls.WebView.getDocumentTitle")] From 24c958dde1e92ce7e3e33f1022cdbdef3b3d7c28 Mon Sep 17 00:00:00 2001 From: Jerome Laban <jerome@platform.uno> Date: Sat, 15 Mar 2025 23:29:16 -0400 Subject: [PATCH 2/5] chore: Adjust test name, use function for conditional return --- .../Windows_UI_Xaml_Controls/Given_WebView2.cs | 14 ++++++++------ .../WebView/Native/Wasm/NativeWebView.wasm.cs | 6 +++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs index 54629da0d8a6..78e79e0408d8 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs @@ -11,7 +11,7 @@ namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls; [TestClass] [RunsOnUIThread] -public class Given_WebView +public class Given_WebView2 { [TestMethod] public async Task When_InvokeScriptAsync() @@ -37,11 +37,13 @@ public async Task When_InvokeScriptAsync() // may be set to true too early on wasm. color = await webView.ExecuteScriptAsync( """ - let testElement = document.getElementById('test'); - if(testElement){ - return testElement.style.backgroundColor.toString(); - } - return ""; + (function () { + let testElement = document.getElementById('test'); + if(testElement){ + return testElement.style.backgroundColor.toString(); + } + return ""; + })() """); } while (sw.Elapsed < TimeSpan.FromSeconds(5) && string.IsNullOrEmpty(color)); diff --git a/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs b/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs index d16e0af64bc8..bec23aab3b26 100644 --- a/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs +++ b/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs @@ -48,7 +48,11 @@ private void OnNavigationCompleted(object sender, EventArgs e) _coreWebView.RaiseNavigationCompleted(uri, true, 200, CoreWebView2WebErrorStatus.Unknown); } - public Task<string> ExecuteScriptAsync(string script, CancellationToken token) => Task.FromResult(NativeMethods.ExecuteScript(HtmlId, script)); + public async Task<string> ExecuteScriptAsync(string script, CancellationToken token) + { + await Task.Yield(); + return NativeMethods.ExecuteScript(HtmlId, script); + } public Task<string> InvokeScriptAsync(string script, string[] arguments, CancellationToken token) => Task.FromResult<string>(""); From c3646509f837532933d8ff7cf93367284ff1fc96 Mon Sep 17 00:00:00 2001 From: Jerome Laban <jerome@platform.uno> Date: Mon, 17 Mar 2025 09:59:41 -0400 Subject: [PATCH 3/5] chore: Adjust for string quoting --- .../Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs | 4 ++-- .../Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs index 78e79e0408d8..38a5a5bf5b71 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs @@ -48,13 +48,13 @@ public async Task When_InvokeScriptAsync() } while (sw.Elapsed < TimeSpan.FromSeconds(5) && string.IsNullOrEmpty(color)); - Assert.AreEqual("blue", color); + Assert.AreEqual("\"blue\"", color); // Change color to red await webView.ExecuteScriptAsync("document.getElementById('test').style.backgroundColor = 'red'"); color = await webView.ExecuteScriptAsync("document.getElementById('test').style.backgroundColor.toString()"); - Assert.AreEqual("red", color); + Assert.AreEqual("\"red\"", color); } } #endif diff --git a/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs b/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs index bec23aab3b26..37dd0e279b96 100644 --- a/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs +++ b/src/Uno.UI/UI/Xaml/Controls/WebView/Native/Wasm/NativeWebView.wasm.cs @@ -51,7 +51,10 @@ private void OnNavigationCompleted(object sender, EventArgs e) public async Task<string> ExecuteScriptAsync(string script, CancellationToken token) { await Task.Yield(); - return NativeMethods.ExecuteScript(HtmlId, script); + var result = NativeMethods.ExecuteScript(HtmlId, script); + + // String needs to be wrapped in quotes to match Windows behavior + return $"\"{result.Replace("\"", "\\\"")}\""; } public Task<string> InvokeScriptAsync(string script, string[] arguments, CancellationToken token) => Task.FromResult<string>(""); From 65602446afbdfb8b33a9a3ae5012ff445a168f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Laban?= <jlaban@gmail.com> Date: Mon, 17 Mar 2025 21:10:37 -0400 Subject: [PATCH 4/5] chore: Adjust for skia targets --- .../Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs index 38a5a5bf5b71..3f6d9c55a6e2 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs @@ -14,6 +14,9 @@ namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls; public class Given_WebView2 { [TestMethod] +#if __SKIA__ + [Ignore("WebView2 is not yet supported on skia targets")] +#endif public async Task When_InvokeScriptAsync() { var border = new Border(); @@ -46,7 +49,7 @@ public async Task When_InvokeScriptAsync() })() """); - } while (sw.Elapsed < TimeSpan.FromSeconds(5) && string.IsNullOrEmpty(color)); + } while (sw.Elapsed < TimeSpan.FromSeconds(5) && string.IsNullOrEmpty(color.Replace("\"", ""))); Assert.AreEqual("\"blue\"", color); From a7beb8796fd1a5f77ba072df3e393067c346f12d Mon Sep 17 00:00:00 2001 From: Jerome Laban <jerome@platform.uno> Date: Tue, 18 Mar 2025 08:34:49 -0400 Subject: [PATCH 5/5] chore: Adjust timeout for iOS --- .../Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs index 3f6d9c55a6e2..ca10e0cbaa6a 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_WebView2.cs @@ -29,7 +29,7 @@ public async Task When_InvokeScriptAsync() await TestServices.WindowHelper.WaitForLoaded(border); webView.NavigationCompleted += (sender, e) => navigated = true; webView.NavigateToString("<html><body><div id='test' style='width: 100px; height: 100px; background-color: blue;' /></body></html>"); - await TestServices.WindowHelper.WaitFor(() => navigated); + await TestServices.WindowHelper.WaitFor(() => navigated, timeoutMS: 10000); var sw = Stopwatch.StartNew(); string color = null; @@ -49,7 +49,7 @@ public async Task When_InvokeScriptAsync() })() """); - } while (sw.Elapsed < TimeSpan.FromSeconds(5) && string.IsNullOrEmpty(color.Replace("\"", ""))); + } while (sw.Elapsed < TimeSpan.FromSeconds(10) && string.IsNullOrEmpty(color.Replace("\"", ""))); Assert.AreEqual("\"blue\"", color);