From 886919dcb062fa9585f77a0e3bb1c8a139af92f2 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Mon, 13 Mar 2023 11:56:26 +0100 Subject: [PATCH 1/3] Add withUnsafeBytesAsync function --- .../BasicObjects/JSTypedArray.swift | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift index c22e6c8cc..e30fc3eb8 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift @@ -88,6 +88,31 @@ public class JSTypedArray: JSBridgedClass, ExpressibleByArrayLiteral wh let result = try body(bufferPtr) return result } + + /// Calls the given async closure with a pointer to a copy of the underlying bytes of the + /// array's storage. + /// + /// - Note: The pointer passed as an argument to `body` is valid only for the + /// lifetime of the closure. Do not escape it from the async closure for later + /// use. + /// + /// - Parameter body: A closure with an `UnsafeBufferPointer` parameter + /// that points to the contiguous storage for the array. + /// If `body` has a return value, that value is also + /// used as the return value for the `withUnsafeBytes(_:)` method. The + /// argument is valid only for the duration of the closure's execution. + /// - Returns: The return value, if any, of the `body`async closure parameter. + public func withUnsafeBytesAsync(_ body: (UnsafeBufferPointer) async throws -> R) async rethrows -> R { + let bytesLength = lengthInBytes + let rawBuffer = malloc(bytesLength)! + defer { free(rawBuffer) } + _load_typed_array(jsObject.id, rawBuffer.assumingMemoryBound(to: UInt8.self)) + let length = lengthInBytes / MemoryLayout.size + let boundPtr = rawBuffer.bindMemory(to: Element.self, capacity: length) + let bufferPtr = UnsafeBufferPointer(start: boundPtr, count: length) + let result = try await body(bufferPtr) + return result + } } // MARK: - Int and UInt support From 9c451401e08024d187b834f75781c05dada57ae7 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 13 Mar 2023 12:15:46 +0000 Subject: [PATCH 2/3] Explicitly select SDKROOT by Xcode --- .github/workflows/test.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d41966fe3..655da183e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,9 +10,9 @@ jobs: matrix: entry: # Ensure that all host can install toolchain, build project, and run tests - - { os: macos-10.15, toolchain: wasm-5.6.0-RELEASE, wasi-backend: Node } - - { os: macos-11, toolchain: wasm-5.6.0-RELEASE, wasi-backend: Node } - - { os: macos-12, toolchain: wasm-5.6.0-RELEASE, wasi-backend: Node } + - { os: macos-10.15, toolchain: wasm-5.6.0-RELEASE, wasi-backend: Node, xcode: Xcode_12.4.app } + - { os: macos-11, toolchain: wasm-5.6.0-RELEASE, wasi-backend: Node, xcode: Xcode_13.2.1.app } + - { os: macos-12, toolchain: wasm-5.6.0-RELEASE, wasi-backend: Node, xcode: Xcode_13.4.1.app } - { os: ubuntu-18.04, toolchain: wasm-5.6.0-RELEASE, wasi-backend: Node } # Ensure that test succeeds with all toolchains and wasi backend combinations @@ -33,6 +33,9 @@ jobs: uses: actions/checkout@master with: fetch-depth: 1 + - name: Select SDKROOT + if: ${{ matrix.entry.xcode }} + run: sudo xcode-select -s /Applications/${{ matrix.entry.xcode }} - uses: swiftwasm/setup-swiftwasm@v1 with: swift-version: ${{ matrix.entry.toolchain }} From 8fbe91dc9f4619e710e03aaa3f48f35b13292b6f Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 13 Mar 2023 12:21:16 +0000 Subject: [PATCH 3/3] Guard Concurrency feature use for older toolchain compatibility --- .../BasicObjects/JSTypedArray.swift | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift index e30fc3eb8..f82864e86 100644 --- a/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift +++ b/Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift @@ -88,31 +88,34 @@ public class JSTypedArray: JSBridgedClass, ExpressibleByArrayLiteral wh let result = try body(bufferPtr) return result } - - /// Calls the given async closure with a pointer to a copy of the underlying bytes of the - /// array's storage. - /// - /// - Note: The pointer passed as an argument to `body` is valid only for the - /// lifetime of the closure. Do not escape it from the async closure for later - /// use. - /// - /// - Parameter body: A closure with an `UnsafeBufferPointer` parameter - /// that points to the contiguous storage for the array. - /// If `body` has a return value, that value is also - /// used as the return value for the `withUnsafeBytes(_:)` method. The - /// argument is valid only for the duration of the closure's execution. - /// - Returns: The return value, if any, of the `body`async closure parameter. - public func withUnsafeBytesAsync(_ body: (UnsafeBufferPointer) async throws -> R) async rethrows -> R { - let bytesLength = lengthInBytes - let rawBuffer = malloc(bytesLength)! - defer { free(rawBuffer) } - _load_typed_array(jsObject.id, rawBuffer.assumingMemoryBound(to: UInt8.self)) - let length = lengthInBytes / MemoryLayout.size - let boundPtr = rawBuffer.bindMemory(to: Element.self, capacity: length) - let bufferPtr = UnsafeBufferPointer(start: boundPtr, count: length) - let result = try await body(bufferPtr) - return result - } + + #if compiler(>=5.5) + /// Calls the given async closure with a pointer to a copy of the underlying bytes of the + /// array's storage. + /// + /// - Note: The pointer passed as an argument to `body` is valid only for the + /// lifetime of the closure. Do not escape it from the async closure for later + /// use. + /// + /// - Parameter body: A closure with an `UnsafeBufferPointer` parameter + /// that points to the contiguous storage for the array. + /// If `body` has a return value, that value is also + /// used as the return value for the `withUnsafeBytes(_:)` method. The + /// argument is valid only for the duration of the closure's execution. + /// - Returns: The return value, if any, of the `body`async closure parameter. + @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) + public func withUnsafeBytesAsync(_ body: (UnsafeBufferPointer) async throws -> R) async rethrows -> R { + let bytesLength = lengthInBytes + let rawBuffer = malloc(bytesLength)! + defer { free(rawBuffer) } + _load_typed_array(jsObject.id, rawBuffer.assumingMemoryBound(to: UInt8.self)) + let length = lengthInBytes / MemoryLayout.size + let boundPtr = rawBuffer.bindMemory(to: Element.self, capacity: length) + let bufferPtr = UnsafeBufferPointer(start: boundPtr, count: length) + let result = try await body(bufferPtr) + return result + } + #endif } // MARK: - Int and UInt support