This commit is contained in:
Horis
2024-03-08 09:55:39 +08:00
parent 2cda94547e
commit f3be1c36b8
11 changed files with 105 additions and 7 deletions
@@ -6,6 +6,7 @@ package com.script
import org.mozilla.javascript.Scriptable
import java.io.Reader
import java.io.StringReader
import kotlin.coroutines.CoroutineContext
abstract class AbstractScriptEngine(val bindings: Bindings? = null) : ScriptEngine {
@@ -64,6 +65,10 @@ abstract class AbstractScriptEngine(val bindings: Bindings? = null) : ScriptEngi
return this.eval(reader, getRuntimeScope(context))
}
override fun eval(script: String, scope: Scriptable, coroutineContext: CoroutineContext?): Any? {
return this.eval(StringReader(script), scope, coroutineContext)
}
@Throws(ScriptException::class)
override fun eval(reader: Reader, bindings: Bindings): Any? {
return this.eval(reader, getScriptContext(bindings))
@@ -5,6 +5,7 @@ package com.script
import org.mozilla.javascript.Scriptable
import java.io.Reader
import kotlin.coroutines.CoroutineContext
interface ScriptEngine {
var context: ScriptContext
@@ -14,14 +15,20 @@ interface ScriptEngine {
@Throws(ScriptException::class)
fun eval(reader: Reader, scope: Scriptable): Any?
@Throws(ScriptException::class)
fun eval(reader: Reader, scope: Scriptable, coroutineContext: CoroutineContext?): Any?
@Throws(ScriptException::class)
suspend fun evalSuspend(reader: Reader, scope: Scriptable): Any?
@Throws(ScriptException::class)
fun eval(script: String, scope: Scriptable): Any?
@Throws(ScriptException::class)
suspend fun evalSuspend(script: String, scope: Scriptable): Any?
@Throws(ScriptException::class)
fun eval(script: String, scope: Scriptable): Any?
fun eval(script: String, scope: Scriptable, coroutineContext: CoroutineContext?): Any?
@Throws(ScriptException::class)
fun eval(reader: Reader): Any?
@@ -0,0 +1,22 @@
package com.script.rhino
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.ensureActive
import org.mozilla.javascript.Context
import org.mozilla.javascript.ContextFactory
import kotlin.coroutines.CoroutineContext
class RhinoContext(factory: ContextFactory) : Context(factory) {
var coroutineContext: CoroutineContext? = null
@Throws(RhinoInterruptError::class)
fun ensureActive() {
try {
coroutineContext?.ensureActive()
} catch (e: CancellationException) {
throw RhinoInterruptError(e)
}
}
}
@@ -0,0 +1,3 @@
package com.script.rhino
class RhinoInterruptError(override val cause: Throwable) : Error()
@@ -35,6 +35,7 @@ import java.io.StringReader
import java.lang.reflect.Method
import java.security.*
import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
/**
@@ -84,6 +85,38 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
return unwrapReturnValue(ret)
}
override fun eval(
reader: Reader,
scope: Scriptable,
coroutineContext: CoroutineContext?
): Any? {
val cx = Context.enter()
if (cx is RhinoContext) {
cx.coroutineContext = coroutineContext
}
val ret: Any?
try {
var filename = this["javax.script.filename"] as? String
filename = filename ?: "<Unknown source>"
ret = cx.evaluateReader(scope, reader, filename, 1, null)
} catch (re: RhinoException) {
val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
val msg: String = if (re is JavaScriptException) {
re.value.toString()
} else {
re.toString()
}
val se = ScriptException(msg, re.sourceName(), line)
se.initCause(re)
throw se
} catch (var14: IOException) {
throw ScriptException(var14)
} finally {
Context.exit()
}
return unwrapReturnValue(ret)
}
@Throws(ContinuationPending::class)
override suspend fun evalSuspend(reader: Reader, scope: Scriptable): Any? {
val cx = Context.enter()
@@ -259,11 +292,12 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
ContextFactory.initGlobal(object : ContextFactory() {
override fun makeContext(): Context {
val cx = super.makeContext()
val cx = RhinoContext(this)
cx.languageVersion = 200
cx.optimizationLevel = -1
cx.setClassShutter(RhinoClassShutter)
cx.wrapFactory = RhinoWrapFactory
cx.instructionObserverThreshold = 10000
return cx
}
@@ -275,6 +309,12 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
}
}
override fun observeInstructionCount(cx: Context, instructionCount: Int) {
if (cx is RhinoContext) {
cx.ensureActive()
}
}
override fun doTopCall(
callable: Callable,
cx: Context,
@@ -308,7 +348,11 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
thisObj: Scriptable?,
args: Array<Any>
): Any? {
return super.doTopCall(callable, cx, scope, thisObj, args)
try {
return super.doTopCall(callable, cx, scope, thisObj, args)
} catch (e: RhinoInterruptError) {
throw e.cause
}
}
})