diff --git a/Plugins/PackageToJS/Tests/ExampleTests.swift b/Plugins/PackageToJS/Tests/ExampleTests.swift index d860a685..e635adfc 100644 --- a/Plugins/PackageToJS/Tests/ExampleTests.swift +++ b/Plugins/PackageToJS/Tests/ExampleTests.swift @@ -14,14 +14,29 @@ extension Trait where Self == ConditionTrait { static func requireSwiftSDK(triple: String) -> ConditionTrait { .enabled( - if: ProcessInfo.processInfo.environment["SWIFT_SDK_ID"] != nil - && ProcessInfo.processInfo.environment["SWIFT_PATH"] != nil - && ProcessInfo.processInfo.environment["SWIFT_SDK_ID"]!.hasSuffix(triple), + if: { + guard let swiftSDKID = ProcessInfo.processInfo.environment["SWIFT_SDK_ID"], + ProcessInfo.processInfo.environment["SWIFT_PATH"] != nil + else { + return false + } + func sanityCheckCompatibility(triple: String) -> Bool { + return swiftSDKID.hasSuffix(triple) + } + // For compatibility with old SDKs, we check wasm32-unknown-wasi as well when + // wasm32-unknown-wasip1 is requested. + if triple == "wasm32-unknown-wasip1" { + if sanityCheckCompatibility(triple: "wasm32-unknown-wasi") { + return true + } + } + return sanityCheckCompatibility(triple: triple) + }(), "Requires SWIFT_SDK_ID and SWIFT_PATH environment variables" ) } - static var requireEmbeddedSwift: ConditionTrait { + static func requireEmbeddedSwiftInToolchain(triple: String) -> ConditionTrait { // Check if $SWIFT_PATH/../lib/swift/embedded/wasm32-unknown-none-wasm/ exists return .enabled( if: { @@ -29,12 +44,48 @@ extension Trait where Self == ConditionTrait { return false } let embeddedPath = URL(fileURLWithPath: swiftPath).deletingLastPathComponent() - .appending(path: "lib/swift/embedded/wasm32-unknown-none-wasm") + .appending(path: "lib/swift/embedded/\(triple)") return FileManager.default.fileExists(atPath: embeddedPath.path) }(), "Requires embedded Swift SDK under $SWIFT_PATH/../lib/swift/embedded" ) } + + static func requireEmbeddedSwiftInSwiftSDK() -> ConditionTrait { + // Check if ${SWIFT_SDK_ID}-embedded is available + return .enabled( + if: { + /// Check if the Swift SDK with the given ID is available. + func isSwiftSDKAvailable(_ id: String, swiftPath: String) -> Bool { + let swiftExecutable = URL( + fileURLWithPath: "swift", + relativeTo: URL(fileURLWithPath: swiftPath) + ) + let process = Process() + process.executableURL = swiftExecutable + let arguments = ["sdk", "configure", "--show-configuration", id] + process.arguments = arguments + process.standardOutput = FileHandle.nullDevice + process.standardError = FileHandle.nullDevice + do { + try process.run() + process.waitUntilExit() + return process.terminationStatus == 0 + } catch { + return false + } + } + guard let swiftPath = ProcessInfo.processInfo.environment["SWIFT_PATH"], + let swiftSDKID = ProcessInfo.processInfo.environment["SWIFT_SDK_ID"] + else { + return false + } + let embeddedSDKID = "\(swiftSDKID)-embedded" + return isSwiftSDKAvailable(embeddedSDKID, swiftPath: swiftPath) + }(), + "Requires SWIFT_SDK_ID to contain 'embedded'" + ) + } } @Suite struct ExampleTests { @@ -46,6 +97,11 @@ extension Trait where Self == ConditionTrait { ProcessInfo.processInfo.environment["SWIFT_PATH"] } + static func getEmbeddedSwiftSDKID() -> String? { + guard let swiftSDKID = getSwiftSDKID() else { return nil } + return "\(swiftSDKID)-embedded" + } + static let repoPath = URL(fileURLWithPath: #filePath) .deletingLastPathComponent() .deletingLastPathComponent() @@ -220,7 +276,7 @@ extension Trait where Self == ConditionTrait { let swiftPath = try #require(Self.getSwiftPath()) try withPackage(at: "Examples/Testing") { packageDir, runProcess, runSwift in try runSwift( - ["package", "--swift-sdk", swiftSDKID, "js", "test", "--enable-code-coverage"], + ["package", "--disable-sandbox", "--swift-sdk", swiftSDKID, "js", "test", "--enable-code-coverage"], [ "LLVM_PROFDATA_PATH": URL(fileURLWithPath: swiftPath).appending(path: "llvm-profdata").path ] @@ -267,7 +323,8 @@ extension Trait where Self == ConditionTrait { } } - @Test(.requireEmbeddedSwift) func embedded() throws { + @Test(.requireEmbeddedSwiftInToolchain(triple: "wasm32-unknown-none-wasm")) + func embeddedWasmUnknownNone() throws { try withPackage(at: "Examples/Embedded") { packageDir, _, runSwift in try runSwift( ["package", "--triple", "wasm32-unknown-none-wasm", "js", "-c", "release"], @@ -278,6 +335,19 @@ extension Trait where Self == ConditionTrait { } } + @Test(.requireEmbeddedSwiftInSwiftSDK()) + func embeddedWasmUnknownWasi() throws { + let swiftSDKID = try #require(Self.getEmbeddedSwiftSDKID()) + try withPackage(at: "Examples/Embedded") { packageDir, _, runSwift in + try runSwift( + ["package", "--swift-sdk", swiftSDKID, "js", "-c", "release"], + [ + "JAVASCRIPTKIT_EXPERIMENTAL_EMBEDDED_WASM": "true" + ] + ) + } + } + @Test(.requireSwiftSDK) func continuationLeakInTest_XCTest() throws { let swiftSDKID = try #require(Self.getSwiftSDKID()) diff --git a/Sources/_CJavaScriptKit/_CJavaScriptKit.c b/Sources/_CJavaScriptKit/_CJavaScriptKit.c index 9df18b88..0603c7d9 100644 --- a/Sources/_CJavaScriptKit/_CJavaScriptKit.c +++ b/Sources/_CJavaScriptKit/_CJavaScriptKit.c @@ -33,10 +33,7 @@ void swjs_cleanup_host_function_call(void *argv_buffer) { free(argv_buffer); } -// NOTE: This __wasi__ check is a hack for Embedded compatibility (assuming that if __wasi__ is defined, we are not building for Embedded) -// cdecls don't work in Embedded, but @_expose(wasm) can be used with Swift >=6.0 -// the previously used `#if __Embedded` did not play well with SwiftPM (defines needed to be on every target up the chain) -# ifdef __wasi__ +# if defined(__wasi__) && !defined(__EMBEDDED_SWIFT__) bool _call_host_function_impl(const JavaScriptHostFuncRef host_func_ref, const RawJSValue *argv, const int argc, const JavaScriptObjectRef callback_func);