-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
21962f5
commit ae20f78
Showing
5 changed files
with
122 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import Foundation | ||
import JavaScriptCore | ||
|
||
@objc public protocol BlobExports: JSExport { | ||
func text() -> JSValue? | ||
func arrayBuffer() -> JSValue | ||
} | ||
|
||
|
||
@objc class Blob: NSObject, BlobExports { | ||
var content: String | ||
|
||
weak var context: JSContext? | ||
|
||
init(content: String) { | ||
self.content = content | ||
} | ||
|
||
func text() -> JSValue? { | ||
guard let context = context else { | ||
fatalError("JSContext is nil") | ||
} | ||
|
||
return JSValue(newPromiseIn: context) { (resolve, reject) in | ||
let blobObject = JSValue(object: self.content, in: context)! | ||
resolve?.call(withArguments: [blobObject]) | ||
} | ||
} | ||
|
||
func arrayBuffer() -> JSValue { | ||
return JSValue(newPromiseIn: context) { [weak self] (resolve, reject) in | ||
guard let data = self?.content.data(using: .utf8) else { | ||
let errorDescription = "Failed to convert blob content to ArrayBuffer" | ||
reject?.call(withArguments: [errorDescription]) | ||
return | ||
} | ||
|
||
// Convert Data to [UInt8] | ||
let byteArray = [UInt8](data) | ||
|
||
// Convert [UInt8] to JavaScript ArrayBuffer | ||
let jsArrayBufferConstructor = self?.context?.evaluateScript("ArrayBuffer") | ||
let jsUint8ArrayConstructor = self?.context?.evaluateScript("Uint8Array") | ||
guard let arrayBuffer = jsArrayBufferConstructor?.construct(withArguments: [byteArray.count]), | ||
let uint8Array = jsUint8ArrayConstructor?.construct(withArguments: [arrayBuffer]) else { | ||
let errorDescription = "Failed to create ArrayBuffer" | ||
reject?.call(withArguments: [errorDescription]) | ||
return | ||
} | ||
|
||
// Set bytes to ArrayBuffer | ||
for (index, byte) in byteArray.enumerated() { | ||
uint8Array.setValue(byte, at: index) | ||
} | ||
|
||
resolve?.call(withArguments: [arrayBuffer]) | ||
} | ||
} | ||
} | ||
|
||
struct BlobAPI { | ||
func registerAPIInto(context: JSContext) { | ||
let blobClass: @convention(block) (String) -> Blob = { text in | ||
let blob = Blob(content: text) | ||
blob.context = context | ||
return blob | ||
} | ||
|
||
context.setObject( | ||
unsafeBitCast(blobClass, to: AnyObject.self), | ||
forKeyedSubscript: "Blob" as NSString | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import ECMASwift | ||
import XCTest | ||
import JavaScriptCore | ||
|
||
final class BlobAPITests: XCTestCase { | ||
let runtime = ECMASwift() | ||
|
||
func testBlobCreation() { | ||
let expectedContent = "Hello, World!" | ||
|
||
let blob = runtime.context.evaluateScript(""" | ||
Blob('\(expectedContent)'); | ||
""") | ||
|
||
XCTAssertNotNil(blob, "Blob creation failed") | ||
} | ||
|
||
func testBlobTextMethod() async { | ||
let expectedContent = "Hello, World!" | ||
_ = runtime.context.evaluateScript(""" | ||
async function getBlob() { | ||
let blob = new Blob(["\(expectedContent)"]) | ||
return await blob.text() | ||
} | ||
""") | ||
let result = try! await runtime.context.callAsyncFunction(key: "getBlob") | ||
XCTAssertEqual(result.toString(), expectedContent) | ||
} | ||
|
||
func testBlobArrayBufferMethod() async { | ||
let expectedContent = "Hello, World!" | ||
_ = runtime.context.evaluateScript(""" | ||
async function getBlob() { | ||
let blob = new Blob(["\(expectedContent)"]) | ||
let res = await blob.arrayBuffer() | ||
return res | ||
} | ||
""") | ||
let result = try! await runtime.context.callAsyncFunction(key: "getBlob") | ||
XCTAssertEqual(result.forProperty("byteLength").toNumber(), 13) | ||
} | ||
} |