Horis 1 год назад
Родитель
Сommit
74db2bca0f

+ 6 - 2
modules/rhino/src/main/java/com/script/CompiledScript.kt

@@ -13,10 +13,14 @@ abstract class CompiledScript {
     abstract fun getEngine(): ScriptEngine
 
     @Throws(ScriptException::class)
-    abstract fun eval(context: ScriptContext): Any?
+    fun eval(context: ScriptContext): Any? {
+        return eval(getEngine().getRuntimeScope(context))
+    }
 
     @Throws(ScriptException::class)
-    abstract fun eval(scope: Scriptable): Any?
+    fun eval(scope: Scriptable): Any? {
+        return eval(scope, null)
+    }
 
     @Throws(ScriptException::class)
     abstract fun eval(scope: Scriptable, coroutineContext: CoroutineContext?): Any?

+ 15 - 49
modules/rhino/src/main/java/com/script/rhino/RhinoCompiledScript.kt

@@ -25,12 +25,17 @@
 package com.script.rhino
 
 import com.script.CompiledScript
-import com.script.ScriptContext
 import com.script.ScriptEngine
 import com.script.ScriptException
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.asContextElement
 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 kotlin.coroutines.Continuation
 import kotlin.coroutines.CoroutineContext
@@ -51,56 +56,15 @@ internal class RhinoCompiledScript(
         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? {
         val cx = Context.enter() as RhinoContext
+        cx.checkRecursive()
         val previousCoroutineContext = cx.coroutineContext
-        cx.coroutineContext = coroutineContext
+        if (coroutineContext != null && coroutineContext[Job] != null) {
+            cx.coroutineContext = coroutineContext
+        }
+        cx.allowScriptRun = true
+        cx.recursiveCount++
         val result: Any?
         try {
             val ret = script.exec(cx, scope)
@@ -117,6 +81,8 @@ internal class RhinoCompiledScript(
             throw se
         } finally {
             cx.coroutineContext = previousCoroutineContext
+            cx.allowScriptRun = false
+            cx.recursiveCount--
             Context.exit()
         }
         return result

+ 8 - 0
modules/rhino/src/main/java/com/script/rhino/RhinoContext.kt

@@ -10,6 +10,7 @@ class RhinoContext(factory: ContextFactory) : Context(factory) {
 
     var coroutineContext: CoroutineContext? = null
     var allowScriptRun = false
+    var recursiveCount = 0
 
     @Throws(RhinoInterruptError::class)
     fun ensureActive() {
@@ -20,4 +21,11 @@ class RhinoContext(factory: ContextFactory) : Context(factory) {
         }
     }
 
+    @Throws(RhinoRecursionError::class)
+    fun checkRecursive() {
+        if (recursiveCount >= 10) {
+            throw RhinoRecursionError()
+        }
+    }
+
 }

+ 2 - 0
modules/rhino/src/main/java/com/script/rhino/RhinoInterruptedError.kt → modules/rhino/src/main/java/com/script/rhino/RhinoErrors.kt

@@ -1,3 +1,5 @@
 package com.script.rhino
 
 class RhinoInterruptError(override val cause: Throwable) : Error()
+
+class RhinoRecursionError(): Error("Maximum recursion depth exceeded.")

+ 8 - 1
modules/rhino/src/main/java/com/script/rhino/RhinoScriptEngine.kt

@@ -33,6 +33,7 @@ import com.script.ScriptBindings
 import com.script.ScriptContext
 import com.script.ScriptException
 import com.script.SimpleBindings
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.asContextElement
 import kotlinx.coroutines.withContext
 import org.mozilla.javascript.Callable
@@ -92,11 +93,13 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
         coroutineContext: CoroutineContext?
     ): Any? {
         val cx = Context.enter() as RhinoContext
+        cx.checkRecursive()
         val previousCoroutineContext = cx.coroutineContext
-        if (coroutineContext != null) {
+        if (coroutineContext != null && coroutineContext[Job] != null) {
             cx.coroutineContext = coroutineContext
         }
         cx.allowScriptRun = true
+        cx.recursiveCount++
         val ret: Any?
         try {
             var filename = this["javax.script.filename"] as? String
@@ -117,6 +120,7 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
         } finally {
             cx.coroutineContext = previousCoroutineContext
             cx.allowScriptRun = false
+            cx.recursiveCount--
             Context.exit()
         }
         return unwrapReturnValue(ret)
@@ -125,9 +129,11 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
     @Throws(ContinuationPending::class)
     override suspend fun evalSuspend(reader: Reader, scope: Scriptable): Any? {
         val cx = Context.enter() as RhinoContext
+        cx.checkRecursive()
         var ret: Any?
         withContext(VMBridgeReflect.contextLocal.asContextElement()) {
             cx.allowScriptRun = true
+            cx.recursiveCount++
             try {
                 var filename = this@RhinoScriptEngine["javax.script.filename"] as? String
                 filename = filename ?: "<Unknown source>"
@@ -166,6 +172,7 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
                 throw ScriptException(var14)
             } finally {
                 cx.allowScriptRun = false
+                cx.recursiveCount--
                 Context.exit()
             }
         }