Search code examples
iosswiftcocoa-touchjavascriptcore

JavaScriptCore doesn't work anything else than 'hello, world'


I'm currently writing a Bitcoin-related app in Swift. As there are no native libraries for BIP32/39 available, I decided to go with js ones using JavaScriptCore.

The problem is, almost everything outputs undefined in Swift, e.g.:

var pip_buffer = new Uint8Array(strength / 8);

This one works:

var pip_buffer = "Hello, world"

Here's my Swift code:

var context: JSContext?

private func initJS() {
    context = JSContext()
    if let jsSrcPath = Bundle.main.path(forResource: "script", ofType: "js") {
        do {
            let jsSrcContents = try String(contentsOfFile: jsSrcPath)
            _ = context?.evaluateScript(jsSrcContents)
        } catch let error {
            print(error.localizedDescription)
        }
    }
}

private func getJSVar(name: String) {
    if let vb = context?.objectForKeyedSubscript(name) {
        print("\(vb)")
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    initJS()
    getJSVar(name: "pip_buffer")
}

How to make this thing work?


Solution

  • Looking at JSValue API Doc I don't see any reference to Uint8Array, which probably means that JavaScriptCore can't convert Uint8Array to a "Swift" value.

    You can use Array.from(pip_buffer) on the JS side to convert your Uint8Array to a regular number array, which works.

    e.g.

        if let vb = context?.evaluateScript("Array.from(pip_buffer)") {
            print("\(vb)")
        }
    

    Once converted a regular JS number array, you can also use JSValue.toArray() (Swift side), to get it as an array (and can also use toNumber(), toInt32() or toUInt32(), for each item in the array).