macOS: unhandled JavaScriptException in async void OnDelegateOnDidFinishNavigation crashes the whole process on non-scriptable navigation (e.g. file download)

Open Beginner friendly
#81 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
csharp, macos
Domain
desktop

Research direction

Start at MaciosWebViewAdapter.OnDelegateOnDidFinishNavigation and inspect its InvokeScript call and async exception path. Reproduce with a non-scriptable file-download response on macOS, then verify that bridge-injection failure no longer terminates the process and navigation completion still behaves as expected.

Written by the indexing model from the issue text.

Description

backend-wkwebview
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
  1. Run an Avalonia application on macOS Apple Silicon with a NativeWebView.
  2. Navigate to a page containing a downloadable file link.
  3. Click a link whose response is a file/download response rather than a normal scriptable HTML page.
  4. 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.

Dominant language
C#
Stars
129
Forks
31
Avg merge
21d 11h
Merged PRs (30d)
1

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from AvaloniaUI/Avalonia.Controls.WebView

All issues in AvaloniaUI/Avalonia.Controls.WebView

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.