Horis 2 лет назад
Родитель
Сommit
79fa3f912a

+ 9 - 7
app/src/main/java/io/legado/app/data/entities/BaseSource.kt

@@ -2,6 +2,7 @@ package io.legado.app.data.entities
 
 import cn.hutool.crypto.symmetric.AES
 import com.script.ScriptBindings
+import com.script.buildScriptBindings
 import com.script.rhino.RhinoScriptEngine
 import io.legado.app.constant.AppConst
 import io.legado.app.constant.AppLog
@@ -232,13 +233,14 @@ interface BaseSource : JsExtensions {
      */
     @Throws(Exception::class)
     fun evalJS(jsStr: String, bindingsConfig: ScriptBindings.() -> Unit = {}): Any? {
-        val bindings = ScriptBindings()
-        bindings.apply(bindingsConfig)
-        bindings["java"] = this
-        bindings["source"] = this
-        bindings["baseUrl"] = getKey()
-        bindings["cookie"] = CookieStore
-        bindings["cache"] = CacheManager
+        val bindings = buildScriptBindings { bindings ->
+            bindings.apply(bindingsConfig)
+            bindings["java"] = this
+            bindings["source"] = this
+            bindings["baseUrl"] = getKey()
+            bindings["cookie"] = CookieStore
+            bindings["cache"] = CacheManager
+        }
         val scope = RhinoScriptEngine.getRuntimeScope(bindings)
         getShareScope()?.let {
             scope.prototype = it

+ 16 - 13
app/src/main/java/io/legado/app/help/book/BookExtensions.kt

@@ -3,7 +3,7 @@
 package io.legado.app.help.book
 
 import android.net.Uri
-import com.script.ScriptBindings
+import com.script.buildScriptBindings
 import com.script.rhino.RhinoScriptEngine
 import io.legado.app.constant.AppLog
 import io.legado.app.constant.BookSourceType
@@ -273,10 +273,11 @@ fun Book.getExportFileName(suffix: String): String {
     if (jsStr.isNullOrBlank()) {
         return "$name 作者:${getRealAuthor()}.$suffix"
     }
-    val bindings = ScriptBindings()
-    bindings["epubIndex"] = ""// 兼容老版本,修复可能存在的错误
-    bindings["name"] = name
-    bindings["author"] = getRealAuthor()
+    val bindings = buildScriptBindings { bindings ->
+        bindings["epubIndex"] = ""// 兼容老版本,修复可能存在的错误
+        bindings["name"] = name
+        bindings["author"] = getRealAuthor()
+    }
     return kotlin.runCatching {
         RhinoScriptEngine.eval(jsStr, bindings).toString() + "." + suffix
     }.onFailure {
@@ -297,10 +298,11 @@ fun Book.getExportFileName(
     if (jsStr.isNullOrBlank()) {
         return default
     }
-    val bindings = ScriptBindings()
-    bindings["name"] = name
-    bindings["author"] = getRealAuthor()
-    bindings["epubIndex"] = epubIndex
+    val bindings = buildScriptBindings { bindings ->
+        bindings["name"] = name
+        bindings["author"] = getRealAuthor()
+        bindings["epubIndex"] = epubIndex
+    }
     return kotlin.runCatching {
         RhinoScriptEngine.eval(jsStr, bindings).toString() + "." + suffix
     }.onFailure {
@@ -327,10 +329,11 @@ fun Book.readSimulating(): Boolean {
 }
 
 fun tryParesExportFileName(jsStr: String): Boolean {
-    val bindings = ScriptBindings()
-    bindings["name"] = "name"
-    bindings["author"] = "author"
-    bindings["epubIndex"] = "epubIndex"
+    val bindings = buildScriptBindings { bindings ->
+        bindings["name"] = "name"
+        bindings["author"] = "author"
+        bindings["epubIndex"] = "epubIndex"
+    }
     return runCatching {
         RhinoScriptEngine.eval(jsStr, bindings)
         true

+ 14 - 12
app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt

@@ -3,6 +3,7 @@ package io.legado.app.model.analyzeRule
 import android.text.TextUtils
 import androidx.annotation.Keep
 import com.script.ScriptBindings
+import com.script.buildScriptBindings
 import com.script.rhino.RhinoScriptEngine
 import io.legado.app.constant.AppPattern.JS_PATTERN
 import io.legado.app.data.entities.BaseBook
@@ -745,18 +746,19 @@ class AnalyzeRule(
      * 执行JS
      */
     fun evalJS(jsStr: String, result: Any? = null): Any? {
-        val bindings = ScriptBindings()
-        bindings["java"] = this
-        bindings["cookie"] = CookieStore
-        bindings["cache"] = CacheManager
-        bindings["source"] = source
-        bindings["book"] = book
-        bindings["result"] = result
-        bindings["baseUrl"] = baseUrl
-        bindings["chapter"] = chapter
-        bindings["title"] = chapter?.title
-        bindings["src"] = content
-        bindings["nextChapterUrl"] = nextChapterUrl
+        val bindings = buildScriptBindings { bindings ->
+            bindings["java"] = this
+            bindings["cookie"] = CookieStore
+            bindings["cache"] = CacheManager
+            bindings["source"] = source
+            bindings["book"] = book
+            bindings["result"] = result
+            bindings["baseUrl"] = baseUrl
+            bindings["chapter"] = chapter
+            bindings["title"] = chapter?.title
+            bindings["src"] = content
+            bindings["nextChapterUrl"] = nextChapterUrl
+        }
         val scope = RhinoScriptEngine.getRuntimeScope(bindings)
         source?.getShareScope()?.let {
             scope.prototype = it

+ 14 - 13
app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt

@@ -6,7 +6,7 @@ import androidx.annotation.Keep
 import androidx.media3.common.MediaItem
 import cn.hutool.core.util.HexUtil
 import com.bumptech.glide.load.model.GlideUrl
-import com.script.ScriptBindings
+import com.script.buildScriptBindings
 import com.script.rhino.RhinoScriptEngine
 import io.legado.app.constant.AppConst.UA_NAME
 import io.legado.app.constant.AppPattern
@@ -266,18 +266,19 @@ class AnalyzeUrl(
      * 执行JS
      */
     fun evalJS(jsStr: String, result: Any? = null): Any? {
-        val bindings = ScriptBindings()
-        bindings["java"] = this
-        bindings["baseUrl"] = baseUrl
-        bindings["cookie"] = CookieStore
-        bindings["cache"] = CacheManager
-        bindings["page"] = page
-        bindings["key"] = key
-        bindings["speakText"] = speakText
-        bindings["speakSpeed"] = speakSpeed
-        bindings["book"] = ruleData as? Book
-        bindings["source"] = source
-        bindings["result"] = result
+        val bindings = buildScriptBindings { bindings ->
+            bindings["java"] = this
+            bindings["baseUrl"] = baseUrl
+            bindings["cookie"] = CookieStore
+            bindings["cache"] = CacheManager
+            bindings["page"] = page
+            bindings["key"] = key
+            bindings["speakText"] = speakText
+            bindings["speakSpeed"] = speakSpeed
+            bindings["book"] = ruleData as? Book
+            bindings["source"] = source
+            bindings["result"] = result
+        }
         val scope = RhinoScriptEngine.getRuntimeScope(bindings)
         source?.getShareScope()?.let {
             scope.prototype = it

+ 17 - 12
app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt

@@ -20,6 +20,7 @@ import io.legado.app.utils.isTrue
 import io.legado.app.utils.mapAsync
 import kotlinx.coroutines.ensureActive
 import kotlinx.coroutines.flow.flow
+import org.mozilla.javascript.Context
 import splitties.init.appCtx
 import kotlin.coroutines.coroutineContext
 
@@ -126,21 +127,25 @@ object BookChapterList {
         }
         Debug.log(book.origin, "◇目录总数:${list.size}")
         coroutineContext.ensureActive()
-        val formatJs = tocRule.formatJs
-        val bindings = ScriptBindings()
-        bindings["gInt"] = 0
         list.forEachIndexed { index, bookChapter ->
             bookChapter.index = index
-            if (!formatJs.isNullOrBlank()) {
-                bindings["index"] = index + 1
-                bindings["chapter"] = bookChapter
-                bindings["title"] = bookChapter.title
-                RhinoScriptEngine.runCatching {
-                    eval(formatJs, bindings)?.toString()?.let {
-                        bookChapter.title = it
+        }
+        val formatJs = tocRule.formatJs
+        if (!formatJs.isNullOrBlank()) {
+            Context.enter().use {
+                val bindings = ScriptBindings()
+                bindings["gInt"] = 0
+                list.forEachIndexed { index, bookChapter ->
+                    bindings["index"] = index + 1
+                    bindings["chapter"] = bookChapter
+                    bindings["title"] = bookChapter.title
+                    RhinoScriptEngine.runCatching {
+                        eval(formatJs, bindings)?.toString()?.let {
+                            bookChapter.title = it
+                        }
+                    }.onFailure {
+                        Debug.log(book.origin, "格式化标题出错, ${it.localizedMessage}")
                     }
-                }.onFailure {
-                    Debug.log(book.origin, "格式化标题出错, ${it.localizedMessage}")
                 }
             }
         }

+ 0 - 1
gradle/libs.versions.toml

@@ -105,7 +105,6 @@ protobuf-javalite = { module = "com.google.protobuf:protobuf-javalite", version.
 
 quick-chinese-transfer-core = { module = "com.github.liuyueyi.quick-chinese-transfer:quick-transfer-core", version.ref = "quickChineseTransfer" }
 
-
 room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
 room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
 room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }

+ 4 - 0
modules/rhino/src/main/java/com/script/ScriptBindings.kt

@@ -39,4 +39,8 @@ class ScriptBindings : NativeObject() {
         }
     }
 
+    fun put(key: String, value: Any?) {
+        set(key, value)
+    }
+
 }

+ 14 - 0
modules/rhino/src/main/java/com/script/ScriptBindingsExtensions.kt

@@ -0,0 +1,14 @@
+package com.script
+
+import org.mozilla.javascript.Context
+
+inline fun buildScriptBindings(block: (bindings: ScriptBindings) -> Unit): ScriptBindings {
+    val bindings = ScriptBindings()
+    Context.enter()
+    try {
+        block(bindings)
+    } finally {
+        Context.exit()
+    }
+    return bindings
+}

+ 7 - 2
modules/rhino/src/main/java/com/script/rhino/RhinoScriptEngine.kt

@@ -55,7 +55,12 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
 
     fun eval(js: String, bindingsConfig: ScriptBindings.() -> Unit = {}): Any? {
         val bindings = ScriptBindings()
-        bindings.apply(bindingsConfig)
+        Context.enter()
+        try {
+            bindings.apply(bindingsConfig)
+        } finally {
+            Context.exit()
+        }
         return eval(js, bindings)
     }
 
@@ -249,7 +254,7 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
         return newScope
     }
 
-    override fun getRuntimeScope(bindings: ScriptBindings): ScriptBindings {
+    override fun getRuntimeScope(bindings: ScriptBindings): Scriptable {
         val cx = Context.enter()
         try {
             bindings.prototype = cx.initStandardObjects()