StikDebug/StikJIT/JSSupport/RunJSView.swift

86 lines
2.6 KiB
Swift

//
// RunJSView.swift
// StikJIT
//
// Created by s s on 2025/4/24.
//
import SwiftUI
import JavaScriptCore
class RunJSViewModel : ObservableObject {
var context: JSContext?
@Published var logs: [String] = []
@Published var scriptName: String = "Script"
@Published var executionInterrupted = false
var pid: Int
var debugProxy: OpaquePointer?
var semaphore: dispatch_semaphore_t?
init(pid: Int, debugProxy: OpaquePointer?, semaphore: dispatch_semaphore_t?) {
self.pid = pid
self.debugProxy = debugProxy
self.semaphore = semaphore
}
func runScript(path: URL) throws {
let scriptContent = try String(contentsOf: path, encoding: .utf8)
scriptName = path.lastPathComponent
let getPidFunction: @convention(block) () -> Int = {
return self.pid
}
let sendCommandFunction: @convention(block) (String?) -> String? = { commandStr in
guard let commandStr else {
self.context?.exception = JSValue(object: "Command should not be nil.", in: self.context!)
return ""
}
if self.executionInterrupted {
self.context?.exception = JSValue(object: "Script execution is interrupted by StikDebug.", in: self.context!)
return ""
}
return handleJSContextSendDebugCommand(self.context, commandStr, self.debugProxy) ?? ""
}
let logFunction: @convention(block) (String) -> Void = { logStr in
DispatchQueue.main.async {
self.logs.append(logStr)
}
}
context = JSContext()
context?.setObject(getPidFunction, forKeyedSubscript: "get_pid" as NSString)
context?.setObject(sendCommandFunction, forKeyedSubscript: "send_command" as NSString)
context?.setObject(logFunction, forKeyedSubscript: "log" as NSString)
context?.evaluateScript(scriptContent)
if let semaphore {
semaphore.signal()
}
DispatchQueue.main.async {
if let exception = self.context?.exception {
self.logs.append(exception.debugDescription)
}
self.logs.append("Script Execution Completed.")
}
}
}
struct RunJSView : View {
@ObservedObject var model : RunJSViewModel
@State var webViewShow = false
var body: some View {
List {
ForEach(model.logs, id: \.self) { logStr in
Text(logStr)
}
}
.navigationTitle("Running \(model.scriptName)")
}
}