bern-script 0.1.0

Target-selected JavaScript contexts for Bern applications
Documentation
import AppKit
struct BernBuffer { var ptr: UnsafeMutablePointer<UInt8>?; var len: Int; var capacity: Int }
@MainActor var sent = false
@MainActor var replies: [String: Any] = [:]
@MainActor func bern_script_start() {}
@MainActor func bern_script_stop() {}
@MainActor func bern_script_poll(_ now: Double) -> BernBuffer {
    if sent { return BernBuffer(ptr: nil, len: 0, capacity: 0) }
    sent = true
    let requests: [[String: Any]] = [
        ["id": "1", "context": "a", "source": "var count = 1; ++count"],
        ["id": "2", "context": "a", "source": "++count"],
        ["id": "3", "context": "b", "source": "typeof count"],
        ["id": "4", "context": "a", "source": "Promise.resolve({items:[1,true,null]})"],
        ["id": "5", "context": "a", "source": "throw new Error('broken')"]
    ]
    let data = try! JSONSerialization.data(withJSONObject: requests)
    let ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
    data.copyBytes(to: ptr, count: data.count)
    return BernBuffer(ptr: ptr, len: data.count, capacity: data.count)
}
func bern_buffer_free(_ buffer: BernBuffer) { buffer.ptr?.deallocate() }
@MainActor func bern_script_complete(_ ptr: UnsafePointer<UInt8>?, _ len: Int) {
    let data = Data(bytes: ptr!, count: len)
    let result = try! JSONSerialization.jsonObject(with: data) as! [String: Any]
    replies[result["id"] as! String] = result
}

/*bern:host*/

@main struct Test {
    @MainActor static func main() {
        _ = NSApplication.shared
        BernScriptHost.shared.start()
        let deadline = Date().addingTimeInterval(20)
        while replies.count < 5 && Date() < deadline { RunLoop.current.run(until: Date().addingTimeInterval(0.01)) }
        BernScriptHost.shared.stop()
        precondition(replies.count == 5, "missing replies: \(replies)")
        precondition((replies["1"] as! [String: Any])["value"] as? Int == 2)
        precondition((replies["2"] as! [String: Any])["value"] as? Int == 3)
        precondition((replies["3"] as! [String: Any])["value"] as? String == "undefined")
        precondition((replies["5"] as! [String: Any])["error"] as? String == "Error: broken")
        print("WKWebView: persistent globals, separate contexts, JSON, Promise, error: passed")
    }
}