优化
This commit is contained in:
@@ -1,7 +0,0 @@
|
|||||||
package io.legado.app.constant
|
|
||||||
|
|
||||||
import com.script.rhino.RhinoScriptEngine
|
|
||||||
|
|
||||||
val SCRIPT_ENGINE: RhinoScriptEngine by lazy {
|
|
||||||
RhinoScriptEngine()
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,18 @@
|
|||||||
package io.legado.app.data.entities
|
package io.legado.app.data.entities
|
||||||
|
|
||||||
import cn.hutool.crypto.symmetric.AES
|
import cn.hutool.crypto.symmetric.AES
|
||||||
import com.script.SimpleBindings
|
|
||||||
import io.legado.app.constant.AppConst
|
import io.legado.app.constant.AppConst
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.constant.SCRIPT_ENGINE
|
|
||||||
import io.legado.app.data.entities.rule.RowUi
|
import io.legado.app.data.entities.rule.RowUi
|
||||||
import io.legado.app.help.CacheManager
|
import io.legado.app.help.CacheManager
|
||||||
import io.legado.app.help.JsExtensions
|
import io.legado.app.help.JsExtensions
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.help.http.CookieStore
|
import io.legado.app.help.http.CookieStore
|
||||||
import io.legado.app.model.SharedJsScope
|
import io.legado.app.model.SharedJsScope
|
||||||
|
import io.legado.app.rhino.Bindings
|
||||||
|
import io.legado.app.rhino.Rhino
|
||||||
|
import io.legado.app.rhino.evaluate
|
||||||
|
import io.legado.app.rhino.putBindings
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
import org.intellij.lang.annotations.Language
|
import org.intellij.lang.annotations.Language
|
||||||
import org.mozilla.javascript.Scriptable
|
import org.mozilla.javascript.Scriptable
|
||||||
@@ -227,19 +229,22 @@ interface BaseSource : JsExtensions {
|
|||||||
* 执行JS
|
* 执行JS
|
||||||
*/
|
*/
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun evalJS(jsStr: String, bindingsConfig: SimpleBindings.() -> Unit = {}): Any? {
|
fun evalJS(jsStr: String, bindingsConfig: Bindings.() -> Unit = {}): Any? {
|
||||||
val bindings = SimpleBindings()
|
val bindings = Bindings()
|
||||||
bindings.apply(bindingsConfig)
|
bindings.apply(bindingsConfig)
|
||||||
bindings["java"] = this
|
bindings["java"] = this
|
||||||
bindings["source"] = this
|
bindings["source"] = this
|
||||||
bindings["baseUrl"] = getKey()
|
bindings["baseUrl"] = getKey()
|
||||||
bindings["cookie"] = CookieStore
|
bindings["cookie"] = CookieStore
|
||||||
bindings["cache"] = CacheManager
|
bindings["cache"] = CacheManager
|
||||||
val scope = SCRIPT_ENGINE.getRuntimeScope(SCRIPT_ENGINE.getScriptContext(bindings))
|
return Rhino.use {
|
||||||
getShareScope()?.let {
|
val scope = initStandardObjects()
|
||||||
scope.prototype = it
|
scope.putBindings(bindings)
|
||||||
|
getShareScope()?.let {
|
||||||
|
scope.prototype = it
|
||||||
|
}
|
||||||
|
evaluate(scope, jsStr)
|
||||||
}
|
}
|
||||||
return SCRIPT_ENGINE.eval(jsStr, scope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getShareScope(): Scriptable? {
|
fun getShareScope(): Scriptable? {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
package io.legado.app.help.book
|
package io.legado.app.help.book
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.script.SimpleBindings
|
|
||||||
import io.legado.app.constant.*
|
import io.legado.app.constant.*
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.BaseBook
|
import io.legado.app.data.entities.BaseBook
|
||||||
@@ -11,6 +10,9 @@ import io.legado.app.data.entities.Book
|
|||||||
import io.legado.app.data.entities.BookSource
|
import io.legado.app.data.entities.BookSource
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
|
import io.legado.app.rhino.Bindings
|
||||||
|
import io.legado.app.rhino.Rhino
|
||||||
|
import io.legado.app.rhino.putBindings
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -234,11 +236,15 @@ fun Book.getExportFileName(suffix: String): String {
|
|||||||
if (jsStr.isNullOrBlank()) {
|
if (jsStr.isNullOrBlank()) {
|
||||||
return "$name 作者:${getRealAuthor()}.$suffix"
|
return "$name 作者:${getRealAuthor()}.$suffix"
|
||||||
}
|
}
|
||||||
val bindings = SimpleBindings()
|
val bindings = Bindings()
|
||||||
bindings["name"] = name
|
bindings["name"] = name
|
||||||
bindings["author"] = getRealAuthor()
|
bindings["author"] = getRealAuthor()
|
||||||
return kotlin.runCatching {
|
return kotlin.runCatching {
|
||||||
SCRIPT_ENGINE.eval(jsStr, bindings).toString() + "." + suffix
|
Rhino.use {
|
||||||
|
val scope = initStandardObjects()
|
||||||
|
scope.putBindings(bindings)
|
||||||
|
evaluateString(scope, jsStr, "name&author", 1, null)
|
||||||
|
}.toString() + "." + suffix
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
AppLog.put("导出书名规则错误,使用默认规则\n${it.localizedMessage}", it)
|
AppLog.put("导出书名规则错误,使用默认规则\n${it.localizedMessage}", it)
|
||||||
}.getOrDefault("${name} 作者:${getRealAuthor()}.$suffix")
|
}.getOrDefault("${name} 作者:${getRealAuthor()}.$suffix")
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package io.legado.app.model
|
package io.legado.app.model
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.script.SimpleBindings
|
|
||||||
import io.legado.app.constant.SCRIPT_ENGINE
|
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
import io.legado.app.help.http.newCallStrResponse
|
import io.legado.app.help.http.newCallStrResponse
|
||||||
import io.legado.app.help.http.okHttpClient
|
import io.legado.app.help.http.okHttpClient
|
||||||
@@ -33,9 +31,8 @@ object SharedJsScope {
|
|||||||
val key = MD5Utils.md5Encode(jsLib)
|
val key = MD5Utils.md5Encode(jsLib)
|
||||||
var scope = scopeMap[key]?.get()
|
var scope = scopeMap[key]?.get()
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
val context = SCRIPT_ENGINE.getScriptContext(SimpleBindings())
|
|
||||||
scope = SCRIPT_ENGINE.getRuntimeScope(context)
|
|
||||||
Rhino.use {
|
Rhino.use {
|
||||||
|
scope = initStandardObjects()
|
||||||
if (jsLib.isJsonObject()) {
|
if (jsLib.isJsonObject()) {
|
||||||
val jsMap: Map<String, String> = GSON.fromJson(
|
val jsMap: Map<String, String> = GSON.fromJson(
|
||||||
jsLib,
|
jsLib,
|
||||||
|
|||||||
@@ -2,14 +2,16 @@ package io.legado.app.model.analyzeRule
|
|||||||
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import com.script.SimpleBindings
|
|
||||||
import io.legado.app.constant.AppPattern.JS_PATTERN
|
import io.legado.app.constant.AppPattern.JS_PATTERN
|
||||||
import io.legado.app.constant.SCRIPT_ENGINE
|
|
||||||
import io.legado.app.data.entities.*
|
import io.legado.app.data.entities.*
|
||||||
import io.legado.app.help.CacheManager
|
import io.legado.app.help.CacheManager
|
||||||
import io.legado.app.help.JsExtensions
|
import io.legado.app.help.JsExtensions
|
||||||
import io.legado.app.help.http.CookieStore
|
import io.legado.app.help.http.CookieStore
|
||||||
import io.legado.app.model.webBook.WebBook
|
import io.legado.app.model.webBook.WebBook
|
||||||
|
import io.legado.app.rhino.Bindings
|
||||||
|
import io.legado.app.rhino.Rhino
|
||||||
|
import io.legado.app.rhino.evaluate
|
||||||
|
import io.legado.app.rhino.putBindings
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withTimeout
|
import kotlinx.coroutines.withTimeout
|
||||||
@@ -681,7 +683,7 @@ class AnalyzeRule(
|
|||||||
* 执行JS
|
* 执行JS
|
||||||
*/
|
*/
|
||||||
fun evalJS(jsStr: String, result: Any? = null): Any? {
|
fun evalJS(jsStr: String, result: Any? = null): Any? {
|
||||||
val bindings = SimpleBindings()
|
val bindings = Bindings()
|
||||||
bindings["java"] = this
|
bindings["java"] = this
|
||||||
bindings["cookie"] = CookieStore
|
bindings["cookie"] = CookieStore
|
||||||
bindings["cache"] = CacheManager
|
bindings["cache"] = CacheManager
|
||||||
@@ -693,12 +695,14 @@ class AnalyzeRule(
|
|||||||
bindings["title"] = chapter?.title
|
bindings["title"] = chapter?.title
|
||||||
bindings["src"] = content
|
bindings["src"] = content
|
||||||
bindings["nextChapterUrl"] = nextChapterUrl
|
bindings["nextChapterUrl"] = nextChapterUrl
|
||||||
val context = SCRIPT_ENGINE.getScriptContext(bindings)
|
return Rhino.use {
|
||||||
val scope = SCRIPT_ENGINE.getRuntimeScope(context)
|
val scope = initStandardObjects()
|
||||||
source?.getShareScope()?.let {
|
scope.putBindings(bindings)
|
||||||
scope.prototype = it
|
source?.getShareScope()?.let {
|
||||||
|
scope.prototype = it
|
||||||
|
}
|
||||||
|
evaluate(scope, jsStr)
|
||||||
}
|
}
|
||||||
return SCRIPT_ENGINE.eval(jsStr, scope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSource(): BaseSource? {
|
override fun getSource(): BaseSource? {
|
||||||
|
|||||||
@@ -5,12 +5,10 @@ import android.util.Base64
|
|||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import cn.hutool.core.util.HexUtil
|
import cn.hutool.core.util.HexUtil
|
||||||
import com.bumptech.glide.load.model.GlideUrl
|
import com.bumptech.glide.load.model.GlideUrl
|
||||||
import com.script.SimpleBindings
|
|
||||||
import io.legado.app.constant.AppConst.UA_NAME
|
import io.legado.app.constant.AppConst.UA_NAME
|
||||||
import io.legado.app.constant.AppPattern
|
import io.legado.app.constant.AppPattern
|
||||||
import io.legado.app.constant.AppPattern.JS_PATTERN
|
import io.legado.app.constant.AppPattern.JS_PATTERN
|
||||||
import io.legado.app.constant.AppPattern.dataUriRegex
|
import io.legado.app.constant.AppPattern.dataUriRegex
|
||||||
import io.legado.app.constant.SCRIPT_ENGINE
|
|
||||||
import io.legado.app.data.entities.BaseSource
|
import io.legado.app.data.entities.BaseSource
|
||||||
import io.legado.app.data.entities.Book
|
import io.legado.app.data.entities.Book
|
||||||
import io.legado.app.data.entities.BookChapter
|
import io.legado.app.data.entities.BookChapter
|
||||||
@@ -20,6 +18,10 @@ import io.legado.app.help.JsExtensions
|
|||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.help.glide.GlideHeaders
|
import io.legado.app.help.glide.GlideHeaders
|
||||||
import io.legado.app.help.http.*
|
import io.legado.app.help.http.*
|
||||||
|
import io.legado.app.rhino.Bindings
|
||||||
|
import io.legado.app.rhino.Rhino
|
||||||
|
import io.legado.app.rhino.evaluate
|
||||||
|
import io.legado.app.rhino.putBindings
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
@@ -253,7 +255,7 @@ class AnalyzeUrl(
|
|||||||
* 执行JS
|
* 执行JS
|
||||||
*/
|
*/
|
||||||
fun evalJS(jsStr: String, result: Any? = null): Any? {
|
fun evalJS(jsStr: String, result: Any? = null): Any? {
|
||||||
val bindings = SimpleBindings()
|
val bindings = Bindings()
|
||||||
bindings["java"] = this
|
bindings["java"] = this
|
||||||
bindings["baseUrl"] = baseUrl
|
bindings["baseUrl"] = baseUrl
|
||||||
bindings["cookie"] = CookieStore
|
bindings["cookie"] = CookieStore
|
||||||
@@ -265,12 +267,14 @@ class AnalyzeUrl(
|
|||||||
bindings["book"] = ruleData as? Book
|
bindings["book"] = ruleData as? Book
|
||||||
bindings["source"] = source
|
bindings["source"] = source
|
||||||
bindings["result"] = result
|
bindings["result"] = result
|
||||||
val context = SCRIPT_ENGINE.getScriptContext(bindings)
|
return Rhino.use {
|
||||||
val scope = SCRIPT_ENGINE.getRuntimeScope(context)
|
val scope = initStandardObjects()
|
||||||
source?.getShareScope()?.let {
|
scope.putBindings(bindings)
|
||||||
scope.prototype = it
|
source?.getShareScope()?.let {
|
||||||
|
scope.prototype = it
|
||||||
|
}
|
||||||
|
evaluate(scope, jsStr)
|
||||||
}
|
}
|
||||||
return SCRIPT_ENGINE.eval(jsStr, scope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun put(key: String, value: String): String {
|
fun put(key: String, value: String): String {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package io.legado.app.model.localBook
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import com.script.SimpleBindings
|
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.constant.*
|
import io.legado.app.constant.*
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
@@ -20,6 +19,9 @@ import io.legado.app.help.config.AppConfig
|
|||||||
import io.legado.app.lib.webdav.WebDav
|
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.evaluate
|
||||||
|
import io.legado.app.rhino.putBinding
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.jsoup.nodes.Entities
|
import org.jsoup.nodes.Entities
|
||||||
@@ -265,13 +267,15 @@ object LocalBook {
|
|||||||
var author = ""
|
var author = ""
|
||||||
if (!AppConfig.bookImportFileName.isNullOrBlank()) {
|
if (!AppConfig.bookImportFileName.isNullOrBlank()) {
|
||||||
try {
|
try {
|
||||||
|
//在用户脚本后添加捕获author、name的代码,只要脚本中author、name有值就会被捕获
|
||||||
|
val js =
|
||||||
|
AppConfig.bookImportFileName + "\nJSON.stringify({author:author,name:name})"
|
||||||
//在脚本中定义如何分解文件名成书名、作者名
|
//在脚本中定义如何分解文件名成书名、作者名
|
||||||
val jsonStr = SCRIPT_ENGINE.eval(
|
val jsonStr = Rhino.use {
|
||||||
//在用户脚本后添加捕获author、name的代码,只要脚本中author、name有值就会被捕获
|
val scope = initStandardObjects()
|
||||||
AppConfig.bookImportFileName + "\nJSON.stringify({author:author,name:name})",
|
scope.putBinding("src", tempFileName)
|
||||||
//将文件名注入到脚本的src变量中
|
evaluate(scope, js)
|
||||||
SimpleBindings().also { it["src"] = tempFileName }
|
}.toString()
|
||||||
).toString()
|
|
||||||
val bookMess = GSON.fromJsonObject<HashMap<String, String>>(jsonStr)
|
val bookMess = GSON.fromJsonObject<HashMap<String, String>>(jsonStr)
|
||||||
.getOrThrow()
|
.getOrThrow()
|
||||||
name = bookMess["name"] ?: ""
|
name = bookMess["name"] ?: ""
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Decompiled with CFR 0.152.
|
||||||
|
*/
|
||||||
|
package io.legado.app.rhino
|
||||||
|
|
||||||
|
class Bindings @JvmOverloads constructor(
|
||||||
|
private val map: MutableMap<String, Any?> = HashMap()
|
||||||
|
) : MutableMap<String, Any?> {
|
||||||
|
|
||||||
|
override fun put(key: String, value: Any?): Any? {
|
||||||
|
return map.put(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun putAll(from: Map<out String, Any?>) {
|
||||||
|
map.putAll(from)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
map.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun containsKey(key: String): Boolean {
|
||||||
|
return map.containsKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun containsValue(value: Any?): Boolean {
|
||||||
|
return map.containsValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val entries: MutableSet<MutableMap.MutableEntry<String, Any?>>
|
||||||
|
get() = map.entries
|
||||||
|
|
||||||
|
override operator fun get(key: String): Any? {
|
||||||
|
return map[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean {
|
||||||
|
return map.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val keys: MutableSet<String>
|
||||||
|
get() = map.keys
|
||||||
|
|
||||||
|
override fun remove(key: String): Any? {
|
||||||
|
return map.remove(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val size: Int
|
||||||
|
get() = map.size
|
||||||
|
|
||||||
|
override val values: MutableCollection<Any?>
|
||||||
|
get() = map.values
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,11 +8,10 @@ import org.mozilla.javascript.Wrapper
|
|||||||
|
|
||||||
object Rhino {
|
object Rhino {
|
||||||
|
|
||||||
inline fun use(block: Context.() -> Any?): Any? {
|
inline fun <T> use(block: Context.() -> T): T {
|
||||||
return try {
|
return try {
|
||||||
val cx = Context.enter()
|
val cx = Context.enter()
|
||||||
val result = block.invoke(cx)
|
block.invoke(cx)
|
||||||
unwrapReturnValue(result)
|
|
||||||
} finally {
|
} finally {
|
||||||
Context.exit()
|
Context.exit()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,56 @@ 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.evaluateString(scope: Scriptable, source: String, sourceName: String) {
|
fun Context.evaluate(
|
||||||
evaluateString(scope, source, sourceName, 1, null)
|
scope: Scriptable,
|
||||||
|
source: String,
|
||||||
|
sourceName: String = "<Unknown source>",
|
||||||
|
lineno: Int = 1,
|
||||||
|
securityDomain: Any? = null
|
||||||
|
): Any? {
|
||||||
|
return Rhino.unwrapReturnValue(
|
||||||
|
evaluateString(scope, source, sourceName, lineno, securityDomain)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.evaluateReader(scope: Scriptable, reader: Reader, sourceName: String) {
|
fun Context.evaluate(
|
||||||
evaluateReader(scope, reader, sourceName, 1, null)
|
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(
|
||||||
|
scope: Scriptable,
|
||||||
|
reader: Reader,
|
||||||
|
sourceName: String = "<Unknown source>",
|
||||||
|
lineno: Int = 1,
|
||||||
|
securityDomain: Any? = null
|
||||||
|
): Any? {
|
||||||
|
return Rhino.unwrapReturnValue(
|
||||||
|
evaluateReader(scope, reader, sourceName, lineno, securityDomain)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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?) {
|
||||||
@@ -20,7 +64,7 @@ fun Scriptable.putBinding(key: String, value: Any?) {
|
|||||||
ScriptableObject.putProperty(this, key, wrappedOut)
|
ScriptableObject.putProperty(this, key, wrappedOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Scriptable.putBindings(bindings: Map<String, Any?>) {
|
fun Scriptable.putBindings(bindings: Bindings) {
|
||||||
bindings.forEach { (t, u) ->
|
bindings.forEach { (t, u) ->
|
||||||
putBinding(t, u)
|
putBinding(t, u)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
package io.legado.app.utils
|
package io.legado.app.utils
|
||||||
|
|
||||||
import com.script.SimpleBindings
|
|
||||||
import io.legado.app.constant.AppPattern.EXP_PATTERN
|
import io.legado.app.constant.AppPattern.EXP_PATTERN
|
||||||
import io.legado.app.constant.SCRIPT_ENGINE
|
import io.legado.app.rhino.Bindings
|
||||||
|
import io.legado.app.rhino.Rhino
|
||||||
|
import io.legado.app.rhino.evaluate
|
||||||
|
|
||||||
object JsUtils {
|
object JsUtils {
|
||||||
|
|
||||||
fun evalJs(js: String, bindingsFun: ((SimpleBindings) -> Unit)? = null): String {
|
fun evalJs(js: String, bindingsFun: ((Bindings) -> Unit)? = null): String {
|
||||||
val bindings = SimpleBindings()
|
val bindings = Bindings()
|
||||||
bindingsFun?.invoke(bindings)
|
bindingsFun?.invoke(bindings)
|
||||||
if (js.contains("{{") && js.contains("}}")) {
|
if (js.contains("{{") && js.contains("}}")) {
|
||||||
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 {
|
||||||
SCRIPT_ENGINE.eval(it, bindings)
|
Rhino.use {
|
||||||
|
evaluate(bindings, it)
|
||||||
|
}
|
||||||
} ?: ""
|
} ?: ""
|
||||||
if (result is String) {
|
if (result is String) {
|
||||||
expMatcher.appendReplacement(sb, result)
|
expMatcher.appendReplacement(sb, result)
|
||||||
@@ -27,7 +30,9 @@ object JsUtils {
|
|||||||
expMatcher.appendTail(sb)
|
expMatcher.appendTail(sb)
|
||||||
return sb.toString()
|
return sb.toString()
|
||||||
}
|
}
|
||||||
return SCRIPT_ENGINE.eval(js, bindings).toString()
|
return Rhino.use {
|
||||||
|
evaluate(bindings, js)
|
||||||
|
}.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package io.legado.app.utils
|
package io.legado.app.utils
|
||||||
|
|
||||||
import androidx.core.os.postDelayed
|
import androidx.core.os.postDelayed
|
||||||
import com.script.SimpleBindings
|
|
||||||
import io.legado.app.constant.SCRIPT_ENGINE
|
|
||||||
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.evaluate
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import splitties.init.appCtx
|
import splitties.init.appCtx
|
||||||
@@ -30,10 +31,11 @@ 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 = SimpleBindings()
|
val bindings = Bindings()
|
||||||
bindings["result"] = matcher.group()
|
bindings["result"] = matcher.group()
|
||||||
val jsResult =
|
val jsResult = Rhino.use {
|
||||||
SCRIPT_ENGINE.eval(replacement1, bindings).toString()
|
evaluate(bindings, replacement1)
|
||||||
|
}.toString()
|
||||||
matcher.appendReplacement(stringBuffer, jsResult)
|
matcher.appendReplacement(stringBuffer, jsResult)
|
||||||
} else {
|
} else {
|
||||||
matcher.appendReplacement(stringBuffer, replacement1)
|
matcher.appendReplacement(stringBuffer, replacement1)
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package io.legado.app
|
package io.legado.app
|
||||||
|
|
||||||
import com.script.SimpleBindings
|
import com.script.SimpleBindings
|
||||||
import io.legado.app.constant.SCRIPT_ENGINE
|
|
||||||
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.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
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mozilla.javascript.Scriptable
|
|
||||||
|
|
||||||
class JsTest {
|
class JsTest {
|
||||||
|
|
||||||
@@ -56,7 +55,7 @@ class JsTest {
|
|||||||
val scope = initStandardObjects()
|
val scope = initStandardObjects()
|
||||||
evaluateString(scope, printJs, "print", 1, null)
|
evaluateString(scope, printJs, "print", 1, null)
|
||||||
scope
|
scope
|
||||||
} as Scriptable
|
}
|
||||||
|
|
||||||
@Language("js")
|
@Language("js")
|
||||||
val jsFor = """
|
val jsFor = """
|
||||||
@@ -85,7 +84,9 @@ class JsTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testReturnNull() {
|
fun testReturnNull() {
|
||||||
val result = SCRIPT_ENGINE.eval("null")
|
val result = Rhino.use {
|
||||||
|
evaluate(initStandardObjects(), "null")
|
||||||
|
}
|
||||||
Assert.assertEquals(null, result)
|
Assert.assertEquals(null, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,9 +102,11 @@ class JsTest {
|
|||||||
.replace(/\;/g,";")
|
.replace(/\;/g,";")
|
||||||
.replace(/\:/g,":")
|
.replace(/\:/g,":")
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val bindings = SimpleBindings()
|
val result = Rhino.use {
|
||||||
bindings["result"] = ",.!?…;:"
|
val scope = initStandardObjects()
|
||||||
val result = SCRIPT_ENGINE.eval(js, bindings).toString()
|
scope.putBinding("result", ",.!?…;:")
|
||||||
|
evaluate(scope, js)
|
||||||
|
}
|
||||||
Assert.assertEquals(result, ",。!?……;:")
|
Assert.assertEquals(result, ",。!?……;:")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,22 +118,29 @@ class JsTest {
|
|||||||
bindings["chapter"] = chapter
|
bindings["chapter"] = chapter
|
||||||
@Language("js")
|
@Language("js")
|
||||||
val js = "chapter.title"
|
val js = "chapter.title"
|
||||||
val result = SCRIPT_ENGINE.eval(js, bindings)
|
val result = Rhino.use {
|
||||||
|
val scope = initStandardObjects()
|
||||||
|
scope.putBinding("chapter", chapter)
|
||||||
|
evaluate(scope, js)
|
||||||
|
}
|
||||||
Assert.assertEquals(result, "xxxyyy")
|
Assert.assertEquals(result, "xxxyyy")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun javaListForEach() {
|
fun javaListForEach() {
|
||||||
val list = arrayListOf(1, 2, 3)
|
val list = arrayListOf(1, 2, 3)
|
||||||
val bindings = SimpleBindings()
|
|
||||||
bindings["list"] = list
|
|
||||||
@Language("js")
|
@Language("js")
|
||||||
val js = """
|
val js = """
|
||||||
var result = 0
|
var result = 0
|
||||||
list.forEach(item => {result = result + item})
|
list.forEach(item => {result = result + item})
|
||||||
result
|
result
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
val result = SCRIPT_ENGINE.eval(js, bindings)
|
val result = Rhino.use {
|
||||||
|
val scope = initStandardObjects()
|
||||||
|
scope.putBinding("list", list)
|
||||||
|
evaluate(scope, js)
|
||||||
|
}
|
||||||
Assert.assertEquals(result, 6.0)
|
Assert.assertEquals(result, 6.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user