diff --git a/Sources/FoundationEssentials/URL/URL.swift b/Sources/FoundationEssentials/URL/URL.swift index 948322a4b..a188f5378 100644 --- a/Sources/FoundationEssentials/URL/URL.swift +++ b/Sources/FoundationEssentials/URL/URL.swift @@ -635,13 +635,15 @@ public struct URL: Equatable, Sendable, Hashable { #if FOUNDATION_FRAMEWORK private static var _type: any _URLProtocol.Type { + if URL.compatibility2 { + return _BridgedURL.self + } return foundation_swift_url_enabled() ? _SwiftURL.self : _BridgedURL.self } #else private static let _type = _SwiftURL.self #endif - #if FOUNDATION_FRAMEWORK internal let _url: any _URLProtocol & AnyObject internal init(_ url: any _URLProtocol & AnyObject) { diff --git a/Sources/FoundationEssentials/URL/URL_Bridge.swift b/Sources/FoundationEssentials/URL/URL_Bridge.swift index 867c06624..8159eeb0c 100644 --- a/Sources/FoundationEssentials/URL/URL_Bridge.swift +++ b/Sources/FoundationEssentials/URL/URL_Bridge.swift @@ -14,17 +14,32 @@ internal import _ForSwiftFoundation internal import CoreFoundation_Private.CFURL +#if canImport(os) +internal import os +#endif + /// `_BridgedURL` wraps an `NSURL` reference. Its methods use the old implementations, which call directly into `NSURL` methods. /// `_BridgedURL` is used when an `NSURL` subclass is bridged to Swift, allowing us to: /// 1) Return the same subclass object when bridging back to ObjC. /// 2) Call methods that are overridden by the `NSURL` subclass like we did before. /// - Note: If the `NSURL` subclass does not override a method, `NSURL` will call into the underlying `_SwiftURL` implementation. -internal final class _BridgedURL: _URLProtocol, @unchecked Sendable { +internal final class _BridgedURL: NSObject, _URLProtocol, @unchecked Sendable { private let _url: NSURL internal init(_ url: NSURL) { self._url = url } + private static let logForwardingErrorOnce: Void = { + #if canImport(os) + URL.logger.error("struct URL no longer stores an NSURL. Clients should not assume the memory address of a URL will contain an NSURL * or CFURLRef and should not send ObjC messages to it directly. Bridge (url as NSURL) instead.") + #endif + }() + + override func forwardingTarget(for aSelector: Selector!) -> Any? { + _ = Self.logForwardingErrorOnce + return _url + } + init?(string: String) { guard !string.isEmpty, let inner = NSURL(string: string) else { return nil } _url = inner @@ -384,11 +399,11 @@ internal final class _BridgedURL: _URLProtocol, @unchecked Sendable { } #endif - var description: String { + override var description: String { return _url.description } - var debugDescription: String { + override var debugDescription: String { return _url.debugDescription }