Skip to content
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

Add JSTypedArray.init(buffer:) initializer #314

Merged
merged 1 commit into from
Mar 25, 2025
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
24 changes: 18 additions & 6 deletions Sources/JavaScriptKit/BasicObjects/JSTypedArray.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,32 @@ public class JSTypedArray<Element>: JSBridgedClass, ExpressibleByArrayLiteral wh
///
/// - Parameter array: The array that will be copied to create a new instance of TypedArray
public convenience init(_ array: [Element]) {
let jsArrayRef = array.withUnsafeBufferPointer { ptr in
// Retain the constructor function to avoid it being released before calling `swjs_create_typed_array`
withExtendedLifetime(Self.constructor!) { ctor in
swjs_create_typed_array(ctor.id, ptr.baseAddress, Int32(array.count))
}
let object = array.withUnsafeBufferPointer { buffer in
Self.createTypedArray(from: buffer)
}
self.init(unsafelyWrapping: JSObject(id: jsArrayRef))
self.init(unsafelyWrapping: object)
}

/// Convenience initializer for `Sequence`.
public convenience init<S: Sequence>(_ sequence: S) where S.Element == Element {
self.init(Array(sequence))
}

/// Initialize a new instance of TypedArray in JavaScript environment with given buffer contents.
///
/// - Parameter buffer: The buffer that will be copied to create a new instance of TypedArray
public convenience init(buffer: UnsafeBufferPointer<Element>) {
self.init(unsafelyWrapping: Self.createTypedArray(from: buffer))
}

private static func createTypedArray(from buffer: UnsafeBufferPointer<Element>) -> JSObject {
// Retain the constructor function to avoid it being released before calling `swjs_create_typed_array`
let jsArrayRef = withExtendedLifetime(Self.constructor!) { ctor in
swjs_create_typed_array(ctor.id, buffer.baseAddress, Int32(buffer.count))
}
return JSObject(id: jsArrayRef)
}

/// Length (in bytes) of the typed array.
/// The value is established when a TypedArray is constructed and cannot be changed.
/// If the TypedArray is not specifying a `byteOffset` or a `length`, the `length` of the referenced `ArrayBuffer` will be returned.
Expand Down
12 changes: 12 additions & 0 deletions Tests/JavaScriptKitTests/JSTypedArrayTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,16 @@ final class JSTypedArrayTests: XCTestCase {

XCTAssertEqual(toString(array.jsValue.object!), jsStringify(Array(0..<100)))
}

func testInitWithBufferPointer() {
let buffer = UnsafeMutableBufferPointer<Float32>.allocate(capacity: 20)
defer { buffer.deallocate() }
for i in 0..<20 {
buffer[i] = Float32(i)
}
let typedArray = JSTypedArray<Float32>(buffer: UnsafeBufferPointer(buffer))
for i in 0..<20 {
XCTAssertEqual(typedArray[i], Float32(i))
}
}
}