feat(scripting): static class type

This commit is contained in:
rhunk
2023-09-18 00:03:12 +02:00
parent 19a0ab8398
commit 86cc8238ef
4 changed files with 40 additions and 16 deletions

View File

@ -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
}

View File

@ -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)
}

View File

@ -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))