Describe the bug
On macOS (Apple Silicon), when the WKWebView backend used by Avalonia.Controls.WebView navigates to a URL whose response is not a scriptable HTML document, the whole process can crash with an unhandled Avalonia.Controls.JavaScriptException.
Observed with ChatGPT-generated file download links. The same application code using the Windows WebView2 backend does not crash on the equivalent download.
The crash occurs inside the macOS adapter. MaciosWebViewAdapter.OnDelegateOnDidFinishNavigation unconditionally calls InvokeScript(...) after navigation finishes. If JavaScript cannot be executed in the resulting document, InvokeScript rethrows the native WebKit failure as JavaScriptException. Because the navigation completion handler is async void and does not catch that exception, the exception escapes and terminates the process.
Reproduced 3 times across two test sessions with an identical stack trace. Application-level attempts to cancel navigation, intercept only NewWindowRequested, and run with no custom navigation handlers did not prevent the crash.
To Reproduce
- Run an Avalonia application on macOS Apple Silicon with a
NativeWebView.
- Navigate to a page containing a downloadable file link.
- Click a link whose response is a file/download response rather than a normal scriptable HTML page.
- Observe that the process exits with an unhandled
Avalonia.Controls.JavaScriptException.
Observed in practice with ChatGPT-generated downloads.
A standalone example target would be an <a href="/download"> where /download responds with:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=test.txt
Expected behavior
Navigating to or initiating a file download must not crash the entire application process.
At minimum, failure to inject the C#↔JavaScript bridge into a non-scriptable document should be handled gracefully.
Actual native file-download support can be treated as a separate feature/fix.
Avalonia WebView version
12.1.0
Avalonia version
12.1.1
OS
macOS
Additional context
Environment:
- macOS, Apple Silicon (
osx-arm64)
- Target framework:
net8.0
dotnet publish -r osx-arm64 -c Debug --self-contained
- Also reproduces in Release
- .NET SDK used to build:
10.0.400
- Windows/WebView2 backend, same app code: does not crash on the equivalent download
Stack trace:
Unhandled exception. Avalonia.Controls.JavaScriptException: Cannot execute JavaScript in this document
---> Avalonia.Controls.Macios.Interop.NSErrorException: A JavaScript exception occurred
at Avalonia.Controls.Macios.Interop.WebKit.WKWebView.EvaluateJavaScriptAsync(String script)
at Avalonia.Controls.Macios.MaciosWebViewAdapter.InvokeScript(String script)
at Avalonia.Controls.Macios.MaciosWebViewAdapter.OnDelegateOnDidFinishNavigation(Object sender, EventArgs args)
...
Source-level confirmation:
private async void OnDelegateOnDidFinishNavigation(object? sender, EventArgs args)
{
_ = await InvokeScript(WebViewHelper.BuildWebKitInvokeCSharpActionScript(_scriptHandlerMessageName, stringify: true));
using var url = _webView.Url;
NavigationCompleted?.Invoke(this, new WebViewNavigationCompletedEventArgs { Request = Uri.TryCreate(url!.AbsoluteString, UriKind.Absolute, out var uri) ? uri : null, IsSuccess = true });
}
InvokeScript converts the native WebKit JavaScript failure into JavaScriptException, and the async void completion handler does not catch it.
Suggested crash-safety fix:
private async void OnDelegateOnDidFinishNavigation(object? sender, EventArgs args)
{
try
{
_ = await InvokeScript(WebViewHelper.BuildWebKitInvokeCSharpActionScript(_scriptHandlerMessageName, stringify: true));
}
catch (JavaScriptException)
{
// Bridge injection failure must not terminate the process.
}
using var url = _webView.Url;
NavigationCompleted?.Invoke(this, new WebViewNavigationCompletedEventArgs { Request = Uri.TryCreate(url!.AbsoluteString, UriKind.Absolute, out var uri) ? uri : null, IsSuccess = true });
}
This proposed change is intentionally scoped only to preventing the process crash. Full download support is separate.
Describe the bug
On macOS (Apple Silicon), when the
WKWebViewbackend used byAvalonia.Controls.WebViewnavigates to a URL whose response is not a scriptable HTML document, the whole process can crash with an unhandledAvalonia.Controls.JavaScriptException.Observed with ChatGPT-generated file download links. The same application code using the Windows WebView2 backend does not crash on the equivalent download.
The crash occurs inside the macOS adapter.
MaciosWebViewAdapter.OnDelegateOnDidFinishNavigationunconditionally callsInvokeScript(...)after navigation finishes. If JavaScript cannot be executed in the resulting document,InvokeScriptrethrows the native WebKit failure asJavaScriptException. Because the navigation completion handler isasync voidand does not catch that exception, the exception escapes and terminates the process.Reproduced 3 times across two test sessions with an identical stack trace. Application-level attempts to cancel navigation, intercept only
NewWindowRequested, and run with no custom navigation handlers did not prevent the crash.To Reproduce
NativeWebView.Avalonia.Controls.JavaScriptException.Observed in practice with ChatGPT-generated downloads.
A standalone example target would be an
<a href="/download">where/downloadresponds with:Content-Type: application/octet-streamContent-Disposition: attachment; filename=test.txtExpected behavior
Navigating to or initiating a file download must not crash the entire application process.
At minimum, failure to inject the C#↔JavaScript bridge into a non-scriptable document should be handled gracefully.
Actual native file-download support can be treated as a separate feature/fix.
Avalonia WebView version
12.1.0
Avalonia version
12.1.1
OS
macOS
Additional context
Environment:
osx-arm64)net8.0dotnet publish -r osx-arm64 -c Debug --self-contained10.0.400Stack trace:
Source-level confirmation:
InvokeScriptconverts the native WebKit JavaScript failure intoJavaScriptException, and theasync voidcompletion handler does not catch it.Suggested crash-safety fix:
This proposed change is intentionally scoped only to preventing the process crash. Full download support is separate.