diff --git a/Sources/Foundation/NSString.swift b/Sources/Foundation/NSString.swift index 9644eb7a79..65fe304f02 100644 --- a/Sources/Foundation/NSString.swift +++ b/Sources/Foundation/NSString.swift @@ -25,7 +25,11 @@ func NSLocalizedString(_ key: String, bundle: Bundle = Bundle.main, value: String = "", comment: String) -> String { +#if os(WASI) + return key +#else return bundle.localizedString(forKey: key, value: value, table: tableName) +#endif } internal let kCFStringEncodingMacRoman = CFStringBuiltInEncodings.macRoman.rawValue diff --git a/Sources/Foundation/NSSwiftRuntime.swift b/Sources/Foundation/NSSwiftRuntime.swift index 462995a366..04958446d7 100644 --- a/Sources/Foundation/NSSwiftRuntime.swift +++ b/Sources/Foundation/NSSwiftRuntime.swift @@ -16,11 +16,15 @@ @_exported import Darwin #elseif os(Linux) || os(Android) || CYGWIN || os(OpenBSD) @_exported import Glibc +#elseif os(WASI) +@_exported import WASILibc #elseif os(Windows) @_exported import CRT #endif +#if !os(WASI) @_exported import Dispatch +#endif #if os(Windows) import WinSDK @@ -257,8 +261,10 @@ internal func __CFInitializeSwift() { __CFSwiftBridge.NSMutableString.appendString = _CFSwiftStringAppend __CFSwiftBridge.NSMutableString.appendCharacters = _CFSwiftStringAppendCharacters __CFSwiftBridge.NSMutableString._cfAppendCString = _CFSwiftStringAppendCString - + +#if !os(WASI) __CFSwiftBridge.NSRunLoop._new = _NSRunLoopNew +#endif __CFSwiftBridge.NSCharacterSet._expandedCFCharacterSet = _CFSwiftCharacterSetExpandedCFCharacterSet __CFSwiftBridge.NSCharacterSet._retainedBitmapRepresentation = _CFSwiftCharacterSetRetainedBitmapRepresentation @@ -304,6 +310,7 @@ internal func __CFInitializeSwift() { // __CFDefaultEightBitStringEncoding = UInt32(kCFStringEncodingUTF8) +#if !os(WASI) __CFSwiftBridge.NSURL.copyResourcePropertyForKey = _CFSwiftURLCopyResourcePropertyForKey __CFSwiftBridge.NSURL.copyResourcePropertiesForKeys = _CFSwiftURLCopyResourcePropertiesForKeys __CFSwiftBridge.NSURL.setResourcePropertyForKey = _CFSwiftURLSetResourcePropertyForKey @@ -312,6 +319,7 @@ internal func __CFInitializeSwift() { __CFSwiftBridge.NSURL.clearResourcePropertyCache = _CFSwiftURLClearResourcePropertyCache __CFSwiftBridge.NSURL.setTemporaryResourceValueForKey = _CFSwiftSetTemporaryResourceValueForKey __CFSwiftBridge.NSURL.resourceIsReachable = _CFSwiftURLResourceIsReachable +#endif } public func === (lhs: AnyClass, rhs: AnyClass) -> Bool { diff --git a/Sources/Foundation/NSURL.swift b/Sources/Foundation/NSURL.swift index cb6d82cc31..bfe77f6de8 100644 --- a/Sources/Foundation/NSURL.swift +++ b/Sources/Foundation/NSURL.swift @@ -206,6 +206,7 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying { if validPathSeps.contains(where: { thePath.hasSuffix(String($0)) }) { isDir = true } else { +#if !os(WASI) let absolutePath: String if let absPath = baseURL?.appendingPathComponent(path).path { absolutePath = absPath @@ -214,6 +215,7 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying { } let _ = FileManager.default.fileExists(atPath: absolutePath, isDirectory: &isDir) +#endif } self.init(fileURLWithPath: thePath, isDirectory: isDir.boolValue, relativeTo: baseURL) @@ -230,9 +232,11 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying { if validPathSeps.contains(where: { thePath.hasSuffix(String($0)) }) { isDir = true } else { +#if !os(WASI) if !FileManager.default.fileExists(atPath: path, isDirectory: &isDir) { isDir = false } +#endif } super.init() _CFURLInitWithFileSystemPathRelativeToBase(_cfObject, thePath._cfObject, kCFURLPlatformPathStyle, isDir.boolValue, nil) @@ -542,6 +546,9 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying { // TODO: should be `checkResourceIsReachableAndReturnError` with autoreleased error parameter. // Currently Autoreleased pointers is not supported on Linux. open func checkResourceIsReachable() throws -> Bool { +#if os(WASI) + return false +#else guard isFileURL, let path = path else { throw NSError(domain: NSCocoaErrorDomain, @@ -557,6 +564,7 @@ open class NSURL : NSObject, NSSecureCoding, NSCopying { } return true +#endif } /* Returns a file path URL that refers to the same resource as a specified URL. File path URLs use a file system style path. An error will occur if the url parameter is not a file URL. A file reference URL's resource must exist and be reachable to be converted to a file path URL. Symbol is present in iOS 4, but performs no operation. @@ -841,6 +849,9 @@ extension NSURL { open func appendingPathComponent(_ pathComponent: String) -> URL? { var result : URL? = appendingPathComponent(pathComponent, isDirectory: false) + + // File URLs can't be handled on WASI without file system access +#if !os(WASI) // Since we are appending to a URL, path seperators should // always be '/', even if we're on Windows if !pathComponent.hasSuffix("/") && isFileURL { @@ -852,6 +863,7 @@ extension NSURL { } } +#endif return result } @@ -896,8 +908,12 @@ extension NSURL { if selfPath.isAbsolutePath { absolutePath = selfPath } else { +#if os(WASI) + return nil +#else let workingDir = FileManager.default.currentDirectoryPath absolutePath = workingDir._bridgeToObjectiveC().appendingPathComponent(selfPath) +#endif } @@ -918,15 +934,20 @@ extension NSURL { default: resolvedPath = resolvedPath._bridgeToObjectiveC().appendingPathComponent(component) +#if !os(WASI) if let destination = FileManager.default._tryToResolveTrailingSymlinkInPath(resolvedPath) { resolvedPath = destination } +#endif } } // It might be a responsibility of NSURL(fileURLWithPath:). Check it. var isExistingDirectory: ObjCBool = false + +#if !os(WASI) let _ = FileManager.default.fileExists(atPath: resolvedPath, isDirectory: &isExistingDirectory) +#endif if excludeSystemDirs { resolvedPath = resolvedPath._tryToRemovePathPrefix("/private") ?? resolvedPath @@ -1005,6 +1026,7 @@ extension NSURL : _StructTypeBridgeable { // ----- +#if !os(WASI) internal func _CFSwiftURLCopyResourcePropertyForKey(_ url: CFTypeRef, _ key: CFString, _ valuePointer: UnsafeMutablePointer?>?, _ errorPointer: UnsafeMutablePointer?>?) -> _DarwinCompatibleBoolean { do { let key = URLResourceKey(rawValue: key._swiftObject) @@ -1538,6 +1560,7 @@ fileprivate extension URLResourceValuesStorage { } } } +#endif // ----- diff --git a/Sources/Foundation/PropertyListSerialization.swift b/Sources/Foundation/PropertyListSerialization.swift index 8a70bf8a5f..0841e78017 100644 --- a/Sources/Foundation/PropertyListSerialization.swift +++ b/Sources/Foundation/PropertyListSerialization.swift @@ -74,6 +74,7 @@ open class PropertyListSerialization : NSObject { } } +#if !os(WASI) internal class func propertyList(with stream: CFReadStream, options opt: ReadOptions, format: UnsafeMutablePointer ?) throws -> Any { var fmt = kCFPropertyListBinaryFormat_v1_0 var error: Unmanaged? = nil @@ -93,4 +94,5 @@ open class PropertyListSerialization : NSObject { open class func propertyList(with stream: InputStream, options opt: ReadOptions = [], format: UnsafeMutablePointer?) throws -> Any { return try propertyList(with: stream._stream, options: opt, format: format) } +#endif } diff --git a/Sources/FoundationXML/XMLParser.swift b/Sources/FoundationXML/XMLParser.swift index e7c0ba91aa..befc828212 100644 --- a/Sources/FoundationXML/XMLParser.swift +++ b/Sources/FoundationXML/XMLParser.swift @@ -396,7 +396,9 @@ internal func _structuredErrorFunc(_ interface: _CFXMLInterface, error: _CFXMLIn open class XMLParser : NSObject { private var _handler: _CFXMLInterfaceSAXHandler +#if !os(WASI) internal var _stream: InputStream? +#endif internal var _data: Data? internal var _chunkSize = Int(4096 * 32) // a suitably large number for a decent chunk size @@ -410,6 +412,9 @@ open class XMLParser : NSObject { // initializes the parser with the specified URL. public convenience init?(contentsOf url: URL) { +#if os(WASI) + return nil +#else setupXMLParsing() if url.isFileURL { if let stream = InputStream(url: url) { @@ -427,6 +432,7 @@ open class XMLParser : NSObject { return nil } } +#endif } // create the parser from data @@ -442,6 +448,7 @@ open class XMLParser : NSObject { _CFXMLInterfaceDestroyContext(_parserContext) } +#if !os(WASI) //create a parser that incrementally pulls data from the specified stream and parses it. public init(stream: InputStream) { setupXMLParsing() @@ -449,6 +456,7 @@ open class XMLParser : NSObject { _handler = _CFXMLInterfaceCreateSAXHandler() _parserContext = nil } +#endif open weak var delegate: XMLParserDelegate? @@ -460,20 +468,32 @@ open class XMLParser : NSObject { open var allowedExternalEntityURLs: Set? +#if os(WASI) + private static var _currentParser: XMLParser? +#endif + internal static func currentParser() -> XMLParser? { +#if os(WASI) + return _currentParser +#else if let current = Thread.current.threadDictionary["__CurrentNSXMLParser"] { return current as? XMLParser } else { return nil } +#endif } internal static func setCurrentParser(_ parser: XMLParser?) { +#if os(WASI) + _currentParser = parser +#else if let p = parser { Thread.current.threadDictionary["__CurrentNSXMLParser"] = p } else { Thread.current.threadDictionary.removeObject(forKey: "__CurrentNSXMLParser") } +#endif } internal func _handleParseResult(_ parseResult: Int32) -> Bool { @@ -547,6 +567,7 @@ open class XMLParser : NSObject { return result } +#if !os(WASI) internal func parseFrom(_ stream : InputStream) -> Bool { var result = true @@ -575,9 +596,29 @@ open class XMLParser : NSObject { return result } - +#else + internal func parse(from data: Data) -> Bool { + var result = true + var chunkStart = 0 + var chunkEnd = min(_chunkSize, data.count) + while result { + if chunkStart >= data.count || chunkEnd >= data.count { + break + } + let chunk = data[chunkStart.. Bool { +#if os(WASI) + return _data.map { parse(from: $0) } ?? false +#else XMLParser.setCurrentParser(self) defer { XMLParser.setCurrentParser(nil) } @@ -588,6 +629,7 @@ open class XMLParser : NSObject { } return false +#endif } // called by the delegate to stop the parse. The delegate will get an error message sent to it.