kunfei 3 жил өмнө
parent
commit
8562cf7f2f

+ 24 - 2
app/src/test/java/io/legado/app/JsTest.kt

@@ -5,9 +5,26 @@ import io.legado.app.constant.SCRIPT_ENGINE
 import org.intellij.lang.annotations.Language
 import org.intellij.lang.annotations.Language
 import org.junit.Assert
 import org.junit.Assert
 import org.junit.Test
 import org.junit.Test
+import org.mozilla.javascript.Context
 
 
 class JsTest {
 class JsTest {
 
 
+    @Language("js")
+    private val printJs = """
+        function print(str, newline) {
+            if (typeof(str) == 'undefined') {
+                str = 'undefined';
+            } else if (str == null) {
+                str = 'null';
+            } 
+            java.lang.System.out.print(String(str));
+            if (newline) java.lang.System.out.print("\n");
+        }
+        function println(str) { 
+            print(str, true);
+        }
+    """.trimIndent()
+
     @Test
     @Test
     fun testMap() {
     fun testMap() {
         val map = hashMapOf("id" to "3242532321")
         val map = hashMapOf("id" to "3242532321")
@@ -20,9 +37,11 @@ class JsTest {
         Assert.assertEquals("12314123", result)
         Assert.assertEquals("12314123", result)
     }
     }
 
 
-
     @Test
     @Test
     fun testFor() {
     fun testFor() {
+        val context = SCRIPT_ENGINE.getScriptContext(SimpleBindings())
+        val scope = SCRIPT_ENGINE.getRuntimeScope(context)
+        Context.enter().evaluateString(scope, printJs, "print", 1, null)
         @Language("js")
         @Language("js")
         val jsFor = """
         val jsFor = """
             let result = 0
             let result = 0
@@ -30,16 +49,19 @@ class JsTest {
             let l=a.length
             let l=a.length
             for (let i = 0;i<l;i++){
             for (let i = 0;i<l;i++){
             	result = result + a[i]
             	result = result + a[i]
+                println(i)
             }
             }
             for (let o of a){
             for (let o of a){
             	result = result + o
             	result = result + o
+                println(o)
             }
             }
             for (let o in a){
             for (let o in a){
             	result = result + o
             	result = result + o
+                println(o)
             }
             }
             result
             result
         """.trimIndent()
         """.trimIndent()
-        val result = SCRIPT_ENGINE.eval(jsFor).toString()
+        val result = SCRIPT_ENGINE.eval(jsFor, scope).toString()
         Assert.assertEquals("12012", result)
         Assert.assertEquals("12012", result)
     }
     }
 
 

+ 18 - 2
rhino/src/main/java/com/script/AbstractScriptEngine.kt

@@ -3,7 +3,9 @@
  */
  */
 package com.script
 package com.script
 
 
+import org.mozilla.javascript.Scriptable
 import java.io.Reader
 import java.io.Reader
+import java.io.StringReader
 
 
 abstract class AbstractScriptEngine(val bindings: Bindings? = null) : ScriptEngine {
 abstract class AbstractScriptEngine(val bindings: Bindings? = null) : ScriptEngine {
 
 
@@ -51,6 +53,15 @@ abstract class AbstractScriptEngine(val bindings: Bindings? = null) : ScriptEngi
         return nn?.get(key)
         return nn?.get(key)
     }
     }
 
 
+    override fun eval(script: String, scope: Scriptable): Any? {
+        return this.eval(StringReader(script), scope)
+    }
+
+    @Throws(ScriptException::class)
+    override fun eval(reader: Reader, context: ScriptContext): Any? {
+        return this.eval(reader, getRuntimeScope(context))
+    }
+
     @Throws(ScriptException::class)
     @Throws(ScriptException::class)
     override fun eval(reader: Reader, bindings: Bindings): Any? {
     override fun eval(reader: Reader, bindings: Bindings): Any? {
         return this.eval(reader, getScriptContext(bindings))
         return this.eval(reader, getScriptContext(bindings))
@@ -71,13 +82,18 @@ abstract class AbstractScriptEngine(val bindings: Bindings? = null) : ScriptEngi
         return this.eval(script, context)
         return this.eval(script, context)
     }
     }
 
 
-    protected fun getScriptContext(nn: Bindings): ScriptContext {
+    @Throws(ScriptException::class)
+    override fun eval(script: String, context: ScriptContext): Any? {
+        return this.eval(StringReader(script), context)
+    }
+
+    override fun getScriptContext(bindings: Bindings): ScriptContext {
         val ctx = SimpleScriptContext()
         val ctx = SimpleScriptContext()
         val gs = getBindings(200)
         val gs = getBindings(200)
         if (gs != null) {
         if (gs != null) {
             ctx.setBindings(gs, 200)
             ctx.setBindings(gs, 200)
         }
         }
-        ctx.setBindings(nn, 100)
+        ctx.setBindings(bindings, 100)
         ctx.reader = context.reader
         ctx.reader = context.reader
         ctx.writer = context.writer
         ctx.writer = context.writer
         ctx.errorWriter = context.errorWriter
         ctx.errorWriter = context.errorWriter

+ 11 - 0
rhino/src/main/java/com/script/ScriptEngine.kt

@@ -3,6 +3,7 @@
  */
  */
 package com.script
 package com.script
 
 
+import org.mozilla.javascript.Scriptable
 import java.io.Reader
 import java.io.Reader
 
 
 interface ScriptEngine {
 interface ScriptEngine {
@@ -10,6 +11,12 @@ interface ScriptEngine {
 
 
     fun createBindings(): Bindings?
     fun createBindings(): Bindings?
 
 
+    @Throws(ScriptException::class)
+    fun eval(reader: Reader, scope: Scriptable): Any?
+
+    @Throws(ScriptException::class)
+    fun eval(script: String, scope: Scriptable): Any?
+
     @Throws(ScriptException::class)
     @Throws(ScriptException::class)
     fun eval(reader: Reader): Any?
     fun eval(reader: Reader): Any?
 
 
@@ -28,6 +35,10 @@ interface ScriptEngine {
     @Throws(ScriptException::class)
     @Throws(ScriptException::class)
     fun eval(script: String, context: ScriptContext): Any?
     fun eval(script: String, context: ScriptContext): Any?
 
 
+    fun getRuntimeScope(context: ScriptContext): Scriptable
+
+    fun getScriptContext(bindings: Bindings): ScriptContext
+
     operator fun get(key: String): Any?
     operator fun get(key: String): Any?
 
 
     fun getBindings(scope: Int): Bindings?
     fun getBindings(scope: Int): Bindings?

+ 26 - 5
rhino/src/main/java/com/script/rhino/RhinoScriptEngine.kt

@@ -49,11 +49,10 @@ class RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
     private val implementor: InterfaceImplementor
     private val implementor: InterfaceImplementor
 
 
     @Throws(ScriptException::class)
     @Throws(ScriptException::class)
-    override fun eval(reader: Reader, context: ScriptContext): Any? {
+    override fun eval(reader: Reader, scope: Scriptable): Any? {
         val cx = Context.enter()
         val cx = Context.enter()
         val ret: Any?
         val ret: Any?
         try {
         try {
-            val scope = getRuntimeScope(context)
             var filename = this["javax.script.filename"] as? String
             var filename = this["javax.script.filename"] as? String
             filename = filename ?: "<Unknown source>"
             filename = filename ?: "<Unknown source>"
             ret = cx.evaluateReader(scope, reader, filename, 1, null)
             ret = cx.evaluateReader(scope, reader, filename, 1, null)
@@ -76,8 +75,30 @@ class RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
     }
     }
 
 
     @Throws(ScriptException::class)
     @Throws(ScriptException::class)
-    override fun eval(script: String, context: ScriptContext): Any? {
-        return this.eval(StringReader(script) as Reader, context)
+    override fun eval(reader: Reader, context: ScriptContext): Any? {
+        val cx = Context.enter()
+        val ret: Any?
+        try {
+            val scope = getRuntimeScope(context)
+            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)
     }
     }
 
 
     override fun createBindings(): Bindings {
     override fun createBindings(): Bindings {
@@ -152,7 +173,7 @@ class RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
         }
         }
     }
     }
 
 
-    fun getRuntimeScope(context: ScriptContext): Scriptable {
+    override fun getRuntimeScope(context: ScriptContext): Scriptable {
         val newScope: Scriptable = ExternalScriptable(context, indexedProps)
         val newScope: Scriptable = ExternalScriptable(context, indexedProps)
         newScope.prototype = topLevel
         newScope.prototype = topLevel
         newScope.put("context", newScope, context)
         newScope.put("context", newScope, context)