fix Luna @MainActor warnings, cleanup, tests, ...

This commit is contained in:
2025-11-01 18:46:16 +01:00
parent 2af2592b8e
commit f09a522156

View File

@@ -74,16 +74,12 @@ public class WKUserContentController {
public func removeScriptMessageHandler(forName name: String) { public func removeScriptMessageHandler(forName name: String) {
scriptMessageHandlers.removeValue(forKey: name) scriptMessageHandlers.removeValue(forKey: name)
Task { @MainActor [weak owner] in owner?._updateJSBridgeBindings()
owner?._updateJSBridgeBindings()
}
} }
public func add(_ scriptMessageHandler: any WKScriptMessageHandler, name: String) { public func add(_ scriptMessageHandler: any WKScriptMessageHandler, name: String) {
scriptMessageHandlers[name] = scriptMessageHandler scriptMessageHandlers[name] = scriptMessageHandler
Task { @MainActor [weak owner] in owner?._updateJSBridgeBindings()
owner?._updateJSBridgeBindings()
}
} }
} }
@@ -140,7 +136,7 @@ public struct WKNavigation {
} }
} }
public struct WKNavigationAction { public struct WKNavigationAction: Sendable {
public let request: URLRequest public let request: URLRequest
@available(*, unavailable, message: "The navigationType property is not supported.") @available(*, unavailable, message: "The navigationType property is not supported.")
@@ -149,7 +145,7 @@ public struct WKNavigationAction {
} }
} }
public enum WKNavigationActionPolicy { public enum WKNavigationActionPolicy: Sendable {
case allow case allow
case cancel case cancel
@@ -157,7 +153,6 @@ public enum WKNavigationActionPolicy {
case download case download
} }
@MainActor
public protocol WKNavigationDelegate : NSObjectProtocol { public protocol WKNavigationDelegate : NSObjectProtocol {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation) func webView(_ webView: WKWebView, didFinish navigation: WKNavigation)
func webView(_ webView: WKWebView, didFail navigation: WKNavigation, withError error: Error) func webView(_ webView: WKWebView, didFail navigation: WKNavigation, withError error: Error)
@@ -169,7 +164,6 @@ public protocol WKNavigationDelegate : NSObjectProtocol {
// MARK: - - WKWebView ( without WebKit ) // MARK: - - WKWebView ( without WebKit )
@MainActor
public class WKWebView: UIView { public class WKWebView: UIView {
fileprivate var _webView: AnyObject? fileprivate var _webView: AnyObject?
fileprivate var _delegateProxy: _DelegateProxy? fileprivate var _delegateProxy: _DelegateProxy?
@@ -339,7 +333,6 @@ fileprivate extension WKWebView {
} }
} }
@MainActor
func _updateJSBridgeBindings() { func _updateJSBridgeBindings() {
let handlerNames = configuration.userContentController.scriptMessageHandlers.keys let handlerNames = configuration.userContentController.scriptMessageHandlers.keys
let bridgeJS = """ let bridgeJS = """
@@ -402,7 +395,6 @@ fileprivate extension WKWebView {
} }
@objc @objc
@MainActor
fileprivate class _DelegateProxy: NSObject { fileprivate class _DelegateProxy: NSObject {
fileprivate weak var owner: WKWebView? fileprivate weak var owner: WKWebView?
@@ -499,30 +491,29 @@ fileprivate class _DelegateProxy: NSObject {
WKWebView.logger?.log("Navigation request: \(request.url?.absoluteString ?? "nil") (Type: \(navigationType))") WKWebView.logger?.log("Navigation request: \(request.url?.absoluteString ?? "nil") (Type: \(navigationType))")
let action = WKNavigationAction(request: request) final class DecisionBox: @unchecked Sendable {
var decision: WKNavigationActionPolicy = .allow var value: WKNavigationActionPolicy = .allow
let semaphore = DispatchSemaphore(value: 0) }
let box = DecisionBox()
let semaphore = DispatchSemaphore(value: 0)
let action = WKNavigationAction(request: request)
let handler: @Sendable (WKNavigationActionPolicy) -> Void = { policy in
box.value = policy
semaphore.signal()
}
// Call on main thread if we're not already there
if Thread.isMainThread { if Thread.isMainThread {
owner.navigationDelegate?.webView(owner, decidePolicyFor: action) { policy in owner.navigationDelegate?.webView(owner, decidePolicyFor: action, decisionHandler: handler)
decision = policy
semaphore.signal()
}
} else { } else {
DispatchQueue.main.async { DispatchQueue.main.async {
owner.navigationDelegate?.webView(owner, decidePolicyFor: action) { policy in owner.navigationDelegate?.webView(owner, decidePolicyFor: action, decisionHandler: handler)
decision = policy
semaphore.signal()
}
} }
} }
let timeout = DispatchTime.now() + .seconds(5) _ = semaphore.wait(timeout: .now() + 5)
if semaphore.wait(timeout: timeout) == .timedOut { let decision = box.value
WKWebView.logger?.log("Decision timeout → defaulting to ALLOW")
}
WKWebView.logger?.log("Decision: \(decision == .allow ? "ALLOW" : "CANCEL")") WKWebView.logger?.log("Decision: \(decision == .allow ? "ALLOW" : "CANCEL")")
return decision == .allow return decision == .allow
} }