This commit is contained in:
Horis
2024-07-31 19:20:55 +08:00
parent be9320124d
commit 0fea035a05
9 changed files with 95 additions and 60 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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}")
}
}
}

View File

@@ -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" }

View File

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

View File

@@ -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
}

View File

@@ -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()