ioswebkitwkwebviewios26wkurlschemehandler

iOS 26 web page with script is terminated on custom scheme WKURLSchemeHandler


Update (06.08.2025): Fixed in iOS beta 5

Something has changed in iOS 26 (tested on beta 4) and now if custom scheme is used and web page contains script element then WebKit is terminated with following log:

0x1130bc170 - [PID=47858] WebProcessProxy::didClose: (web process 0 crash)
0x1130bc170 - [PID=47858] WebProcessProxy::processDidTerminateOrFailedToLaunch: reason=Crash

Steps to reproduce:

  1. Create WKWebView with custom configuration and custom url scheme handler
  2. Load HTML with script element inside that references to another file

Expected result: WKWebView is loaded

Actual result: WKWebView is terminated

Code example:

final class CustomSchemeViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let sampleConfiguration = WKWebViewConfiguration()
        sampleConfiguration.setURLSchemeHandler(
            SampleURLSchemeHandler(),
            forURLScheme: "sample"
        )

        let webView = WKWebView(frame: view.bounds, configuration: sampleConfiguration)
        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(webView)

        webView.navigationDelegate = self

        webView.load(URLRequest(url: URL(string: "sample://pages/sample.html")!))
    }
}

extension CustomSchemeViewController: WKNavigationDelegate {
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        print("webViewWebContentProcessDidTerminate")
    }
}

final class SampleURLSchemeHandler: NSObject, WKURLSchemeHandler {
    private func post(_ body: String, mimeType: String, urlSchemeTask: WKURLSchemeTask) {
        let body = Data(body.utf8)

        let response = URLResponse(
            url: urlSchemeTask.request.url!,
            mimeType: mimeType,
            expectedContentLength: body.count,
            textEncodingName: nil
        )

        urlSchemeTask.didReceive(response)
        urlSchemeTask.didReceive(body)
        urlSchemeTask.didFinish()
    }

    func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
        switch urlSchemeTask.request.url?.lastPathComponent {
        case "sample.html":
            post("""
                <?xml version="1.0" encoding="UTF-8"?><html xmlns="http://www.w3.org/1999/xhtml">
                  <head>
                    <script src="/scripts/sample.js"></script>
                  </head>
                  <body>
                    <p>Sample</p>
                  </body>
                </html>
                """,
                mimeType: "application/xhtml+xml",
                urlSchemeTask: urlSchemeTask
            )
        case "sample.js":
            post("console.log('Hello from JS File')",
                 mimeType: "text/javascript",
                 urlSchemeTask: urlSchemeTask
            )
        default:
            assertionFailure()
        }
    }

    func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {
        print("webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask)")
    }
}

It works fine with css file inside, without script tag or with async attribute

Code of sample project https://github.com/Igor-Palaguta/iOS26URLSchemeTermination


Solution

  • Fixed in iOS 26.0 beta 5

    According to WebKit ticket https://bugs.webkit.org/show_bug.cgi?id=296698 this was a duplicate of known already fixed issue https://bugs.webkit.org/show_bug.cgi?id=295946 And this fix was included to recent beta 5.