This commit is contained in:
Horis
2025-03-25 22:53:42 +08:00
parent 2e7b878f1a
commit b07b9dcf77
31 changed files with 178 additions and 78 deletions
+2
View File
@@ -12,6 +12,7 @@ import android.os.Build
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.jeremyliao.liveeventbus.logger.DefaultLogger import com.jeremyliao.liveeventbus.logger.DefaultLogger
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
@@ -77,6 +78,7 @@ class App : Application() {
Coroutine.async { Coroutine.async {
URL.setURLStreamHandlerFactory(ObsoleteUrlFactory(okHttpClient)) URL.setURLStreamHandlerFactory(ObsoleteUrlFactory(okHttpClient))
launch { installGmsTlsProvider(appCtx) } launch { installGmsTlsProvider(appCtx) }
RhinoScriptEngine
//初始化封面 //初始化封面
BookCover.toString() BookCover.toString()
//清除过期数据 //清除过期数据
@@ -5,6 +5,7 @@ import androidx.room.Entity
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import io.legado.app.model.analyzeRule.AnalyzeRule import io.legado.app.model.analyzeRule.AnalyzeRule
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import kotlin.coroutines.coroutineContext
/** /**
* 字典规则 * 字典规则
@@ -36,12 +37,12 @@ data class DictRule(
* 搜索字典 * 搜索字典
*/ */
suspend fun search(word: String): String { suspend fun search(word: String): String {
val analyzeUrl = AnalyzeUrl(urlRule, key = word) val analyzeUrl = AnalyzeUrl(urlRule, key = word, coroutineContext = coroutineContext)
val body = analyzeUrl.getStrResponseAwait().body val body = analyzeUrl.getStrResponseAwait().body
if (showRule.isBlank()) { if (showRule.isBlank()) {
return body!! return body!!
} }
val analyzeRule = AnalyzeRule() val analyzeRule = AnalyzeRule().setCoroutineContext(coroutineContext)
return analyzeRule.getString(showRule, mContent = body) return analyzeRule.getString(showRule, mContent = body)
} }
@@ -14,6 +14,7 @@ import io.legado.app.utils.fromJsonArray
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
import splitties.init.appCtx import splitties.init.appCtx
import java.io.File import java.io.File
import kotlin.coroutines.coroutineContext
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
object DirectLinkUpload { object DirectLinkUpload {
@@ -60,6 +61,7 @@ object DirectLinkUpload {
mFile.delete() mFile.delete()
} }
val analyzeRule = AnalyzeRule().setContent(res.body, res.url) val analyzeRule = AnalyzeRule().setContent(res.body, res.url)
.setCoroutineContext(coroutineContext)
val downloadUrl = analyzeRule.getString(downloadUrlRule) val downloadUrl = analyzeRule.getString(downloadUrlRule)
if (downloadUrl.isBlank()) { if (downloadUrl.isBlank()) {
throw NoStackTraceException("上传失败,${res.body}") throw NoStackTraceException("上传失败,${res.body}")
@@ -28,6 +28,7 @@ import io.legado.app.utils.getFile
import io.legado.app.utils.isContentScheme import io.legado.app.utils.isContentScheme
import io.legado.app.utils.onEachParallel import io.legado.app.utils.onEachParallel
import io.legado.app.utils.postEvent import io.legado.app.utils.postEvent
import io.legado.app.utils.runScriptWithContext
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
@@ -232,12 +233,16 @@ object BookHelp {
if (isImageExist(book, src)) { if (isImageExist(book, src)) {
return return
} }
val analyzeUrl = AnalyzeUrl(src, source = bookSource) val analyzeUrl = AnalyzeUrl(
src, source = bookSource, coroutineContext = coroutineContext
)
val bytes = analyzeUrl.getByteArrayAwait() val bytes = analyzeUrl.getByteArrayAwait()
//某些图片被加密,需要进一步解密 //某些图片被加密,需要进一步解密
ImageUtils.decode( runScriptWithContext {
src, bytes, isCover = false, bookSource, book ImageUtils.decode(
)?.let { src, bytes, isCover = false, bookSource, book
)
}?.let {
if (!checkImage(it)) { if (!checkImage(it)) {
// 如果部分图片失效,每次进入正文都会花很长时间再次获取图片数据 // 如果部分图片失效,每次进入正文都会花很长时间再次获取图片数据
// 所以无论如何都要将数据写入到文件里 // 所以无论如何都要将数据写入到文件里
@@ -546,12 +551,16 @@ object BookHelp {
} }
private val chapterNamePattern1 by lazy { private val chapterNamePattern1 by lazy {
Pattern.compile(".*?第([\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)[章节篇回集话]") Pattern.compile(
".*?第([\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)[章节篇回集话]"
)
} }
@Suppress("RegExpSimplifiable") @Suppress("RegExpSimplifiable")
private val chapterNamePattern2 by lazy { private val chapterNamePattern2 by lazy {
Pattern.compile("^(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+[,:、])*([\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)(?:[,:、]|\\.[^\\d])") Pattern.compile(
"^(?:[\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+[,:、])*([\\d零〇一二两三四五六七八九十百千万壹贰叁肆伍陆柒捌玖拾佰仟]+)(?:[,:、]|\\.[^\\d])"
)
} }
private val regexA by lazy { private val regexA by lazy {
@@ -12,6 +12,8 @@ import io.legado.app.exception.NoStackTraceException
import io.legado.app.model.ReadManga import io.legado.app.model.ReadManga
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.utils.ImageUtils import io.legado.app.utils.ImageUtils
import io.legado.app.utils.runScriptWithContext
import kotlinx.coroutines.Job
import java.io.InputStream import java.io.InputStream
class LegadoDataUrlLoader : ModelLoader<String, InputStream> { class LegadoDataUrlLoader : ModelLoader<String, InputStream> {
@@ -33,15 +35,23 @@ class LegadoDataUrlLoader : ModelLoader<String, InputStream> {
} }
class LegadoDataUrlFetcher(private val model: String) : DataFetcher<InputStream> { class LegadoDataUrlFetcher(private val model: String) : DataFetcher<InputStream> {
private val coroutineContext = Job()
override fun loadData( override fun loadData(
priority: Priority, priority: Priority,
callback: DataFetcher.DataCallback<in InputStream> callback: DataFetcher.DataCallback<in InputStream>
) { ) {
try { try {
val bytes = AnalyzeUrl(model, source = ReadManga.bookSource).getByteArray() val bytes = AnalyzeUrl(
val decoded = ImageUtils.decode( model, source = ReadManga.bookSource,
model, bytes, isCover = false, ReadManga.bookSource, ReadManga.book coroutineContext = coroutineContext
)?.inputStream() ).getByteArray()
val decoded = runScriptWithContext(coroutineContext) {
ImageUtils.decode(
model, bytes, isCover = false, ReadManga.bookSource, ReadManga.book
)?.inputStream()
}
if (decoded == null) { if (decoded == null) {
throw NoStackTraceException("漫画图片解密失败") throw NoStackTraceException("漫画图片解密失败")
} }
@@ -56,7 +66,7 @@ class LegadoDataUrlLoader : ModelLoader<String, InputStream> {
} }
override fun cancel() { override fun cancel() {
// do nothing coroutineContext.cancel()
} }
override fun getDataClass(): Class<InputStream> { override fun getDataClass(): Class<InputStream> {
@@ -17,6 +17,8 @@ import io.legado.app.help.source.SourceHelp
import io.legado.app.model.ReadManga import io.legado.app.model.ReadManga
import io.legado.app.utils.ImageUtils import io.legado.app.utils.ImageUtils
import io.legado.app.utils.isWifiConnect import io.legado.app.utils.isWifiConnect
import io.legado.app.utils.runScriptWithContext
import kotlinx.coroutines.Job
import okhttp3.Call import okhttp3.Call
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@@ -38,6 +40,7 @@ class OkHttpStreamFetcher(
private var callback: DataFetcher.DataCallback<in InputStream>? = null private var callback: DataFetcher.DataCallback<in InputStream>? = null
private var source: BaseSource? = null private var source: BaseSource? = null
private val manga = options.get(OkHttpModelLoader.mangaOption) == true private val manga = options.get(OkHttpModelLoader.mangaOption) == true
private val coroutineContext = Job()
@Volatile @Volatile
private var call: Call? = null private var call: Call? = null
@@ -89,6 +92,7 @@ class OkHttpStreamFetcher(
override fun cancel() { override fun cancel() {
call?.cancel() call?.cancel()
coroutineContext.cancel()
} }
override fun getDataClass(): Class<InputStream> { override fun getDataClass(): Class<InputStream> {
@@ -106,19 +110,21 @@ class OkHttpStreamFetcher(
override fun onResponse(call: Call, response: Response) { override fun onResponse(call: Call, response: Response) {
responseBody = response.body responseBody = response.body
if (response.isSuccessful) { if (response.isSuccessful) {
val decodeResult = if (manga) { val decodeResult = runScriptWithContext(coroutineContext) {
ImageUtils.decode( if (manga) {
oldUrl.toString(), ImageUtils.decode(
responseBody!!.bytes(), oldUrl.toString(),
isCover = false, responseBody!!.bytes(),
source, isCover = false,
ReadManga.book source,
)?.inputStream() ReadManga.book
} else { )?.inputStream()
ImageUtils.decode( } else {
url.toStringUrl(), responseBody!!.byteStream(), ImageUtils.decode(
isCover = true, source url.toStringUrl(), responseBody!!.byteStream(),
) isCover = true, source
)
}
} }
if (decodeResult == null) { if (decodeResult == null) {
callback?.onLoadFailed(NoStackTraceException("封面二次解密失败")) callback?.onLoadFailed(NoStackTraceException("封面二次解密失败"))
@@ -11,6 +11,7 @@ import io.legado.app.utils.MD5Utils
import io.legado.app.utils.fromJsonArray import io.legado.app.utils.fromJsonArray
import io.legado.app.utils.isJsonArray import io.legado.app.utils.isJsonArray
import io.legado.app.utils.printOnDebug import io.legado.app.utils.printOnDebug
import io.legado.app.utils.runScriptWithContext
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
@@ -61,7 +62,9 @@ suspend fun BookSource.exploreKinds(): List<ExploreKind> {
} else { } else {
exploreUrl.substring(4, exploreUrl.lastIndexOf("<")) exploreUrl.substring(4, exploreUrl.lastIndexOf("<"))
} }
ruleStr = evalJS(jsStr).toString().trim() ruleStr = runScriptWithContext {
evalJS(jsStr).toString().trim()
}
aCache.put(exploreKindsKey, ruleStr) aCache.put(exploreKindsKey, ruleStr)
} }
} }
@@ -4,6 +4,7 @@ import io.legado.app.data.entities.RssSource
import io.legado.app.utils.ACache import io.legado.app.utils.ACache
import io.legado.app.utils.MD5Utils import io.legado.app.utils.MD5Utils
import io.legado.app.utils.NetworkUtils import io.legado.app.utils.NetworkUtils
import io.legado.app.utils.runScriptWithContext
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@@ -29,7 +30,9 @@ suspend fun RssSource.sortUrls(): List<Pair<String, String>> {
} else { } else {
sortUrl!!.substring(4, sortUrl!!.lastIndexOf("<")) sortUrl!!.substring(4, sortUrl!!.lastIndexOf("<"))
} }
str = evalJS(jsStr).toString() str = runScriptWithContext {
evalJS(jsStr).toString()
}
aCache.put(sortUrlsKey, str) aCache.put(sortUrlsKey, str)
} }
} }
@@ -84,7 +84,6 @@ object SourceVerificationHelp {
putExtra("sourceName", source.getTag()) putExtra("sourceName", source.getTag())
putExtra("sourceVerificationEnable", saveResult) putExtra("sourceVerificationEnable", saveResult)
putExtra("refetchAfterSuccess", refetchAfterSuccess) putExtra("refetchAfterSuccess", refetchAfterSuccess)
IntentData.put(url, source.getHeaderMap(true))
IntentData.put(getVerificationResultKey(source), Thread.currentThread()) IntentData.put(getVerificationResultKey(source), Thread.currentThread())
} }
} }
@@ -31,6 +31,7 @@ import io.legado.app.utils.getPrefBoolean
import io.legado.app.utils.getPrefString import io.legado.app.utils.getPrefString
import splitties.init.appCtx import splitties.init.appCtx
import java.io.File import java.io.File
import kotlin.coroutines.coroutineContext
@Keep @Keep
object BookCover { object BookCover {
@@ -174,10 +175,12 @@ object BookCover {
config.searchUrl, config.searchUrl,
book.name, book.name,
source = config, source = config,
headerMapF = config.getHeaderMap() coroutineContext = coroutineContext,
hasLoginHeader = false
) )
val res = analyzeUrl.getStrResponseAwait() val res = analyzeUrl.getStrResponseAwait()
val analyzeRule = AnalyzeRule(book) val analyzeRule = AnalyzeRule(book)
analyzeRule.setCoroutineContext(coroutineContext)
analyzeRule.setContent(res.body) analyzeRule.setContent(res.body)
analyzeRule.setRedirectUrl(res.url) analyzeRule.setRedirectUrl(res.url)
return analyzeRule.getString(config.coverRule, isUrl = true) return analyzeRule.getString(config.coverRule, isUrl = true)
@@ -45,6 +45,7 @@ import io.legado.app.utils.isJson
import io.legado.app.utils.isJsonArray import io.legado.app.utils.isJsonArray
import io.legado.app.utils.isJsonObject import io.legado.app.utils.isJsonObject
import io.legado.app.utils.isXml import io.legado.app.utils.isXml
import io.legado.app.utils.runScriptWithContext
import io.legado.app.utils.splitNotBlank import io.legado.app.utils.splitNotBlank
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
@@ -81,6 +82,7 @@ class AnalyzeUrl(
private val readTimeout: Long? = null, private val readTimeout: Long? = null,
private var coroutineContext: CoroutineContext = EmptyCoroutineContext, private var coroutineContext: CoroutineContext = EmptyCoroutineContext,
headerMapF: Map<String, String>? = null, headerMapF: Map<String, String>? = null,
hasLoginHeader: Boolean = true
) : JsExtensions { ) : JsExtensions {
companion object { companion object {
val paramPattern: Pattern = Pattern.compile("\\s*,\\s*(?=\\{)") val paramPattern: Pattern = Pattern.compile("\\s*,\\s*(?=\\{)")
@@ -118,7 +120,9 @@ class AnalyzeUrl(
coroutineContext = coroutineContext.minusKey(ContinuationInterceptor) coroutineContext = coroutineContext.minusKey(ContinuationInterceptor)
val urlMatcher = paramPattern.matcher(baseUrl) val urlMatcher = paramPattern.matcher(baseUrl)
if (urlMatcher.find()) baseUrl = baseUrl.substring(0, urlMatcher.start()) if (urlMatcher.find()) baseUrl = baseUrl.substring(0, urlMatcher.start())
(headerMapF ?: source?.getHeaderMap(true))?.let { (headerMapF ?: runScriptWithContext(coroutineContext) {
source?.getHeaderMap(hasLoginHeader)
})?.let {
headerMap.putAll(it) headerMap.putAll(it)
if (it.containsKey("proxy")) { if (it.containsKey("proxy")) {
proxy = it["proxy"] proxy = it["proxy"]
@@ -12,6 +12,7 @@ import io.legado.app.utils.NetworkUtils
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
object Rss { object Rss {
@@ -41,7 +42,8 @@ object Rss {
page = page, page = page,
source = rssSource, source = rssSource,
ruleData = ruleData, ruleData = ruleData,
headerMapF = rssSource.getHeaderMap() coroutineContext = coroutineContext,
hasLoginHeader = false
) )
val res = analyzeUrl.getStrResponseAwait() val res = analyzeUrl.getStrResponseAwait()
checkRedirect(rssSource, res) checkRedirect(rssSource, res)
@@ -70,7 +72,8 @@ object Rss {
baseUrl = rssArticle.origin, baseUrl = rssArticle.origin,
source = rssSource, source = rssSource,
ruleData = rssArticle, ruleData = rssArticle,
headerMapF = rssSource.getHeaderMap() coroutineContext = coroutineContext,
hasLoginHeader = false
) )
val res = analyzeUrl.getStrResponseAwait() val res = analyzeUrl.getStrResponseAwait()
checkRedirect(rssSource, res) checkRedirect(rssSource, res)
@@ -79,6 +82,7 @@ object Rss {
val analyzeRule = AnalyzeRule(rssArticle, rssSource) val analyzeRule = AnalyzeRule(rssArticle, rssSource)
analyzeRule.setContent(res.body) analyzeRule.setContent(res.body)
.setBaseUrl(NetworkUtils.getAbsoluteURL(rssArticle.origin, rssArticle.link)) .setBaseUrl(NetworkUtils.getAbsoluteURL(rssArticle.origin, rssArticle.link))
.setCoroutineContext(coroutineContext)
.setRedirectUrl(res.url) .setRedirectUrl(res.url)
return analyzeRule.getString(ruleContent) return analyzeRule.getString(ruleContent)
} }
@@ -11,12 +11,13 @@ import io.legado.app.model.analyzeRule.RuleData
import io.legado.app.utils.NetworkUtils import io.legado.app.utils.NetworkUtils
import splitties.init.appCtx import splitties.init.appCtx
import java.util.Locale import java.util.Locale
import kotlin.coroutines.coroutineContext
@Keep @Keep
object RssParserByRule { object RssParserByRule {
@Throws(Exception::class) @Throws(Exception::class)
fun parseXML( suspend fun parseXML(
sortName: String, sortName: String,
sortUrl: String, sortUrl: String,
redirectUrl: String, redirectUrl: String,
@@ -40,6 +41,7 @@ object RssParserByRule {
} else { } else {
val articleList = mutableListOf<RssArticle>() val articleList = mutableListOf<RssArticle>()
val analyzeRule = AnalyzeRule(ruleData, rssSource) val analyzeRule = AnalyzeRule(ruleData, rssSource)
analyzeRule.setCoroutineContext(coroutineContext)
analyzeRule.setContent(body).setBaseUrl(sortUrl) analyzeRule.setContent(body).setBaseUrl(sortUrl)
analyzeRule.setRedirectUrl(redirectUrl) analyzeRule.setRedirectUrl(redirectUrl)
var reverse = false var reverse = false
@@ -70,7 +70,6 @@ object BookChapterList {
mUrl = nextUrl, mUrl = nextUrl,
source = bookSource, source = bookSource,
ruleData = book, ruleData = book,
headerMapF = bookSource.getHeaderMap(),
coroutineContext = coroutineContext coroutineContext = coroutineContext
) )
val res = analyzeUrl.getStrResponseAwait() //控制并发访问 val res = analyzeUrl.getStrResponseAwait() //控制并发访问
@@ -100,7 +99,6 @@ object BookChapterList {
mUrl = urlStr, mUrl = urlStr,
source = bookSource, source = bookSource,
ruleData = book, ruleData = book,
headerMapF = bookSource.getHeaderMap(),
coroutineContext = coroutineContext coroutineContext = coroutineContext
) )
val res = analyzeUrl.getStrResponseAwait() //控制并发访问 val res = analyzeUrl.getStrResponseAwait() //控制并发访问
@@ -90,7 +90,6 @@ object BookContent {
mUrl = nextUrl, mUrl = nextUrl,
source = bookSource, source = bookSource,
ruleData = book, ruleData = book,
headerMapF = bookSource.getHeaderMap(),
coroutineContext = coroutineContext coroutineContext = coroutineContext
) )
val res = analyzeUrl.getStrResponseAwait() //控制并发访问 val res = analyzeUrl.getStrResponseAwait() //控制并发访问
@@ -118,7 +117,6 @@ object BookContent {
mUrl = urlStr, mUrl = urlStr,
source = bookSource, source = bookSource,
ruleData = book, ruleData = book,
headerMapF = bookSource.getHeaderMap(),
coroutineContext = coroutineContext coroutineContext = coroutineContext
) )
val res = analyzeUrl.getStrResponseAwait() //控制并发访问 val res = analyzeUrl.getStrResponseAwait() //控制并发访问
@@ -62,7 +62,6 @@ object WebBook {
key = key, key = key,
page = page, page = page,
baseUrl = bookSource.bookSourceUrl, baseUrl = bookSource.bookSourceUrl,
headerMapF = bookSource.getHeaderMap(true),
source = bookSource, source = bookSource,
ruleData = ruleData, ruleData = ruleData,
coroutineContext = coroutineContext coroutineContext = coroutineContext
@@ -115,7 +114,6 @@ object WebBook {
baseUrl = bookSource.bookSourceUrl, baseUrl = bookSource.bookSourceUrl,
source = bookSource, source = bookSource,
ruleData = ruleData, ruleData = ruleData,
headerMapF = bookSource.getHeaderMap(true),
coroutineContext = coroutineContext coroutineContext = coroutineContext
) )
var res = analyzeUrl.getStrResponseAwait() var res = analyzeUrl.getStrResponseAwait()
@@ -173,7 +171,6 @@ object WebBook {
baseUrl = bookSource.bookSourceUrl, baseUrl = bookSource.bookSourceUrl,
source = bookSource, source = bookSource,
ruleData = book, ruleData = book,
headerMapF = bookSource.getHeaderMap(true),
coroutineContext = coroutineContext coroutineContext = coroutineContext
) )
var res = analyzeUrl.getStrResponseAwait() var res = analyzeUrl.getStrResponseAwait()
@@ -249,7 +246,6 @@ object WebBook {
baseUrl = book.bookUrl, baseUrl = book.bookUrl,
source = bookSource, source = bookSource,
ruleData = book, ruleData = book,
headerMapF = bookSource.getHeaderMap(true),
coroutineContext = coroutineContext coroutineContext = coroutineContext
) )
var res = analyzeUrl.getStrResponseAwait() var res = analyzeUrl.getStrResponseAwait()
@@ -328,7 +324,6 @@ object WebBook {
source = bookSource, source = bookSource,
ruleData = book, ruleData = book,
chapter = bookChapter, chapter = bookChapter,
headerMapF = bookSource.getHeaderMap(true),
coroutineContext = coroutineContext coroutineContext = coroutineContext
) )
var res = analyzeUrl.getStrResponseAwait( var res = analyzeUrl.getStrResponseAwait(
@@ -225,6 +225,7 @@ class AudioPlayService : BaseService(),
source = AudioPlay.bookSource, source = AudioPlay.bookSource,
ruleData = AudioPlay.book, ruleData = AudioPlay.book,
chapter = AudioPlay.durChapter, chapter = AudioPlay.durChapter,
coroutineContext = coroutineContext
) )
exoPlayer.setMediaItem(analyzeUrl.getMediaItem()) exoPlayer.setMediaItem(analyzeUrl.getMediaItem())
exoPlayer.playWhenReady = true exoPlayer.playWhenReady = true
@@ -328,7 +328,6 @@ class HttpReadAloudService : BaseReadAloudService(),
speakText = speakText, speakText = speakText,
speakSpeed = speechRate, speakSpeed = speechRate,
source = httpTts, source = httpTts,
headerMapF = httpTts.getHeaderMap(true),
readTimeout = 300 * 1000L, readTimeout = 300 * 1000L,
coroutineContext = coroutineContext coroutineContext = coroutineContext
) )
@@ -274,7 +274,10 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
val fileNameNoExtension = if (book.author.isBlank()) book.name val fileNameNoExtension = if (book.author.isBlank()) book.name
else "${book.name} 作者:${book.author}" else "${book.name} 作者:${book.author}"
book.downloadUrls!!.map { book.downloadUrls!!.map {
val analyzeUrl = AnalyzeUrl(it, source = bookSource) val analyzeUrl = AnalyzeUrl(
it, source = bookSource,
coroutineContext = coroutineContext
)
val mFileName = UrlUtil.getFileName(analyzeUrl) val mFileName = UrlUtil.getFileName(analyzeUrl)
?: "${fileNameNoExtension}.${analyzeUrl.type}" ?: "${fileNameNoExtension}.${analyzeUrl.type}"
WebFile(it, mFileName) WebFile(it, mFileName)
@@ -12,10 +12,10 @@ import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import io.legado.app.R import io.legado.app.R
import io.legado.app.databinding.ViewMangaMenuBinding import io.legado.app.databinding.ViewMangaMenuBinding
import io.legado.app.help.IntentData
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.bottomBackground import io.legado.app.lib.theme.bottomBackground
import io.legado.app.model.ReadBook
import io.legado.app.model.ReadManga import io.legado.app.model.ReadManga
import io.legado.app.ui.browser.WebViewActivity import io.legado.app.ui.browser.WebViewActivity
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
@@ -176,9 +176,11 @@ class MangaMenu @JvmOverloads constructor(
} else { } else {
context.startActivity<WebViewActivity> { context.startActivity<WebViewActivity> {
val url = tvChapterUrl.text.toString() val url = tvChapterUrl.text.toString()
val bookSource = ReadBook.bookSource
putExtra("title", tvChapterName.text) putExtra("title", tvChapterName.text)
putExtra("url", url) putExtra("url", url)
IntentData.put(url, ReadManga.bookSource?.getHeaderMap(true)) putExtra("sourceOrigin", bookSource?.bookSourceUrl)
putExtra("sourceName", bookSource?.bookSourceName)
} }
} }
} }
@@ -1281,7 +1281,7 @@ class ReadBookActivity : BaseReadBookActivity(),
alert(R.string.chapter_pay) { alert(R.string.chapter_pay) {
setMessage(chapter.title) setMessage(chapter.title)
yesButton { yesButton {
Coroutine.async { Coroutine.async(lifecycleScope) {
val source = val source =
ReadBook.bookSource ?: throw NoStackTraceException("no book source") ReadBook.bookSource ?: throw NoStackTraceException("no book source")
val payAction = source.getContentRule().payAction val payAction = source.getContentRule().payAction
@@ -1289,6 +1289,7 @@ class ReadBookActivity : BaseReadBookActivity(),
throw NoStackTraceException("no pay action") throw NoStackTraceException("no pay action")
} }
val analyzeRule = AnalyzeRule(book, source) val analyzeRule = AnalyzeRule(book, source)
analyzeRule.setCoroutineContext(coroutineContext)
analyzeRule.setBaseUrl(chapter.url) analyzeRule.setBaseUrl(chapter.url)
analyzeRule.chapter = chapter analyzeRule.chapter = chapter
analyzeRule.evalJS(payAction).toString() analyzeRule.evalJS(payAction).toString()
@@ -1297,7 +1298,7 @@ class ReadBookActivity : BaseReadBookActivity(),
startActivity<WebViewActivity> { startActivity<WebViewActivity> {
putExtra("title", getString(R.string.chapter_pay)) putExtra("title", getString(R.string.chapter_pay))
putExtra("url", it) putExtra("url", it)
IntentData.put(it, ReadBook.bookSource?.getHeaderMap(true)) putExtra("sourceOrigin", ReadBook.bookSource?.bookSourceUrl)
} }
} else if (it.isTrue()) { } else if (it.isTrue()) {
//购买成功后刷新目录 //购买成功后刷新目录
@@ -18,7 +18,6 @@ import androidx.core.view.isVisible
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.databinding.ViewReadMenuBinding import io.legado.app.databinding.ViewReadMenuBinding
import io.legado.app.help.IntentData
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.LocalConfig import io.legado.app.help.config.LocalConfig
import io.legado.app.help.config.ReadBookConfig import io.legado.app.help.config.ReadBookConfig
@@ -350,9 +349,11 @@ class ReadMenu @JvmOverloads constructor(
Coroutine.async { Coroutine.async {
context.startActivity<WebViewActivity> { context.startActivity<WebViewActivity> {
val url = tvChapterUrl.text.toString() val url = tvChapterUrl.text.toString()
val bookSource = ReadBook.bookSource
putExtra("title", tvChapterName.text) putExtra("title", tvChapterName.text)
putExtra("url", url) putExtra("url", url)
IntentData.put(url, ReadBook.bookSource?.getHeaderMap(true)) putExtra("sourceOrigin", bookSource?.bookSourceUrl)
putExtra("sourceName", bookSource?.bookSourceName)
} }
} }
} }
@@ -11,7 +11,6 @@ import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
import io.legado.app.data.appDb import io.legado.app.data.appDb
import io.legado.app.exception.NoStackTraceException import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.IntentData
import io.legado.app.help.http.newCallResponseBody import io.legado.app.help.http.newCallResponseBody
import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.okHttpClient
import io.legado.app.help.source.SourceVerificationHelp import io.legado.app.help.source.SourceVerificationHelp
@@ -48,8 +47,8 @@ class WebViewModel(application: Application) : BaseViewModel(application) {
sourceOrigin = intent.getStringExtra("sourceOrigin") ?: "" sourceOrigin = intent.getStringExtra("sourceOrigin") ?: ""
sourceVerificationEnable = intent.getBooleanExtra("sourceVerificationEnable", false) sourceVerificationEnable = intent.getBooleanExtra("sourceVerificationEnable", false)
refetchAfterSuccess = intent.getBooleanExtra("refetchAfterSuccess", true) refetchAfterSuccess = intent.getBooleanExtra("refetchAfterSuccess", true)
val headerMapF = IntentData.get<Map<String, String>>(url) val source = appDb.bookSourceDao.getBookSource(sourceOrigin)
val analyzeUrl = AnalyzeUrl(url, headerMapF = headerMapF) val analyzeUrl = AnalyzeUrl(url, source = source, coroutineContext = coroutineContext)
baseUrl = analyzeUrl.url baseUrl = analyzeUrl.url
headerMap.putAll(analyzeUrl.headerMap) headerMap.putAll(analyzeUrl.headerMap)
if (analyzeUrl.isPost()) { if (analyzeUrl.isPost()) {
@@ -107,7 +106,8 @@ class WebViewModel(application: Application) : BaseViewModel(application) {
html = AnalyzeUrl( html = AnalyzeUrl(
url, url,
headerMapF = headerMap, headerMapF = headerMap,
source = source source = source,
coroutineContext = coroutineContext
).getStrResponseAwait(useWebView = false).body ).getStrResponseAwait(useWebView = false).body
SourceVerificationHelp.setResult(sourceOrigin, html ?: "") SourceVerificationHelp.setResult(sourceOrigin, html ?: "")
}.onSuccess { }.onSuccess {
@@ -16,7 +16,6 @@ import io.legado.app.data.entities.rule.RowUi
import io.legado.app.databinding.DialogLoginBinding import io.legado.app.databinding.DialogLoginBinding
import io.legado.app.databinding.ItemFilletTextBinding import io.legado.app.databinding.ItemFilletTextBinding
import io.legado.app.databinding.ItemSourceEditBinding import io.legado.app.databinding.ItemSourceEditBinding
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.primaryColor import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.about.AppLogDialog import io.legado.app.ui.about.AppLogDialog
@@ -26,6 +25,7 @@ import io.legado.app.utils.dpToPx
import io.legado.app.utils.isAbsUrl import io.legado.app.utils.isAbsUrl
import io.legado.app.utils.openUrl import io.legado.app.utils.openUrl
import io.legado.app.utils.printOnDebug import io.legado.app.utils.printOnDebug
import io.legado.app.utils.runScriptWithContext
import io.legado.app.utils.setLayout import io.legado.app.utils.setLayout
import io.legado.app.utils.showDialogFragment import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
@@ -119,16 +119,18 @@ class SourceLoginDialog : BaseDialogFragment(R.layout.dialog_login, true) {
} }
private fun handleButtonClick(source: BaseSource, rowUi: RowUi, loginUi: List<RowUi>) { private fun handleButtonClick(source: BaseSource, rowUi: RowUi, loginUi: List<RowUi>) {
Coroutine.async { lifecycleScope.launch(IO) {
if (rowUi.action.isAbsUrl()) { if (rowUi.action.isAbsUrl()) {
context?.openUrl(rowUi.action!!) context?.openUrl(rowUi.action!!)
} else if (rowUi.action != null) { } else if (rowUi.action != null) {
// JavaScript // JavaScript
val buttonFunctionJS = rowUi.action!! val buttonFunctionJS = rowUi.action!!
val loginJS = source.getLoginJs() ?: return@async val loginJS = source.getLoginJs() ?: return@launch
kotlin.runCatching { kotlin.runCatching {
source.evalJS("$loginJS\n$buttonFunctionJS") { runScriptWithContext {
put("result", getLoginData(loginUi)) source.evalJS("$loginJS\n$buttonFunctionJS") {
put("result", getLoginData(loginUi))
}
} }
}.onFailure { e -> }.onFailure { e ->
AppLog.put("LoginUI Button ${rowUi.name} JavaScript error", e) AppLog.put("LoginUI Button ${rowUi.name} JavaScript error", e)
@@ -161,7 +163,9 @@ class SourceLoginDialog : BaseDialogFragment(R.layout.dialog_login, true) {
} }
} else if (source.putLoginInfo(GSON.toJson(loginData))) { } else if (source.putLoginInfo(GSON.toJson(loginData))) {
try { try {
source.login() runScriptWithContext {
source.login()
}
context?.toastOnUi(R.string.success) context?.toastOnUi(R.string.success)
withContext(Main) { withContext(Main) {
dismiss() dismiss()
@@ -6,11 +6,13 @@ import io.legado.app.base.BaseViewModel
import io.legado.app.data.appDb import io.legado.app.data.appDb
import io.legado.app.data.entities.BaseSource import io.legado.app.data.entities.BaseSource
import io.legado.app.exception.NoStackTraceException import io.legado.app.exception.NoStackTraceException
import io.legado.app.utils.runScriptWithContext
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
class SourceLoginViewModel(application: Application) : BaseViewModel(application) { class SourceLoginViewModel(application: Application) : BaseViewModel(application) {
var source: BaseSource? = null var source: BaseSource? = null
var headerMap: Map<String, String> = emptyMap()
fun initData(intent: Intent, success: (bookSource: BaseSource) -> Unit) { fun initData(intent: Intent, success: (bookSource: BaseSource) -> Unit) {
execute { execute {
@@ -21,6 +23,9 @@ class SourceLoginViewModel(application: Application) : BaseViewModel(application
"rssSource" -> source = appDb.rssSourceDao.getByKey(sourceKey) "rssSource" -> source = appDb.rssSourceDao.getByKey(sourceKey)
"httpTts" -> source = appDb.httpTTSDao.get(sourceKey.toLong()) "httpTts" -> source = appDb.httpTTSDao.get(sourceKey.toLong())
} }
headerMap = runScriptWithContext {
source?.getHeaderMap(true) ?: emptyMap()
}
source source
}.onSuccess { }.onSuccess {
if (it != null) { if (it != null) {
@@ -16,6 +16,7 @@ import android.webkit.WebSettings
import android.webkit.WebView import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseFragment import io.legado.app.base.BaseFragment
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
@@ -29,6 +30,7 @@ import io.legado.app.utils.longSnackbar
import io.legado.app.utils.openUrl import io.legado.app.utils.openUrl
import io.legado.app.utils.snackbar import io.legado.app.utils.snackbar
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.launch
class WebViewLoginFragment : BaseFragment(R.layout.fragment_web_view_login) { class WebViewLoginFragment : BaseFragment(R.layout.fragment_web_view_login) {
@@ -55,11 +57,8 @@ class WebViewLoginFragment : BaseFragment(R.layout.fragment_web_view_login) {
if (!checking) { if (!checking) {
checking = true checking = true
binding.titleBar.snackbar(R.string.check_host_cookie) binding.titleBar.snackbar(R.string.check_host_cookie)
viewModel.source?.let { source -> viewModel.source?.let {
source.loginUrl?.let { loadUrl(it)
val absoluteUrl = NetworkUtils.getAbsoluteURL(source.getKey(), it)
binding.webView.loadUrl(absoluteUrl, source.getHeaderMap(true))
}
} }
} }
} }
@@ -77,7 +76,7 @@ class WebViewLoginFragment : BaseFragment(R.layout.fragment_web_view_login) {
builtInZoomControls = true builtInZoomControls = true
javaScriptEnabled = true javaScriptEnabled = true
displayZoomControls = false displayZoomControls = false
source.getHeaderMap()[AppConst.UA_NAME]?.let { viewModel.headerMap[AppConst.UA_NAME]?.let {
userAgentString = it userAgentString = it
} }
} }
@@ -143,9 +142,14 @@ class WebViewLoginFragment : BaseFragment(R.layout.fragment_web_view_login) {
} }
} }
source.loginUrl?.let { loadUrl(source)
val absoluteUrl = NetworkUtils.getAbsoluteURL(source.getKey(), it) }
binding.webView.loadUrl(absoluteUrl, source.getHeaderMap(true))
private fun loadUrl(source: BaseSource) {
lifecycleScope.launch {
val loginUrl = source.loginUrl ?: return@launch
val absoluteUrl = NetworkUtils.getAbsoluteURL(source.getKey(), loginUrl)
binding.webView.loadUrl(absoluteUrl, viewModel.headerMap)
} }
} }
@@ -4,6 +4,7 @@ import android.app.Application
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.data.appDb import io.legado.app.data.appDb
import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssSource
import io.legado.app.utils.runScriptWithContext
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
class RssViewModel(application: Application) : BaseViewModel(application) { class RssViewModel(application: Application) : BaseViewModel(application) {
@@ -58,7 +59,9 @@ class RssViewModel(application: Application) : BaseViewModel(application) {
} else { } else {
sortUrl.substring(4, sortUrl.lastIndexOf("<")) sortUrl.substring(4, sortUrl.lastIndexOf("<"))
} }
val result = rssSource.evalJS(jsStr)?.toString() val result = runScriptWithContext {
rssSource.evalJS(jsStr)?.toString()
}
if (!result.isNullOrBlank()) { if (!result.isNullOrBlank()) {
sortUrl = result sortUrl = result
} }
@@ -46,7 +46,6 @@ import io.legado.app.ui.login.SourceLoginActivity
import io.legado.app.ui.rss.favorites.RssFavoritesDialog import io.legado.app.ui.rss.favorites.RssFavoritesDialog
import io.legado.app.utils.ACache import io.legado.app.utils.ACache
import io.legado.app.utils.NetworkUtils import io.legado.app.utils.NetworkUtils
import io.legado.app.utils.get
import io.legado.app.utils.gone import io.legado.app.utils.gone
import io.legado.app.utils.invisible import io.legado.app.utils.invisible
import io.legado.app.utils.isTrue import io.legado.app.utils.isTrue
@@ -187,7 +186,7 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
} }
override fun updateFavorite(title: String?, group: String?) { override fun updateFavorite(title: String?, group: String?) {
viewModel.rssArticle?.let{ viewModel.rssArticle?.let {
if (title != null) { if (title != null) {
it.title = title it.title = title
} }
@@ -294,8 +293,7 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
val url = NetworkUtils.getAbsoluteURL(it.origin, it.link) val url = NetworkUtils.getAbsoluteURL(it.origin, it.link)
val html = viewModel.clHtml(content) val html = viewModel.clHtml(content)
binding.webView.settings.userAgentString = binding.webView.settings.userAgentString =
viewModel.rssSource?.getHeaderMap()?.get(AppConst.UA_NAME, true) viewModel.headerMap[AppConst.UA_NAME] ?: AppConfig.userAgent
?: AppConfig.userAgent
if (viewModel.rssSource?.loadWithBaseUrl == true) { if (viewModel.rssSource?.loadWithBaseUrl == true) {
binding.webView binding.webView
.loadDataWithBaseURL(url, html, "text/html", "utf-8", url)//不想用baseUrl进else .loadDataWithBaseURL(url, html, "text/html", "utf-8", url)//不想用baseUrl进else
@@ -21,11 +21,13 @@ import io.legado.app.help.http.newCallResponseBody
import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.okHttpClient
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.model.rss.Rss import io.legado.app.model.rss.Rss
import io.legado.app.utils.runScriptWithContext
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import io.legado.app.utils.writeBytes import io.legado.app.utils.writeBytes
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import splitties.init.appCtx import splitties.init.appCtx
import java.util.Date import java.util.Date
import kotlin.coroutines.coroutineContext
class ReadRssViewModel(application: Application) : BaseViewModel(application), JsExtensions { class ReadRssViewModel(application: Application) : BaseViewModel(application), JsExtensions {
@@ -37,6 +39,7 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application), J
var rssStar: RssStar? = null var rssStar: RssStar? = null
val upTtsMenuData = MutableLiveData<Boolean>() val upTtsMenuData = MutableLiveData<Boolean>()
val upStarMenuData = MutableLiveData<Boolean>() val upStarMenuData = MutableLiveData<Boolean>()
var headerMap: Map<String, String> = emptyMap()
override fun getSource(): BaseSource? { override fun getSource(): BaseSource? {
return rssSource return rssSource
@@ -47,6 +50,9 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application), J
val origin = intent.getStringExtra("origin") ?: return@execute val origin = intent.getStringExtra("origin") ?: return@execute
val link = intent.getStringExtra("link") val link = intent.getStringExtra("link")
rssSource = appDb.rssSourceDao.getByKey(origin) rssSource = appDb.rssSourceDao.getByKey(origin)
headerMap = runScriptWithContext {
rssSource?.getHeaderMap() ?: emptyMap()
}
if (link != null) { if (link != null) {
rssStar = appDb.rssStarDao.get(origin, link) rssStar = appDb.rssStarDao.get(origin, link)
rssArticle = rssStar?.toRssArticle() ?: appDb.rssArticleDao.get(origin, link) rssArticle = rssStar?.toRssArticle() ?: appDb.rssArticleDao.get(origin, link)
@@ -80,11 +86,13 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application), J
} }
} }
private fun loadUrl(url: String, baseUrl: String) { private suspend fun loadUrl(url: String, baseUrl: String) {
val analyzeUrl = AnalyzeUrl( val analyzeUrl = AnalyzeUrl(
mUrl = url, mUrl = url,
baseUrl = baseUrl, baseUrl = baseUrl,
headerMapF = rssSource?.getHeaderMap() source = rssSource,
coroutineContext = coroutineContext,
hasLoginHeader = false
) )
urlLiveData.postValue(analyzeUrl) urlLiveData.postValue(analyzeUrl)
} }
@@ -1,5 +1,7 @@
package io.legado.app.utils package io.legado.app.utils
import com.script.rhino.RhinoContext
import com.script.rhino.RhinoScriptEngine
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
@@ -7,6 +9,9 @@ import org.mozilla.javascript.Context
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.coroutines.ContinuationInterceptor
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND") @Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND")
@OptIn(ExperimentalContracts::class) @OptIn(ExperimentalContracts::class)
@@ -29,3 +34,28 @@ inline fun <T> suspendContinuation(crossinline block: suspend CoroutineScope.()
Context.exit() Context.exit()
} }
} }
inline fun <T> runScriptWithContext(context: CoroutineContext, block: () -> T): T {
RhinoScriptEngine
val rhinoContext = Context.enter() as RhinoContext
val previousCoroutineContext = rhinoContext.coroutineContext
rhinoContext.coroutineContext = context.minusKey(ContinuationInterceptor)
try {
return block()
} finally {
rhinoContext.coroutineContext = previousCoroutineContext
Context.exit()
}
}
suspend inline fun <T> runScriptWithContext(block: () -> T): T {
val rhinoContext = Context.enter() as RhinoContext
val previousCoroutineContext = rhinoContext.coroutineContext
rhinoContext.coroutineContext = coroutineContext.minusKey(ContinuationInterceptor)
try {
return block()
} finally {
rhinoContext.coroutineContext = previousCoroutineContext
Context.exit()
}
}
@@ -93,7 +93,9 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
): Any? { ): Any? {
val cx = Context.enter() as RhinoContext val cx = Context.enter() as RhinoContext
val previousCoroutineContext = cx.coroutineContext val previousCoroutineContext = cx.coroutineContext
cx.coroutineContext = coroutineContext if (coroutineContext != null) {
cx.coroutineContext = coroutineContext
}
cx.allowScriptRun = true cx.allowScriptRun = true
val ret: Any? val ret: Any?
try { try {