diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/IRemoteIPC.kt b/app/src/main/kotlin/me/rhunk/snapenhance/scripting/IRemoteIPC.kt index fc110d35..76010dd2 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/IRemoteIPC.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/scripting/IRemoteIPC.kt @@ -1,13 +1,19 @@ package me.rhunk.snapenhance.scripting -class IRemoteIPC : IPCInterface { - private val listeners = mutableMapOf>() +import java.util.concurrent.ConcurrentHashMap + +class IRemoteIPC : IPCInterface() { + private val listeners = ConcurrentHashMap>() + + fun removeListener(eventName: String, listener: Listener) { + listeners[eventName]?.remove(listener) + } override fun on(eventName: String, listener: Listener) { listeners.getOrPut(eventName) { mutableSetOf() }.add(listener) } override fun emit(eventName: String, args: Array) { - listeners[eventName]?.forEach { it(args) } + listeners[eventName]?.toList()?.forEach { it(args) } } } \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/RemoteScriptManager.kt b/app/src/main/kotlin/me/rhunk/snapenhance/scripting/RemoteScriptManager.kt index b08937d6..e057748c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/RemoteScriptManager.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/scripting/RemoteScriptManager.kt @@ -1,6 +1,7 @@ package me.rhunk.snapenhance.scripting import android.net.Uri +import android.os.DeadObjectException import androidx.documentfile.provider.DocumentFile import me.rhunk.snapenhance.RemoteSideContext import me.rhunk.snapenhance.bridge.scripting.IPCListener @@ -75,12 +76,24 @@ class RemoteScriptManager( } override fun registerIPCListener(eventName: String, listener: IPCListener) { - runtime.ipcManager.on(eventName) { args -> - listener.onMessage(args) - } + runtime.ipcManager.on(eventName, object: Listener { + override fun invoke(args: Array) { + try { + listener.onMessage(args) + } catch (e: DeadObjectException) { + (runtime.ipcManager as IRemoteIPC).removeListener(eventName, this) + } catch (t: Throwable) { + context.log.error("Failed to invoke $eventName", t) + } + } + }) } override fun sendIPCMessage(eventName: String, args: Array) { - runtime.ipcManager.emit(eventName, args) + runCatching { + runtime.ipcManager.emit(eventName, *args) + }.onFailure { + context.log.error("Failed to send message for $eventName", it) + } } } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt b/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt index 10dd3dbc..abd7e066 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/SnapEnhance.kt @@ -125,7 +125,7 @@ class SnapEnhance { } }) - scriptRuntime.ipcManager = object: IPCInterface { + scriptRuntime.ipcManager = object: IPCInterface() { override fun on(eventName: String, listener: Listener) { registerIPCListener(eventName, object: IPCListener.Stub() { override fun onMessage(args: Array) { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/scripting/IPCInterface.kt b/core/src/main/kotlin/me/rhunk/snapenhance/scripting/IPCInterface.kt index 12b4b782..040ce400 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/scripting/IPCInterface.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/scripting/IPCInterface.kt @@ -2,7 +2,10 @@ package me.rhunk.snapenhance.scripting typealias Listener = (Array) -> Unit -interface IPCInterface { - fun on(eventName: String, listener: Listener) - fun emit(eventName: String, args: Array) +abstract class IPCInterface { + abstract fun on(eventName: String, listener: Listener) + + abstract fun emit(eventName: String, vararg args: String?) + + fun emit(eventName: String) = emit(eventName, *emptyArray()) } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/scripting/ScriptRuntime.kt b/core/src/main/kotlin/me/rhunk/snapenhance/scripting/ScriptRuntime.kt index 8e48cbaa..f39f5534 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/scripting/ScriptRuntime.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/scripting/ScriptRuntime.kt @@ -13,7 +13,13 @@ class ScriptRuntime( private val modules = mutableMapOf() fun eachModule(f: JSModule.() -> Unit) { - modules.values.forEach(f) + modules.values.forEach { module -> + runCatching { + module.f() + }.onFailure { + logger.error("Failed to run module function in ${module.moduleInfo.name}", it) + } + } } private fun readModuleInfo(reader: BufferedReader): ModuleInfo {