commit 86cc8238efd26c1d08703ce077162075e63b9763
parent 19a0ab8398c9c8fd2ddb6dce8afcc3bc24375d11
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Mon, 18 Sep 2023 00:03:12 +0200
feat(scripting): static class type
Diffstat:
4 files changed, 40 insertions(+), 16 deletions(-)
diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/scripting/RemoteScriptManager.kt b/app/src/main/kotlin/me/rhunk/snapenhance/scripting/RemoteScriptManager.kt
@@ -12,7 +12,7 @@ import java.io.InputStream
class RemoteScriptManager(
private val context: RemoteSideContext,
) : IScripting.Stub() {
- val runtime = ScriptRuntime(context.log)
+ val runtime = ScriptRuntime(context.log, context.androidContext.classLoader)
private val reloadListeners = mutableListOf<ReloadListener>()
private val cachedModuleInfo = mutableMapOf<String, ModuleInfo>()
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/scripting/JSModule.kt b/core/src/main/kotlin/me/rhunk/snapenhance/scripting/JSModule.kt
@@ -9,12 +9,13 @@ import org.mozilla.javascript.Function
import org.mozilla.javascript.NativeJavaObject
import org.mozilla.javascript.ScriptableObject
import org.mozilla.javascript.Undefined
+import java.lang.reflect.Modifier
class JSModule(
+ val scriptRuntime: ScriptRuntime,
val moduleInfo: ModuleInfo,
val content: String,
) {
- lateinit var logger: AbstractLogger
private lateinit var moduleObject: ScriptableObject
fun load(block: ScriptableObject.() -> Unit) {
@@ -50,8 +51,39 @@ class JSModule(
field.get(obj.unwrap())
}
+ moduleObject.putFunction("findClass") {
+ val className = it?.get(0).toString()
+ scriptRuntime.classLoader.loadClass(className)
+ }
+
+ moduleObject.putFunction("type") { args ->
+ val className = args?.get(0).toString()
+ val clazz = scriptRuntime.classLoader.loadClass(className)
+
+ scriptableObject("JavaClassWrapper") {
+ putFunction("newInstance") newInstance@{ args ->
+ val constructor = clazz.declaredConstructors.find {
+ it.parameterCount == (args?.size ?: 0)
+ } ?: return@newInstance Undefined.instance
+ constructor.newInstance(*args ?: emptyArray())
+ }
+
+ clazz.declaredMethods.forEach { method ->
+ method.isAccessible = true
+ putFunction(method.name) { args ->
+ args?.also { method.invoke(null, *it) } ?: method.invoke(null)
+ }
+ }
+
+ clazz.declaredFields.filter { Modifier.isStatic(it.modifiers) }.forEach { field ->
+ field.isAccessible = true
+ defineProperty(field.name, { field.get(null)}, { value -> field.set(null, value) }, 0)
+ }
+ }
+ }
+
moduleObject.putFunction("logInfo") { args ->
- logger.info(args?.joinToString(" ") ?: "")
+ scriptRuntime.logger.info(args?.joinToString(" ") ?: "")
Undefined.instance
}
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/scripting/ScriptRuntime.kt b/core/src/main/kotlin/me/rhunk/snapenhance/scripting/ScriptRuntime.kt
@@ -8,7 +8,8 @@ import java.io.ByteArrayInputStream
import java.io.InputStream
open class ScriptRuntime(
- protected val logger: AbstractLogger,
+ val logger: AbstractLogger,
+ val classLoader: ClassLoader,
) {
var buildModuleObject: ScriptableObject.(JSModule) -> Unit = {}
private val modules = mutableMapOf<String, JSModule>()
@@ -72,10 +73,10 @@ open class ScriptRuntime(
logger.info("Loading module $path")
return runCatching {
JSModule(
+ scriptRuntime = this,
moduleInfo = readModuleInfo(ByteArrayInputStream(content.toByteArray(Charsets.UTF_8)).bufferedReader()),
content = content,
).apply {
- logger = this@ScriptRuntime.logger
load {
buildModuleObject(this, this@apply)
}
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/scripting/core/CoreScriptRuntime.kt b/core/src/main/kotlin/me/rhunk/snapenhance/scripting/core/CoreScriptRuntime.kt
@@ -8,14 +8,11 @@ import me.rhunk.snapenhance.scripting.IPCInterface
import me.rhunk.snapenhance.scripting.Listener
import me.rhunk.snapenhance.scripting.ScriptRuntime
import me.rhunk.snapenhance.scripting.core.impl.ScriptHooker
-import me.rhunk.snapenhance.scripting.ktx.putFunction
class CoreScriptRuntime(
logger: AbstractLogger,
- private val classLoader: ClassLoader
-): ScriptRuntime(logger) {
- private lateinit var ipcInterface: IPCInterface
-
+ classLoader: ClassLoader,
+): ScriptRuntime(logger, classLoader) {
private val scriptHookers = mutableListOf<ScriptHooker>()
fun connect(scriptingInterface: IScripting) {
@@ -48,18 +45,12 @@ class CoreScriptRuntime(
sendIPCMessage(channel, eventName, args)
}
})
- putFunction("findClass") {
- val className = it?.get(0).toString()
- classLoader.loadClass(className)
- }
putConst("hooker", this, ScriptHooker(module.moduleInfo, logger, classLoader).also {
scriptHookers.add(it)
})
}
}
-
-
scriptingInterface.enabledScripts.forEach { path ->
runCatching {
load(path, scriptingInterface.getScriptContent(path))