This commit is contained in:
Horis
2025-03-30 16:42:42 +08:00
parent 8320ff9e20
commit d92b69f7fa
5 changed files with 39 additions and 52 deletions
@@ -13,10 +13,14 @@ abstract class CompiledScript {
abstract fun getEngine(): ScriptEngine abstract fun getEngine(): ScriptEngine
@Throws(ScriptException::class) @Throws(ScriptException::class)
abstract fun eval(context: ScriptContext): Any? fun eval(context: ScriptContext): Any? {
return eval(getEngine().getRuntimeScope(context))
}
@Throws(ScriptException::class) @Throws(ScriptException::class)
abstract fun eval(scope: Scriptable): Any? fun eval(scope: Scriptable): Any? {
return eval(scope, null)
}
@Throws(ScriptException::class) @Throws(ScriptException::class)
abstract fun eval(scope: Scriptable, coroutineContext: CoroutineContext?): Any? abstract fun eval(scope: Scriptable, coroutineContext: CoroutineContext?): Any?
@@ -25,12 +25,17 @@
package com.script.rhino package com.script.rhino
import com.script.CompiledScript import com.script.CompiledScript
import com.script.ScriptContext
import com.script.ScriptEngine import com.script.ScriptEngine
import com.script.ScriptException import com.script.ScriptException
import kotlinx.coroutines.Job
import kotlinx.coroutines.asContextElement import kotlinx.coroutines.asContextElement
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.mozilla.javascript.* import org.mozilla.javascript.Context
import org.mozilla.javascript.ContinuationPending
import org.mozilla.javascript.JavaScriptException
import org.mozilla.javascript.RhinoException
import org.mozilla.javascript.Script
import org.mozilla.javascript.Scriptable
import java.io.IOException import java.io.IOException
import kotlin.coroutines.Continuation import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@@ -51,56 +56,15 @@ internal class RhinoCompiledScript(
return engine return engine
} }
@Throws(ScriptException::class)
override fun eval(context: ScriptContext): Any? {
val cx = Context.enter()
val result: Any?
try {
val scope = engine.getRuntimeScope(context)
val ret = script.exec(cx, scope)
result = engine.unwrapReturnValue(ret)
} 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
} finally {
Context.exit()
}
return result
}
override fun eval(scope: Scriptable): Any? {
val cx = Context.enter()
val result: Any?
try {
val ret = script.exec(cx, scope)
result = engine.unwrapReturnValue(ret)
} 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
} finally {
Context.exit()
}
return result
}
override fun eval(scope: Scriptable, coroutineContext: CoroutineContext?): Any? { override fun eval(scope: Scriptable, coroutineContext: CoroutineContext?): Any? {
val cx = Context.enter() as RhinoContext val cx = Context.enter() as RhinoContext
cx.checkRecursive()
val previousCoroutineContext = cx.coroutineContext val previousCoroutineContext = cx.coroutineContext
cx.coroutineContext = coroutineContext if (coroutineContext != null && coroutineContext[Job] != null) {
cx.coroutineContext = coroutineContext
}
cx.allowScriptRun = true
cx.recursiveCount++
val result: Any? val result: Any?
try { try {
val ret = script.exec(cx, scope) val ret = script.exec(cx, scope)
@@ -117,6 +81,8 @@ internal class RhinoCompiledScript(
throw se throw se
} finally { } finally {
cx.coroutineContext = previousCoroutineContext cx.coroutineContext = previousCoroutineContext
cx.allowScriptRun = false
cx.recursiveCount--
Context.exit() Context.exit()
} }
return result return result
@@ -10,6 +10,7 @@ class RhinoContext(factory: ContextFactory) : Context(factory) {
var coroutineContext: CoroutineContext? = null var coroutineContext: CoroutineContext? = null
var allowScriptRun = false var allowScriptRun = false
var recursiveCount = 0
@Throws(RhinoInterruptError::class) @Throws(RhinoInterruptError::class)
fun ensureActive() { fun ensureActive() {
@@ -20,4 +21,11 @@ class RhinoContext(factory: ContextFactory) : Context(factory) {
} }
} }
@Throws(RhinoRecursionError::class)
fun checkRecursive() {
if (recursiveCount >= 10) {
throw RhinoRecursionError()
}
}
} }
@@ -1,3 +1,5 @@
package com.script.rhino package com.script.rhino
class RhinoInterruptError(override val cause: Throwable) : Error() class RhinoInterruptError(override val cause: Throwable) : Error()
class RhinoRecursionError(): Error("Maximum recursion depth exceeded.")
@@ -33,6 +33,7 @@ import com.script.ScriptBindings
import com.script.ScriptContext import com.script.ScriptContext
import com.script.ScriptException import com.script.ScriptException
import com.script.SimpleBindings import com.script.SimpleBindings
import kotlinx.coroutines.Job
import kotlinx.coroutines.asContextElement import kotlinx.coroutines.asContextElement
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.mozilla.javascript.Callable import org.mozilla.javascript.Callable
@@ -92,11 +93,13 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
coroutineContext: CoroutineContext? coroutineContext: CoroutineContext?
): Any? { ): Any? {
val cx = Context.enter() as RhinoContext val cx = Context.enter() as RhinoContext
cx.checkRecursive()
val previousCoroutineContext = cx.coroutineContext val previousCoroutineContext = cx.coroutineContext
if (coroutineContext != null) { if (coroutineContext != null && coroutineContext[Job] != null) {
cx.coroutineContext = coroutineContext cx.coroutineContext = coroutineContext
} }
cx.allowScriptRun = true cx.allowScriptRun = true
cx.recursiveCount++
val ret: Any? val ret: Any?
try { try {
var filename = this["javax.script.filename"] as? String var filename = this["javax.script.filename"] as? String
@@ -117,6 +120,7 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
} finally { } finally {
cx.coroutineContext = previousCoroutineContext cx.coroutineContext = previousCoroutineContext
cx.allowScriptRun = false cx.allowScriptRun = false
cx.recursiveCount--
Context.exit() Context.exit()
} }
return unwrapReturnValue(ret) return unwrapReturnValue(ret)
@@ -125,9 +129,11 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
@Throws(ContinuationPending::class) @Throws(ContinuationPending::class)
override suspend fun evalSuspend(reader: Reader, scope: Scriptable): Any? { override suspend fun evalSuspend(reader: Reader, scope: Scriptable): Any? {
val cx = Context.enter() as RhinoContext val cx = Context.enter() as RhinoContext
cx.checkRecursive()
var ret: Any? var ret: Any?
withContext(VMBridgeReflect.contextLocal.asContextElement()) { withContext(VMBridgeReflect.contextLocal.asContextElement()) {
cx.allowScriptRun = true cx.allowScriptRun = true
cx.recursiveCount++
try { try {
var filename = this@RhinoScriptEngine["javax.script.filename"] as? String var filename = this@RhinoScriptEngine["javax.script.filename"] as? String
filename = filename ?: "<Unknown source>" filename = filename ?: "<Unknown source>"
@@ -166,6 +172,7 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
throw ScriptException(var14) throw ScriptException(var14)
} finally { } finally {
cx.allowScriptRun = false cx.allowScriptRun = false
cx.recursiveCount--
Context.exit() Context.exit()
} }
} }