Skip to content

Commit 304116e

Browse files
Add JavaScriptFoundationCompat module to provide utilities to interact Foundation types
1 parent 233d6b2 commit 304116e

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

Package.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,18 @@ let package = Package(
106106
"JavaScriptEventLoopTestSupport",
107107
]
108108
),
109+
.target(
110+
name: "JavaScriptFoundationCompat",
111+
dependencies: [
112+
"JavaScriptKit"
113+
]
114+
),
115+
.testTarget(
116+
name: "JavaScriptFoundationCompatTests",
117+
dependencies: [
118+
"JavaScriptFoundationCompat"
119+
]
120+
),
109121
.plugin(
110122
name: "PackageToJS",
111123
capability: .command(
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import Foundation
2+
import JavaScriptKit
3+
4+
/// Data <-> Uint8Array conversion. The conversion is lossless and copies the bytes at most once per conversion
5+
extension Data: ConvertibleToJSValue, ConstructibleFromJSValue {
6+
/// Convert a Data to a JSValue.
7+
///
8+
/// - Returns: A Uint8Array that contains the bytes of the Data.
9+
public var jsValue: JSValue {
10+
self.withUnsafeBytes { buffer in
11+
return JSTypedArray<UInt8>(buffer: buffer.bindMemory(to: UInt8.self)).jsValue
12+
}
13+
}
14+
15+
/// Construct a Data from a JSValue.
16+
///
17+
/// - Parameter jsValue: The JSValue to construct a Data from.
18+
/// - Returns: A Data, if the JSValue is a Uint8Array.
19+
public static func construct(from jsValue: JSValue) -> Data? {
20+
guard let uint8Array = JSTypedArray<UInt8>(from: jsValue) else {
21+
// If the JSValue is not a Uint8Array, fail.
22+
return nil
23+
}
24+
// First, allocate the data storage
25+
var data = Data(count: uint8Array.lengthInBytes)
26+
// Then, copy the byte contents into the Data buffer
27+
data.withUnsafeMutableBytes { destinationBuffer in
28+
uint8Array.copyMemory(to: destinationBuffer.bindMemory(to: UInt8.self))
29+
}
30+
return data
31+
}
32+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import XCTest
2+
import Foundation
3+
import JavaScriptFoundationCompat
4+
import JavaScriptKit
5+
6+
final class DataJSValueTests: XCTestCase {
7+
func testDataToJSValue() {
8+
let data = Data([0x00, 0x01, 0x02, 0x03])
9+
let jsValue = data.jsValue
10+
11+
let uint8Array = JSTypedArray<UInt8>(from: jsValue)
12+
XCTAssertEqual(uint8Array?.lengthInBytes, 4)
13+
XCTAssertEqual(uint8Array?[0], 0x00)
14+
XCTAssertEqual(uint8Array?[1], 0x01)
15+
XCTAssertEqual(uint8Array?[2], 0x02)
16+
XCTAssertEqual(uint8Array?[3], 0x03)
17+
}
18+
19+
func testJSValueToData() {
20+
let jsValue = JSTypedArray<UInt8>([0x00, 0x01, 0x02, 0x03]).jsValue
21+
let data = Data.construct(from: jsValue)
22+
XCTAssertEqual(data, Data([0x00, 0x01, 0x02, 0x03]))
23+
}
24+
25+
func testDataToJSValue_withLargeData() {
26+
let data = Data(repeating: 0x00, count: 1024 * 1024)
27+
let jsValue = data.jsValue
28+
let uint8Array = JSTypedArray<UInt8>(from: jsValue)
29+
XCTAssertEqual(uint8Array?.lengthInBytes, 1024 * 1024)
30+
}
31+
32+
func testJSValueToData_withLargeData() {
33+
let jsValue = JSTypedArray<UInt8>(Array(repeating: 0x00, count: 1024 * 1024)).jsValue
34+
let data = Data.construct(from: jsValue)
35+
XCTAssertEqual(data?.count, 1024 * 1024)
36+
}
37+
38+
func testDataToJSValue_withEmptyData() {
39+
let data = Data()
40+
let jsValue = data.jsValue
41+
let uint8Array = JSTypedArray<UInt8>(from: jsValue)
42+
XCTAssertEqual(uint8Array?.lengthInBytes, 0)
43+
}
44+
45+
func testJSValueToData_withEmptyData() {
46+
let jsValue = JSTypedArray<UInt8>([]).jsValue
47+
let data = Data.construct(from: jsValue)
48+
XCTAssertEqual(data, Data())
49+
}
50+
51+
func testJSValueToData_withInvalidJSValue() {
52+
let data = Data.construct(from: JSObject().jsValue)
53+
XCTAssertNil(data)
54+
}
55+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy