| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- import Foundation
- import JavaScriptCore
- private let contextLock = NSRecursiveLock()
- final class JavaScriptWorker {
- private let processQueue = DispatchQueue(label: "DispatchQueue.JavaScriptWorker")
- private let virtualMachine: JSVirtualMachine
- @SyncAccess(lock: contextLock) private var commonContext: JSContext? = nil
- init() {
- virtualMachine = processQueue.sync { JSVirtualMachine()! }
- }
- private func createContext() -> JSContext {
- let context = JSContext(virtualMachine: virtualMachine)!
- context.exceptionHandler = { _, exception in
- if let error = exception?.toString() {
- print(error)
- }
- }
- return context
- }
- @discardableResult func evaluate(script: Script) -> JSValue! {
- evaluate(string: script.body)
- }
- private func evaluate(string: String) -> JSValue! {
- let ctx = commonContext ?? createContext()
- return ctx.evaluateScript(string)
- }
- private func json(for string: String) -> JSON {
- evaluate(string: "JSON.stringify(\(string));")!.toString()!
- }
- func call(function: String, with arguments: [JSON]) -> JSON {
- let joined = arguments.map(\.string).joined(separator: ",")
- return json(for: "\(function)(\(joined))")
- }
- func inCommonContext<Value>(execute: (JavaScriptWorker) -> Value) -> Value {
- commonContext = createContext()
- defer {
- commonContext = nil
- }
- return execute(self)
- }
- }
|