diff --git a/FreeAPS/Sources/APS/OpenAPS/JavaScriptWorker.swift b/FreeAPS/Sources/APS/OpenAPS/JavaScriptWorker.swift index 66991b2b6..d0829319e 100644 --- a/FreeAPS/Sources/APS/OpenAPS/JavaScriptWorker.swift +++ b/FreeAPS/Sources/APS/OpenAPS/JavaScriptWorker.swift @@ -3,10 +3,32 @@ import JavaScriptCore private let contextLock = NSRecursiveLock() +extension String { + var lowercasingFirst: String { prefix(1).lowercased() + dropFirst() } + var uppercasingFirst: String { prefix(1).uppercased() + dropFirst() } + var camelCased: String { + guard !isEmpty else { return "" } + let parts = components(separatedBy: .alphanumerics.inverted) + let first = parts.first!.lowercasingFirst + let rest = parts.dropFirst().map(\.uppercasingFirst) + return ([first] + rest).joined() + } + + var pascalCased: String { + guard !isEmpty else { return "" } + let parts = components(separatedBy: .alphanumerics.inverted) + let first = parts.first!.uppercasingFirst + let rest = parts.dropFirst().map(\.uppercasingFirst) + return ([first] + rest).joined() + } +} + final class JavaScriptWorker { private let processQueue = DispatchQueue(label: "DispatchQueue.JavaScriptWorker") private let virtualMachine: JSVirtualMachine @SyncAccess(lock: contextLock) private var commonContext: JSContext? = nil + private var consoleLogs: [String] = [] + private var logContext: String = "" init() { virtualMachine = processQueue.sync { JSVirtualMachine()! } @@ -20,9 +42,11 @@ final class JavaScriptWorker { } } let consoleLog: @convention(block) (String) -> Void = { message in - debug(.openAPS, "JavaScript log: \(message)") + let trimmedMessage = message.trimmingCharacters(in: .whitespacesAndNewlines) + if !trimmedMessage.isEmpty { + self.consoleLogs.append("\(trimmedMessage)") + } } - context.setObject( consoleLog, forKeyedSubscript: "_consoleLog" as NSString @@ -30,8 +54,37 @@ final class JavaScriptWorker { return context } + // New method to flush aggregated logs + private func outputLogs() { + var outputLogs = consoleLogs.joined(separator: "\n").trimmingCharacters(in: .whitespacesAndNewlines) + consoleLogs.removeAll() + + if outputLogs.isEmpty { return } + + if logContext == "autosens.js" { + outputLogs = outputLogs.split(separator: "\n").map { logLine in + logLine.replacingOccurrences( + of: "^[-+=x!]|u\\(|\\)|\\d{1,2}h$", + with: "", + options: .regularExpression + ) + }.joined(separator: "\n") + } + + if !outputLogs.isEmpty { + outputLogs.split(separator: "\n").forEach { logLine in + if !"\(logLine)".trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + debug(.openAPS, "\(logContext): \(logLine)") + } + } + } + } + @discardableResult func evaluate(script: Script) -> JSValue! { - evaluate(string: script.body) + logContext = URL(fileURLWithPath: script.name).lastPathComponent + let result = evaluate(string: script.body) + outputLogs() + return result } private func evaluate(string: String) -> JSValue! { @@ -52,6 +105,7 @@ final class JavaScriptWorker { commonContext = createContext() defer { commonContext = nil + outputLogs() } return execute(self) } diff --git a/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift b/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift index 5aefb7929..4d3c5e54e 100644 --- a/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift +++ b/FreeAPS/Sources/APS/OpenAPS/OpenAPS.swift @@ -635,11 +635,11 @@ final class OpenAPS { private func middlewareScript(name: String) -> Script? { if let body = storage.retrieveRaw(name) { - return Script(name: "Middleware", body: body) + return Script(name: name, body: body) } if let url = Foundation.Bundle.main.url(forResource: "javascript/\(name)", withExtension: "") { - return Script(name: "Middleware", body: try! String(contentsOf: url)) + return Script(name: name, body: try! String(contentsOf: url)) } return nil