Skip to content

Commit

Permalink
Swift 6: Fix concurrency warnings (#23)
Browse files Browse the repository at this point in the history
* Fix concurrency warnings

* Update json api

* Update readme

* Build on swift 5.9
  • Loading branch information
AndrewBarba authored Mar 20, 2024
1 parent 5f847f2 commit d0f41df
Show file tree
Hide file tree
Showing 18 changed files with 94 additions and 115 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ on: push
jobs:
build:
runs-on: ubuntu-latest
container: ghcr.io/swiftwasm/swift:5.7
container: ghcr.io/swiftwasm/swift:5.9

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- run: swift --version

- run: swift build -c debug --triple wasm32-unknown-wasi
- run: swift build -c debug --triple wasm32-unknown-wasi
38 changes: 0 additions & 38 deletions .github/workflows/codeql.yml

This file was deleted.

4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-crypto",
"state" : {
"revision" : "cc76b894169a3c86b71bac10c78a4db6beb7a9ad",
"version" : "3.2.0"
"revision" : "f0525da24dc3c6cbb2b6b338b65042bc91cbc4bb",
"version" : "3.3.0"
}
}
],
Expand Down
30 changes: 25 additions & 5 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.6
// swift-tools-version:5.9

import PackageDescription

Expand All @@ -17,9 +17,29 @@ let package = Package(
.package(url: "https://github.com/apple/swift-crypto", from: "3.0.0")
],
targets: [
.target(name: "Compute", dependencies: ["ComputeRuntime", .product(name: "Crypto", package: "swift-crypto")]),
.target(name: "ComputeRuntime"),
.executableTarget(name: "ComputeDemo", dependencies: ["Compute"]),
.testTarget(name: "ComputeTests", dependencies: ["Compute"])
.target(
name: "Compute",
dependencies: [
"ComputeRuntime",
.product(name: "Crypto", package: "swift-crypto")
],
swiftSettings: [
.enableExperimentalFeature("StrictConcurrency")
]
),
.target(
name: "ComputeRuntime",
swiftSettings: [
.enableExperimentalFeature("StrictConcurrency")
]
),
.executableTarget(
name: "ComputeDemo",
dependencies: ["Compute"]
),
.testTarget(
name: "ComputeTests",
dependencies: ["Compute"]
)
]
)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ swift package init --type executable
Install the Compute runtime:

```swift
.package(url: "https://github.com/swift-cloud/Compute", from: "2.19.0")
.package(url: "https://github.com/swift-cloud/Compute", from: "3.0.0")
```

Add it as a target dependency:
Expand Down
9 changes: 4 additions & 5 deletions Sources/Compute/Console.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

public let console = Console()

public struct Console {
public struct Console: Sendable {

public var prefix: String? = nil

Expand All @@ -25,19 +25,18 @@ public struct Console {
}

public func error(_ items: Any...) {
var errorStream = StandardErrorOutputStream()
let text = items.map { String(describing: $0) }.joined(separator: " ")
if let prefix = prefix {
print(prefix, text, to: &StandardErrorOutputStream.default)
print(prefix, text, to: &errorStream)
} else {
print(text, to: &StandardErrorOutputStream.default)
print(text, to: &errorStream)
}
}
}

fileprivate struct StandardErrorOutputStream: TextOutputStream {

fileprivate static var `default` = StandardErrorOutputStream()

private let stderr = FileHandle.standardError

func write(_ string: String) {
Expand Down
18 changes: 6 additions & 12 deletions Sources/Compute/Fanout/FanoutMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,22 +74,16 @@ extension FanoutMessage {
return try decoder.decode(type, from: data())
}

public func json() throws -> Any {
return try JSONSerialization.jsonObject(with: data())
public func json<T: Sendable>() throws -> T {
return try JSONSerialization.jsonObject(with: data()) as! T
}

public func jsonObject() throws -> [String: Any] {
guard let json = try JSONSerialization.jsonObject(with: data()) as? [String: Any] else {
throw FanoutMessageError.invalidFormat
}
return json
public func jsonObject() throws -> [String: Sendable] {
return try json()
}

public func jsonArray() throws -> [Any] {
guard let json = try JSONSerialization.jsonObject(with: data()) as? [Any] else {
throw FanoutMessageError.invalidFormat
}
return json
public func jsonArray() throws -> [Sendable] {
return try json()
}

public func data() throws -> Data {
Expand Down
16 changes: 8 additions & 8 deletions Sources/Compute/Fastly/FastlyEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ extension Fastly {
}

extension Fastly.Environment {
public static var cacheGeneration = current["FASTLY_CACHE_GENERATION"] ?? "local"
public static let cacheGeneration = current["FASTLY_CACHE_GENERATION"] ?? "local"

public static var customerId = current["FASTLY_CUSTOMER_ID"] ?? "local"
public static let customerId = current["FASTLY_CUSTOMER_ID"] ?? "local"

public static var hostname = current["FASTLY_HOSTNAME"] ?? "localhost"
public static let hostname = current["FASTLY_HOSTNAME"] ?? "localhost"

public static var pop = current["FASTLY_POP"] ?? "local"
public static let pop = current["FASTLY_POP"] ?? "local"

public static var region = current["FASTLY_REGION"] ?? "local"
public static let region = current["FASTLY_REGION"] ?? "local"

public static var serviceId = current["FASTLY_SERVICE_ID"] ?? "local"
public static let serviceId = current["FASTLY_SERVICE_ID"] ?? "local"

public static var serviceVersion = current["FASTLY_SERVICE_VERSION"] ?? "0"
public static let serviceVersion = current["FASTLY_SERVICE_VERSION"] ?? "0"

public static var traceId = current["FASTLY_TRACE_ID"] ?? "local"
public static let traceId = current["FASTLY_TRACE_ID"] ?? "local"

public static var viceroy: Bool {
return hostname == "localhost"
Expand Down
2 changes: 1 addition & 1 deletion Sources/Compute/Fastly/FastlyStubs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func fastly_cache__cache_transaction_cancel(_ handle: WasiHandle) -> Int32 { fat
func fastly_device__device_detection_lookup(
_ user_agent: UnsafePointer<CChar>!,
_ user_agent_len: Int,
_ buf: UnsafeMutablePointer<CChar>!,
_ buf: UnsafeMutablePointer<UInt8>!,
_ buf_len: Int,
_ nwritten: UnsafeMutablePointer<Int>!
) -> Int32 { fatalError() }
Expand Down
39 changes: 22 additions & 17 deletions Sources/Compute/Fetch/Fetch+Wasi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ internal struct WasiFetcher: Sendable {

// Register the backend
if Fastly.Environment.viceroy, request.backend != "localhost" {
try registerDynamicBackend(request.backend, for: httpRequest, ssl: urlComponents.scheme == "https")
try await dynamicBackends.register(request.backend, for: httpRequest, ssl: urlComponents.scheme == "https")
}

// Issue async request
Expand Down Expand Up @@ -119,25 +119,30 @@ internal struct WasiFetcher: Sendable {
}
}
}
}

private static var dynamicBackends: Set<String> = []
extension WasiFetcher {
private static let dynamicBackends = DynamicBackendRepository()

private static func registerDynamicBackend(_ backend: String, for request: Fastly.Request, ssl: Bool) throws {
// Make sure we didn't already register the backend
guard dynamicBackends.contains(backend) == false else {
return
}
private actor DynamicBackendRepository {

// Attempt to register the backend
do {
try request.registerDynamicBackend(name: backend, target: backend, options: .init(ssl: ssl))
} catch WasiStatus.unexpected {
// ignore
} catch {
throw error
}
private var state: Set<String> = []

func register(_ backend: String, for request: Fastly.Request, ssl: Bool) throws {
// Make sure we didn't already register the backend
guard !state.contains(backend) else { return }

// Mark the backend as registered
dynamicBackends.insert(backend)
// Mark the backend as registered
defer { state.insert(backend) }

// Attempt to register the backend
do {
try request.registerDynamicBackend(name: backend, target: backend, options: .init(ssl: ssl))
} catch WasiStatus.unexpected {
// ignore
} catch {
throw error
}
}
}
}
4 changes: 2 additions & 2 deletions Sources/Compute/Fetch/FetchRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,12 @@ extension FetchRequest {
}

public static func json(_ jsonObject: [String: Any]) throws -> Body {
let data = try JSONSerialization.data(withJSONObject: jsonObject, options: [])
let data = try JSONSerialization.data(withJSONObject: jsonObject)
return Body.json(data)
}

public static func json(_ jsonArray: [Any]) throws -> Body {
let data = try JSONSerialization.data(withJSONObject: jsonArray, options: [])
let data = try JSONSerialization.data(withJSONObject: jsonArray)
return Body.json(data)
}

Expand Down
6 changes: 3 additions & 3 deletions Sources/Compute/Fetch/FetchResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ extension FetchResponse {
return try await body.decode(type, decoder: decoder)
}

public func json() async throws -> Any {
public func json<T: Sendable>() async throws -> T {
return try await body.json()
}

public func jsonObject() async throws -> [String: Any] {
public func jsonObject() async throws -> [String: Sendable] {
return try await body.jsonObject()
}

public func jsonArray() async throws -> [Any] {
public func jsonArray() async throws -> [Sendable] {
return try await body.jsonArray()
}

Expand Down
10 changes: 5 additions & 5 deletions Sources/Compute/JWT/JWT.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public struct JWT: Sendable {
}

public init(
claims: [String: Any],
claims: [String: Sendable],
secret: String,
algorithm: Algorithm = .hs256,
issuedAt: Date = .init(),
Expand All @@ -63,12 +63,12 @@ public struct JWT: Sendable {
subject: String? = nil,
identifier: String? = nil
) throws {
let header: [String: Any] = [
let header: [String: Sendable] = [
"alg": algorithm.rawValue,
"typ": "JWT"
]

var properties: [String: Any] = [
var properties: [String: Sendable] = [
"iat": floor(issuedAt.timeIntervalSince1970)
]

Expand Down Expand Up @@ -192,9 +192,9 @@ extension JWT {
}
}

private func decodeJWTPart(_ value: String) throws -> [String: Any] {
private func decodeJWTPart(_ value: String) throws -> [String: Sendable] {
let bodyData = try base64UrlDecode(value)
guard let json = try JSONSerialization.jsonObject(with: bodyData, options: []) as? [String: Any] else {
guard let json = try JSONSerialization.jsonObject(with: bodyData) as? [String: Sendable] else {
throw JWTError.invalidJSON
}
return json
Expand Down
4 changes: 2 additions & 2 deletions Sources/Compute/KVStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ extension KVStore {
}

public func put(_ key: String, jsonObject: [String: Any]) async throws {
let data = try JSONSerialization.data(withJSONObject: jsonObject, options: [])
let data = try JSONSerialization.data(withJSONObject: jsonObject)
try await put(key, data: data)
}

public func put(_ key: String, jsonArray: [Any]) async throws {
let data = try JSONSerialization.data(withJSONObject: jsonArray, options: [])
let data = try JSONSerialization.data(withJSONObject: jsonArray)
try await put(key, data: data)
}

Expand Down
8 changes: 4 additions & 4 deletions Sources/Compute/ReadableBody/ReadableBody+Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@ extension ReadableDataBody {
return try decoder.decode(type, from: data)
}

func json() async throws -> Sendable {
return try JSONSerialization.jsonObject(with: data)
func json<T: Sendable>() async throws -> T {
return try JSONSerialization.jsonObject(with: data) as! T
}

func jsonObject() async throws -> [String : Sendable] {
return try JSONSerialization.jsonObject(with: data) as! [String: Any]
return try await json()
}

func jsonArray() async throws -> [Sendable] {
return try JSONSerialization.jsonObject(with: data) as! [Any]
return try await json()
}

func formValues() async throws -> HTTPSearchParams {
Expand Down
Loading

0 comments on commit d0f41df

Please sign in to comment.