kunfei 3 лет назад
Родитель
Сommit
9b9587d70b

+ 6 - 8
app/src/androidTest/java/io/legado/app/AndroidJsTest.kt

@@ -37,7 +37,7 @@ class AndroidJsTest {
             queryStringWithSign
             queryStringWithSign
         """.trimIndent()
         """.trimIndent()
         Rhino.use {
         Rhino.use {
-            evaluateString(initStandardObjects(), js, "yy", 1, null)
+            evaluateString(it, js, "yy", 1, null)
         }
         }
         @Language("js")
         @Language("js")
         val js1 = """
         val js1 = """
@@ -45,7 +45,7 @@ class AndroidJsTest {
             returnData.getErrorMsg()
             returnData.getErrorMsg()
         """.trimIndent()
         """.trimIndent()
         val result1 = Rhino.use {
         val result1 = Rhino.use {
-            evaluateString(initStandardObjects(), js1, "xx", 1, null)
+            evaluateString(it, js1, "xx", 1, null)
         }
         }
         Assert.assertEquals(result1, "未知错误,请联系开发者!").let {
         Assert.assertEquals(result1, "未知错误,请联系开发者!").let {
 
 
@@ -59,17 +59,15 @@ class AndroidJsTest {
         @Language("js")
         @Language("js")
         val jsMap = "$=result;id=$.id;id"
         val jsMap = "$=result;id=$.id;id"
         val result = Rhino.use {
         val result = Rhino.use {
-            val scope = initStandardObjects()
-            scope.putBinding("result", map)
-            evaluateString(scope, jsMap, "xxx", 1, null)
+            it.putBinding("result", map)
+            evaluateString(it, jsMap, "xxx", 1, null)
         }
         }
         Assert.assertEquals("3242532321", result)
         Assert.assertEquals("3242532321", result)
         @Language("js")
         @Language("js")
         val jsMap1 = """result.get("id")"""
         val jsMap1 = """result.get("id")"""
         val result1 = Rhino.use {
         val result1 = Rhino.use {
-            val scope = initStandardObjects()
-            scope.putBinding("result", map)
-            evaluateString(scope, jsMap1, "xxx", 1, null)
+            it.putBinding("result", map)
+            evaluateString(it, jsMap1, "xxx", 1, null)
         }
         }
         Assert.assertEquals("3242532321", result1)
         Assert.assertEquals("3242532321", result1)
     }
     }

+ 0 - 2
app/src/main/java/io/legado/app/App.kt

@@ -10,7 +10,6 @@ import android.os.Build
 import com.github.liuyueyi.quick.transfer.ChineseUtils
 import com.github.liuyueyi.quick.transfer.ChineseUtils
 import com.github.liuyueyi.quick.transfer.constants.TransType
 import com.github.liuyueyi.quick.transfer.constants.TransType
 import com.jeremyliao.liveeventbus.LiveEventBus
 import com.jeremyliao.liveeventbus.LiveEventBus
-import com.script.rhino.RhinoScriptEngine
 import io.legado.app.base.AppContextWrapper
 import io.legado.app.base.AppContextWrapper
 import io.legado.app.constant.AppConst.channelIdDownload
 import io.legado.app.constant.AppConst.channelIdDownload
 import io.legado.app.constant.AppConst.channelIdReadAloud
 import io.legado.app.constant.AppConst.channelIdReadAloud
@@ -41,7 +40,6 @@ class App : Application() {
 
 
     override fun onCreate() {
     override fun onCreate() {
         super.onCreate()
         super.onCreate()
-        RhinoScriptEngine
         oldConfig = Configuration(resources.configuration)
         oldConfig = Configuration(resources.configuration)
         CrashHandler(this)
         CrashHandler(this)
         //预下载Cronet so
         //预下载Cronet so

+ 8 - 4
app/src/main/java/io/legado/app/data/entities/BaseSource.kt

@@ -236,15 +236,19 @@ interface BaseSource : JsExtensions {
         bindings["baseUrl"] = getKey()
         bindings["baseUrl"] = getKey()
         bindings["cookie"] = CookieStore
         bindings["cookie"] = CookieStore
         bindings["cache"] = CacheManager
         bindings["cache"] = CacheManager
-//        return Rhino.use {
-//            val scope = initStandardObjects()
+//        return Rhino.use { scope ->
 //            scope.putBindings(bindings)
 //            scope.putBindings(bindings)
 //            getShareScope()?.let {
 //            getShareScope()?.let {
 //                scope.prototype = it
 //                scope.prototype = it
 //            }
 //            }
-//            evaluate(scope, jsStr)
+//            eval(scope, jsStr)
 //        }
 //        }
-        return RhinoScriptEngine.eval(jsStr, SimpleBindings(bindings))
+        val context = RhinoScriptEngine.getScriptContext(SimpleBindings(bindings))
+        val scope = RhinoScriptEngine.getRuntimeScope(context)
+        getShareScope()?.let {
+            scope.prototype = it
+        }
+        return RhinoScriptEngine.eval(jsStr, scope)
     }
     }
 
 
     fun getShareScope(): Scriptable? {
     fun getShareScope(): Scriptable? {

+ 2 - 3
app/src/main/java/io/legado/app/help/book/BookExtensions.kt

@@ -241,9 +241,8 @@ fun Book.getExportFileName(suffix: String): String {
     bindings["author"] = getRealAuthor()
     bindings["author"] = getRealAuthor()
     return kotlin.runCatching {
     return kotlin.runCatching {
         Rhino.use {
         Rhino.use {
-            val scope = initStandardObjects()
-            scope.putBindings(bindings)
-            evaluateString(scope, jsStr, "name&author", 1, null)
+            it.putBindings(bindings)
+            evaluateString(it, jsStr, "name&author", 1, null)
         }.toString() + "." + suffix
         }.toString() + "." + suffix
     }.onFailure {
     }.onFailure {
         AppLog.put("导出书名规则错误,使用默认规则\n${it.localizedMessage}", it)
         AppLog.put("导出书名规则错误,使用默认规则\n${it.localizedMessage}", it)

+ 1 - 1
app/src/main/java/io/legado/app/model/SharedJsScope.kt

@@ -32,7 +32,7 @@ object SharedJsScope {
         var scope = scopeMap[key]?.get()
         var scope = scopeMap[key]?.get()
         if (scope == null) {
         if (scope == null) {
             Rhino.use {
             Rhino.use {
-                scope = initStandardObjects()
+                scope = it
                 if (jsLib.isJsonObject()) {
                 if (jsLib.isJsonObject()) {
                     val jsMap: Map<String, String> = GSON.fromJson(
                     val jsMap: Map<String, String> = GSON.fromJson(
                         jsLib,
                         jsLib,

+ 26 - 6
app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt

@@ -258,6 +258,7 @@ class AnalyzeRule(
                                 } else {
                                 } else {
                                     getAnalyzeByJSoup(it).getString(sourceRule.rule)
                                     getAnalyzeByJSoup(it).getString(sourceRule.rule)
                                 }
                                 }
+
                                 else -> sourceRule.rule
                                 else -> sourceRule.rule
                             }
                             }
                         }
                         }
@@ -307,6 +308,7 @@ class AnalyzeRule(
                             result.toString(),
                             result.toString(),
                             sourceRule.rule.splitNotBlank("&&")
                             sourceRule.rule.splitNotBlank("&&")
                         )
                         )
+
                         Mode.Js -> evalJS(sourceRule.rule, it)
                         Mode.Js -> evalJS(sourceRule.rule, it)
                         Mode.Json -> getAnalyzeByJSonPath(it).getObject(sourceRule.rule)
                         Mode.Json -> getAnalyzeByJSonPath(it).getObject(sourceRule.rule)
                         Mode.XPath -> getAnalyzeByXPath(it).getElements(sourceRule.rule)
                         Mode.XPath -> getAnalyzeByXPath(it).getElements(sourceRule.rule)
@@ -339,6 +341,7 @@ class AnalyzeRule(
                             result.toString(),
                             result.toString(),
                             sourceRule.rule.splitNotBlank("&&")
                             sourceRule.rule.splitNotBlank("&&")
                         )
                         )
+
                         Mode.Js -> evalJS(sourceRule.rule, result)
                         Mode.Js -> evalJS(sourceRule.rule, result)
                         Mode.Json -> getAnalyzeByJSonPath(it).getList(sourceRule.rule)
                         Mode.Json -> getAnalyzeByJSonPath(it).getList(sourceRule.rule)
                         Mode.XPath -> getAnalyzeByXPath(it).getElements(sourceRule.rule)
                         Mode.XPath -> getAnalyzeByXPath(it).getElements(sourceRule.rule)
@@ -389,7 +392,7 @@ class AnalyzeRule(
         if (rule.replaceRegex.isEmpty()) return result
         if (rule.replaceRegex.isEmpty()) return result
         var vResult = result
         var vResult = result
         vResult = if (rule.replaceFirst) {
         vResult = if (rule.replaceFirst) {
-        /* ##match##replace### 获取第一个匹配到的结果并进行替换 */
+            /* ##match##replace### 获取第一个匹配到的结果并进行替换 */
             kotlin.runCatching {
             kotlin.runCatching {
                 val pattern = Pattern.compile(rule.replaceRegex)
                 val pattern = Pattern.compile(rule.replaceRegex)
                 val matcher = pattern.matcher(vResult)
                 val matcher = pattern.matcher(vResult)
@@ -402,7 +405,7 @@ class AnalyzeRule(
                 rule.replacement
                 rule.replacement
             }
             }
         } else {
         } else {
-        /* ##match##replace 替换*/
+            /* ##match##replace 替换*/
             kotlin.runCatching {
             kotlin.runCatching {
                 vResult.replace(rule.replaceRegex.toRegex(), rule.replacement)
                 vResult.replace(rule.replaceRegex.toRegex(), rule.replacement)
             }.getOrElse {
             }.getOrElse {
@@ -476,26 +479,32 @@ class AnalyzeRule(
                     mode = Mode.Default
                     mode = Mode.Default
                     ruleStr
                     ruleStr
                 }
                 }
+
                 ruleStr.startsWith("@@") -> {
                 ruleStr.startsWith("@@") -> {
                     mode = Mode.Default
                     mode = Mode.Default
                     ruleStr.substring(2)
                     ruleStr.substring(2)
                 }
                 }
+
                 ruleStr.startsWith("@XPath:", true) -> {
                 ruleStr.startsWith("@XPath:", true) -> {
                     mode = Mode.XPath
                     mode = Mode.XPath
                     ruleStr.substring(7)
                     ruleStr.substring(7)
                 }
                 }
+
                 ruleStr.startsWith("@Json:", true) -> {
                 ruleStr.startsWith("@Json:", true) -> {
                     mode = Mode.Json
                     mode = Mode.Json
                     ruleStr.substring(6)
                     ruleStr.substring(6)
                 }
                 }
+
                 isJSON || ruleStr.startsWith("$.") || ruleStr.startsWith("$[") -> {
                 isJSON || ruleStr.startsWith("$.") || ruleStr.startsWith("$[") -> {
                     mode = Mode.Json
                     mode = Mode.Json
                     ruleStr
                     ruleStr
                 }
                 }
+
                 ruleStr.startsWith("/") -> {//XPath特征很明显,无需配置单独的识别标头
                 ruleStr.startsWith("/") -> {//XPath特征很明显,无需配置单独的识别标头
                     mode = Mode.XPath
                     mode = Mode.XPath
                     ruleStr
                     ruleStr
                 }
                 }
+
                 else -> ruleStr
                 else -> ruleStr
             }
             }
             //分离put
             //分离put
@@ -523,10 +532,12 @@ class AnalyzeRule(
                             ruleType.add(getRuleType)
                             ruleType.add(getRuleType)
                             ruleParam.add(tmp.substring(6, tmp.lastIndex))
                             ruleParam.add(tmp.substring(6, tmp.lastIndex))
                         }
                         }
+
                         tmp.startsWith("{{") -> {
                         tmp.startsWith("{{") -> {
                             ruleType.add(jsRuleType)
                             ruleType.add(jsRuleType)
                             ruleParam.add(tmp.substring(2, tmp.length - 2))
                             ruleParam.add(tmp.substring(2, tmp.length - 2))
                         }
                         }
+
                         else -> {
                         else -> {
                             splitRegex(tmp)
                             splitRegex(tmp)
                         }
                         }
@@ -592,6 +603,7 @@ class AnalyzeRule(
                                 }
                                 }
                             } ?: infoVal.insert(0, ruleParam[index])
                             } ?: infoVal.insert(0, ruleParam[index])
                         }
                         }
+
                         regType == jsRuleType -> {
                         regType == jsRuleType -> {
                             if (isRule(ruleParam[index])) {
                             if (isRule(ruleParam[index])) {
                                 getString(arrayListOf(SourceRule(ruleParam[index]))).let {
                                 getString(arrayListOf(SourceRule(ruleParam[index]))).let {
@@ -606,13 +618,16 @@ class AnalyzeRule(
                                         0,
                                         0,
                                         String.format("%.0f", jsEval)
                                         String.format("%.0f", jsEval)
                                     )
                                     )
+
                                     else -> infoVal.insert(0, jsEval.toString())
                                     else -> infoVal.insert(0, jsEval.toString())
                                 }
                                 }
                             }
                             }
                         }
                         }
+
                         regType == getRuleType -> {
                         regType == getRuleType -> {
                             infoVal.insert(0, get(ruleParam[index]))
                             infoVal.insert(0, get(ruleParam[index]))
                         }
                         }
+
                         else -> infoVal.insert(0, ruleParam[index])
                         else -> infoVal.insert(0, ruleParam[index])
                     }
                     }
                 }
                 }
@@ -667,6 +682,7 @@ class AnalyzeRule(
             "bookName" -> book?.let {
             "bookName" -> book?.let {
                 return it.name
                 return it.name
             }
             }
+
             "title" -> chapter?.let {
             "title" -> chapter?.let {
                 return it.title
                 return it.title
             }
             }
@@ -694,15 +710,19 @@ class AnalyzeRule(
         bindings["title"] = chapter?.title
         bindings["title"] = chapter?.title
         bindings["src"] = content
         bindings["src"] = content
         bindings["nextChapterUrl"] = nextChapterUrl
         bindings["nextChapterUrl"] = nextChapterUrl
-//        return Rhino.use {
-//            val scope = initStandardObjects()
+//        return Rhino.use { scope ->
 //            scope.putBindings(bindings)
 //            scope.putBindings(bindings)
 //            source?.getShareScope()?.let {
 //            source?.getShareScope()?.let {
 //                scope.prototype = it
 //                scope.prototype = it
 //            }
 //            }
-//            evaluate(scope, jsStr)
+//            eval(scope, jsStr)
 //        }
 //        }
-        return RhinoScriptEngine.eval(jsStr, SimpleBindings(bindings))
+        val context = RhinoScriptEngine.getScriptContext(SimpleBindings(bindings))
+        val scope = RhinoScriptEngine.getRuntimeScope(context)
+        source?.getShareScope()?.let {
+            scope.prototype = it
+        }
+        return RhinoScriptEngine.eval(jsStr, scope)
     }
     }
 
 
     override fun getSource(): BaseSource? {
     override fun getSource(): BaseSource? {

+ 17 - 5
app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt

@@ -215,6 +215,7 @@ class AnalyzeUrl(
                     urlNoQuery = url.substring(0, pos)
                     urlNoQuery = url.substring(0, pos)
                 }
                 }
             }
             }
+
             RequestMethod.POST -> body?.let {
             RequestMethod.POST -> body?.let {
                 if (!it.isJson() && !it.isXml() && headerMap["Content-Type"].isNullOrEmpty()) {
                 if (!it.isJson() && !it.isXml() && headerMap["Content-Type"].isNullOrEmpty()) {
                     analyzeFields(it)
                     analyzeFields(it)
@@ -266,15 +267,19 @@ class AnalyzeUrl(
         bindings["book"] = ruleData as? Book
         bindings["book"] = ruleData as? Book
         bindings["source"] = source
         bindings["source"] = source
         bindings["result"] = result
         bindings["result"] = result
-//        return Rhino.use {
-//            val scope = initStandardObjects()
+//        return Rhino.use { scope ->
 //            scope.putBindings(bindings)
 //            scope.putBindings(bindings)
 //            source?.getShareScope()?.let {
 //            source?.getShareScope()?.let {
 //                scope.prototype = it
 //                scope.prototype = it
 //            }
 //            }
-//            evaluate(scope, jsStr)
+//            eval(scope, jsStr)
 //        }
 //        }
-        return RhinoScriptEngine.eval(jsStr, SimpleBindings(bindings))
+        val context = RhinoScriptEngine.getScriptContext(SimpleBindings(bindings))
+        val scope = RhinoScriptEngine.getRuntimeScope(context)
+        source?.getShareScope()?.let {
+            scope.prototype = it
+        }
+        return RhinoScriptEngine.eval(jsStr, scope)
     }
     }
 
 
     fun put(key: String, value: String): String {
     fun put(key: String, value: String): String {
@@ -288,6 +293,7 @@ class AnalyzeUrl(
             "bookName" -> (ruleData as? Book)?.let {
             "bookName" -> (ruleData as? Book)?.let {
                 return it.name
                 return it.name
             }
             }
+
             "title" -> chapter?.let {
             "title" -> chapter?.let {
                 return it.title
                 return it.title
             }
             }
@@ -353,7 +359,10 @@ class AnalyzeUrl(
             }
             }
         }
         }
         if (waitTime > 0) {
         if (waitTime > 0) {
-            throw ConcurrentException("根据并发率还需等待${waitTime}毫秒才可以访问", waitTime = waitTime)
+            throw ConcurrentException(
+                "根据并发率还需等待${waitTime}毫秒才可以访问",
+                waitTime = waitTime
+            )
         }
         }
         return fetchRecord
         return fetchRecord
     }
     }
@@ -414,6 +423,7 @@ class AnalyzeUrl(
                             headerMap = headerMap
                             headerMap = headerMap
                         ).getStrResponse()
                         ).getStrResponse()
                     }
                     }
+
                     else -> BackstageWebView(
                     else -> BackstageWebView(
                         url = url,
                         url = url,
                         tag = source?.getKey(),
                         tag = source?.getKey(),
@@ -439,6 +449,7 @@ class AnalyzeUrl(
                                 postJson(body)
                                 postJson(body)
                             }
                             }
                         }
                         }
+
                         else -> get(urlNoQuery, fieldMap, true)
                         else -> get(urlNoQuery, fieldMap, true)
                     }
                     }
                 }.let {
                 }.let {
@@ -500,6 +511,7 @@ class AnalyzeUrl(
                             postJson(body)
                             postJson(body)
                         }
                         }
                     }
                     }
+
                     else -> get(urlNoQuery, fieldMap, true)
                     else -> get(urlNoQuery, fieldMap, true)
                 }
                 }
             }
             }

+ 3 - 4
app/src/main/java/io/legado/app/model/localBook/LocalBook.kt

@@ -20,7 +20,7 @@ import io.legado.app.lib.webdav.WebDav
 import io.legado.app.lib.webdav.WebDavException
 import io.legado.app.lib.webdav.WebDavException
 import io.legado.app.model.analyzeRule.AnalyzeUrl
 import io.legado.app.model.analyzeRule.AnalyzeUrl
 import io.legado.app.rhino.Rhino
 import io.legado.app.rhino.Rhino
-import io.legado.app.rhino.evaluate
+import io.legado.app.rhino.eval
 import io.legado.app.rhino.putBinding
 import io.legado.app.rhino.putBinding
 import io.legado.app.utils.*
 import io.legado.app.utils.*
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.runBlocking
@@ -272,9 +272,8 @@ object LocalBook {
                     AppConfig.bookImportFileName + "\nJSON.stringify({author:author,name:name})"
                     AppConfig.bookImportFileName + "\nJSON.stringify({author:author,name:name})"
                 //在脚本中定义如何分解文件名成书名、作者名
                 //在脚本中定义如何分解文件名成书名、作者名
                 val jsonStr = Rhino.use {
                 val jsonStr = Rhino.use {
-                    val scope = initStandardObjects()
-                    scope.putBinding("src", tempFileName)
-                    evaluate(scope, js)
+                    it.putBinding("src", tempFileName)
+                    eval(it, js)
                 }.toString()
                 }.toString()
                 val bookMess = GSON.fromJsonObject<HashMap<String, String>>(jsonStr)
                 val bookMess = GSON.fromJsonObject<HashMap<String, String>>(jsonStr)
                     .getOrThrow()
                     .getOrThrow()

+ 5 - 2
app/src/main/java/io/legado/app/rhino/Rhino.kt

@@ -1,15 +1,18 @@
 package io.legado.app.rhino
 package io.legado.app.rhino
 
 
 import org.mozilla.javascript.Context
 import org.mozilla.javascript.Context
+import org.mozilla.javascript.ImporterTopLevel
+import org.mozilla.javascript.Scriptable
 import org.mozilla.javascript.Undefined
 import org.mozilla.javascript.Undefined
 import org.mozilla.javascript.Wrapper
 import org.mozilla.javascript.Wrapper
 
 
 object Rhino {
 object Rhino {
 
 
-    inline fun <T> use(block: Context.() -> T): T {
+    inline fun <T> use(block: Context.(Scriptable) -> T): T {
         return try {
         return try {
             val cx = Context.enter()
             val cx = Context.enter()
-            block.invoke(cx)
+            val scope = cx.initStandardObjects(ImporterTopLevel(cx))
+            block.invoke(cx, scope)
         } finally {
         } finally {
             Context.exit()
             Context.exit()
         }
         }

+ 2 - 30
app/src/main/java/io/legado/app/rhino/RhinoExtensions.kt

@@ -7,7 +7,7 @@ import org.mozilla.javascript.Scriptable
 import org.mozilla.javascript.ScriptableObject
 import org.mozilla.javascript.ScriptableObject
 import java.io.Reader
 import java.io.Reader
 
 
-fun Context.evaluate(
+fun Context.eval(
     scope: Scriptable,
     scope: Scriptable,
     source: String,
     source: String,
     sourceName: String = "<Unknown source>",
     sourceName: String = "<Unknown source>",
@@ -19,21 +19,7 @@ fun Context.evaluate(
     )
     )
 }
 }
 
 
-fun Context.evaluate(
-    bindings: Bindings,
-    source: String,
-    sourceName: String = "<Unknown source>",
-    lineno: Int = 1,
-    securityDomain: Any? = null
-): Any? {
-    val scope = initStandardObjects()
-    scope.putBindings(bindings)
-    return Rhino.unwrapReturnValue(
-        evaluateString(scope, source, sourceName, lineno, securityDomain)
-    )
-}
-
-fun Context.evaluate(
+fun Context.eval(
     scope: Scriptable,
     scope: Scriptable,
     reader: Reader,
     reader: Reader,
     sourceName: String = "<Unknown source>",
     sourceName: String = "<Unknown source>",
@@ -45,20 +31,6 @@ fun Context.evaluate(
     )
     )
 }
 }
 
 
-fun Context.evaluate(
-    bindings: Bindings,
-    reader: Reader,
-    sourceName: String = "<Unknown source>",
-    lineno: Int = 1,
-    securityDomain: Any? = null
-): Any? {
-    val scope = initStandardObjects()
-    scope.putBindings(bindings)
-    return Rhino.unwrapReturnValue(
-        evaluateReader(scope, reader, sourceName, lineno, securityDomain)
-    )
-}
-
 fun Scriptable.putBinding(key: String, value: Any?) {
 fun Scriptable.putBinding(key: String, value: Any?) {
     val wrappedOut = Context.javaToJS(value, this)
     val wrappedOut = Context.javaToJS(value, this)
     ScriptableObject.putProperty(this, key, wrappedOut)
     ScriptableObject.putProperty(this, key, wrappedOut)

+ 7 - 4
app/src/main/java/io/legado/app/utils/JsUtils.kt

@@ -3,7 +3,8 @@ package io.legado.app.utils
 import io.legado.app.constant.AppPattern.EXP_PATTERN
 import io.legado.app.constant.AppPattern.EXP_PATTERN
 import io.legado.app.rhino.Bindings
 import io.legado.app.rhino.Bindings
 import io.legado.app.rhino.Rhino
 import io.legado.app.rhino.Rhino
-import io.legado.app.rhino.evaluate
+import io.legado.app.rhino.eval
+import io.legado.app.rhino.putBindings
 
 
 object JsUtils {
 object JsUtils {
 
 
@@ -14,9 +15,10 @@ object JsUtils {
             val sb = StringBuffer()
             val sb = StringBuffer()
             val expMatcher = EXP_PATTERN.matcher(js)
             val expMatcher = EXP_PATTERN.matcher(js)
             while (expMatcher.find()) {
             while (expMatcher.find()) {
-                val result = expMatcher.group(1)?.let {
+                val result = expMatcher.group(1)?.let { js1 ->
                     Rhino.use {
                     Rhino.use {
-                        evaluate(bindings, it)
+                        it.putBindings(bindings)
+                        eval(it, js1)
                     }
                     }
                 } ?: ""
                 } ?: ""
                 if (result is String) {
                 if (result is String) {
@@ -31,7 +33,8 @@ object JsUtils {
             return sb.toString()
             return sb.toString()
         }
         }
         return Rhino.use {
         return Rhino.use {
-            evaluate(bindings, js)
+            it.putBindings(bindings)
+            eval(it, js)
         }.toString()
         }.toString()
     }
     }
 
 

+ 4 - 5
app/src/main/java/io/legado/app/utils/RegexExtensions.kt

@@ -4,9 +4,9 @@ import androidx.core.os.postDelayed
 import io.legado.app.exception.RegexTimeoutException
 import io.legado.app.exception.RegexTimeoutException
 import io.legado.app.help.CrashHandler
 import io.legado.app.help.CrashHandler
 import io.legado.app.help.coroutine.Coroutine
 import io.legado.app.help.coroutine.Coroutine
-import io.legado.app.rhino.Bindings
 import io.legado.app.rhino.Rhino
 import io.legado.app.rhino.Rhino
-import io.legado.app.rhino.evaluate
+import io.legado.app.rhino.eval
+import io.legado.app.rhino.putBinding
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlinx.coroutines.suspendCancellableCoroutine
 import splitties.init.appCtx
 import splitties.init.appCtx
@@ -31,10 +31,9 @@ fun CharSequence.replace(regex: Regex, replacement: String, timeout: Long): Stri
                     val stringBuffer = StringBuffer()
                     val stringBuffer = StringBuffer()
                     while (matcher.find()) {
                     while (matcher.find()) {
                         if (isJs) {
                         if (isJs) {
-                            val bindings = Bindings()
-                            bindings["result"] = matcher.group()
                             val jsResult = Rhino.use {
                             val jsResult = Rhino.use {
-                                evaluate(bindings, replacement1)
+                                it.putBinding("result", matcher.group())
+                                eval(it, replacement1)
                             }.toString()
                             }.toString()
                             matcher.appendReplacement(stringBuffer, jsResult)
                             matcher.appendReplacement(stringBuffer, jsResult)
                         } else {
                         } else {

+ 14 - 18
app/src/test/java/io/legado/app/JsTest.kt

@@ -3,7 +3,7 @@ package io.legado.app
 import com.script.SimpleBindings
 import com.script.SimpleBindings
 import io.legado.app.data.entities.BookChapter
 import io.legado.app.data.entities.BookChapter
 import io.legado.app.rhino.Rhino
 import io.legado.app.rhino.Rhino
-import io.legado.app.rhino.evaluate
+import io.legado.app.rhino.eval
 import io.legado.app.rhino.putBinding
 import io.legado.app.rhino.putBinding
 import org.intellij.lang.annotations.Language
 import org.intellij.lang.annotations.Language
 import org.junit.Assert
 import org.junit.Assert
@@ -42,9 +42,8 @@ class JsTest {
         @Language("js")
         @Language("js")
         val jsMap1 = """result.get("id")"""
         val jsMap1 = """result.get("id")"""
         val result1 = Rhino.use {
         val result1 = Rhino.use {
-            val scope = initStandardObjects()
-            scope.putBinding("result", map)
-            evaluateString(scope, jsMap1, "xxx", 1, null)
+            it.putBinding("result", map)
+            evaluateString(it, jsMap1, "xxx", 1, null)
         }
         }
         Assert.assertEquals("3242532321", result1)
         Assert.assertEquals("3242532321", result1)
     }
     }
@@ -52,9 +51,8 @@ class JsTest {
     @Test
     @Test
     fun testFor() {
     fun testFor() {
         val scope = Rhino.use {
         val scope = Rhino.use {
-            val scope = initStandardObjects()
-            evaluateString(scope, printJs, "print", 1, null)
-            scope
+            evaluateString(it, printJs, "print", 1, null)
+            it
         }
         }
 
 
         @Language("js")
         @Language("js")
@@ -77,7 +75,8 @@ class JsTest {
             result
             result
         """.trimIndent()
         """.trimIndent()
         val result = Rhino.use {
         val result = Rhino.use {
-            evaluateString(scope, jsFor, "jsFor", 1, null)
+            it.prototype = scope
+            evaluateString(it, jsFor, "jsFor", 1, null)
         }
         }
         Assert.assertEquals("12012", result)
         Assert.assertEquals("12012", result)
     }
     }
@@ -85,7 +84,7 @@ class JsTest {
     @Test
     @Test
     fun testReturnNull() {
     fun testReturnNull() {
         val result = Rhino.use {
         val result = Rhino.use {
-            evaluate(initStandardObjects(), "null")
+            eval(it, "null")
         }
         }
         Assert.assertEquals(null, result)
         Assert.assertEquals(null, result)
     }
     }
@@ -103,9 +102,8 @@ class JsTest {
             .replace(/\:/g,":")
             .replace(/\:/g,":")
         """.trimIndent()
         """.trimIndent()
         val result = Rhino.use {
         val result = Rhino.use {
-            val scope = initStandardObjects()
-            scope.putBinding("result", ",.!?…;:")
-            evaluate(scope, js)
+            it.putBinding("result", ",.!?…;:")
+            eval(it, js)
         }
         }
         Assert.assertEquals(result, ",。!?……;:")
         Assert.assertEquals(result, ",。!?……;:")
     }
     }
@@ -119,9 +117,8 @@ class JsTest {
         @Language("js")
         @Language("js")
         val js = "chapter.title"
         val js = "chapter.title"
         val result = Rhino.use {
         val result = Rhino.use {
-            val scope = initStandardObjects()
-            scope.putBinding("chapter", chapter)
-            evaluate(scope, js)
+            it.putBinding("chapter", chapter)
+            eval(it, js)
         }
         }
         Assert.assertEquals(result, "xxxyyy")
         Assert.assertEquals(result, "xxxyyy")
     }
     }
@@ -137,9 +134,8 @@ class JsTest {
             result
             result
         """.trimIndent()
         """.trimIndent()
         val result = Rhino.use {
         val result = Rhino.use {
-            val scope = initStandardObjects()
-            scope.putBinding("list", list)
-            evaluate(scope, js)
+            it.putBinding("list", list)
+            eval(it, js)
         }
         }
         Assert.assertEquals(result, 6.0)
         Assert.assertEquals(result, 6.0)
     }
     }