Skip to content

Enable String, URL and XML-related types for WASI #3051

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Sources/Foundation/NSString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 9 additions & 1 deletion Sources/Foundation/NSSwiftRuntime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand Down
23 changes: 23 additions & 0 deletions Sources/Foundation/NSURL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -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.
Expand Down Expand Up @@ -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 {
Expand All @@ -852,6 +863,7 @@ extension NSURL {
}

}
#endif
return result
}

Expand Down Expand Up @@ -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
}


Expand All @@ -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
Expand Down Expand Up @@ -1005,6 +1026,7 @@ extension NSURL : _StructTypeBridgeable {

// -----

#if !os(WASI)
internal func _CFSwiftURLCopyResourcePropertyForKey(_ url: CFTypeRef, _ key: CFString, _ valuePointer: UnsafeMutablePointer<Unmanaged<CFTypeRef>?>?, _ errorPointer: UnsafeMutablePointer<Unmanaged<CFError>?>?) -> _DarwinCompatibleBoolean {
do {
let key = URLResourceKey(rawValue: key._swiftObject)
Expand Down Expand Up @@ -1538,6 +1560,7 @@ fileprivate extension URLResourceValuesStorage {
}
}
}
#endif

// -----

Expand Down
2 changes: 2 additions & 0 deletions Sources/Foundation/PropertyListSerialization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ open class PropertyListSerialization : NSObject {
}
}

#if !os(WASI)
internal class func propertyList(with stream: CFReadStream, options opt: ReadOptions, format: UnsafeMutablePointer <PropertyListFormat>?) throws -> Any {
var fmt = kCFPropertyListBinaryFormat_v1_0
var error: Unmanaged<CFError>? = nil
Expand All @@ -93,4 +94,5 @@ open class PropertyListSerialization : NSObject {
open class func propertyList(with stream: InputStream, options opt: ReadOptions = [], format: UnsafeMutablePointer<PropertyListFormat>?) throws -> Any {
return try propertyList(with: stream._stream, options: opt, format: format)
}
#endif
}
44 changes: 43 additions & 1 deletion Sources/FoundationXML/XMLParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand All @@ -427,6 +432,7 @@ open class XMLParser : NSObject {
return nil
}
}
#endif
}

// create the parser from data
Expand All @@ -442,13 +448,15 @@ 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()
_stream = stream
_handler = _CFXMLInterfaceCreateSAXHandler()
_parserContext = nil
}
#endif

open weak var delegate: XMLParserDelegate?

Expand All @@ -460,20 +468,32 @@ open class XMLParser : NSObject {

open var allowedExternalEntityURLs: Set<URL>?

#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 {
Expand Down Expand Up @@ -547,6 +567,7 @@ open class XMLParser : NSObject {
return result
}

#if !os(WASI)
internal func parseFrom(_ stream : InputStream) -> Bool {
var result = true

Expand Down Expand Up @@ -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..<chunkEnd]
result = parseData(chunk)
chunkStart = chunkEnd
chunkEnd = min(chunkEnd + _chunkSize, data.count)
}
return result
}
#endif

// called to start the event-driven parse. Returns YES in the event of a successful parse, and NO in case of error.
open func parse() -> Bool {
#if os(WASI)
return _data.map { parse(from: $0) } ?? false
#else
XMLParser.setCurrentParser(self)
defer { XMLParser.setCurrentParser(nil) }

Expand All @@ -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.
Expand Down