kunfei 3 лет назад
Родитель
Сommit
8772ac785f

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

@@ -1,7 +1,7 @@
 package io.legado.app
 
-import io.legado.app.rhino.Rhino
-import io.legado.app.rhino.putBinding
+import com.script.SimpleBindings
+import com.script.rhino.RhinoScriptEngine
 import org.intellij.lang.annotations.Language
 import org.junit.Assert
 import org.junit.Test
@@ -36,17 +36,13 @@ class AndroidJsTest {
             var queryStringWithSign = "Signature=" + signStr + "&" + query;
             queryStringWithSign
         """.trimIndent()
-        Rhino.use {
-            evaluateString(it, js, "yy", 1, null)
-        }
+        RhinoScriptEngine.eval(js)
         @Language("js")
         val js1 = """
             var returnData = new Packages.io.legado.app.api.ReturnData()
             returnData.getErrorMsg()
         """.trimIndent()
-        val result1 = Rhino.use {
-            evaluateString(it, js1, "xx", 1, null)
-        }
+        val result1 = RhinoScriptEngine.eval(js1)
         Assert.assertEquals(result1, "未知错误,请联系开发者!").let {
 
         }
@@ -55,20 +51,15 @@ class AndroidJsTest {
     @Test
     fun testMap() {
         val map = hashMapOf("id" to "3242532321")
-
+        val bindings = SimpleBindings()
+        bindings["result"] = map
         @Language("js")
         val jsMap = "$=result;id=$.id;id"
-        val result = Rhino.use {
-            it.putBinding("result", map)
-            evaluateString(it, jsMap, "xxx", 1, null)
-        }
+        val result = RhinoScriptEngine.eval(jsMap, bindings)
         Assert.assertEquals("3242532321", result)
         @Language("js")
         val jsMap1 = """result.get("id")"""
-        val result1 = Rhino.use {
-            it.putBinding("result", map)
-            evaluateString(it, jsMap1, "xxx", 1, null)
-        }
+        val result1 = RhinoScriptEngine.eval(jsMap1, bindings)
         Assert.assertEquals("3242532321", result1)
     }
 

+ 3 - 11
app/src/main/java/io/legado/app/data/entities/BaseSource.kt

@@ -11,7 +11,6 @@ import io.legado.app.help.JsExtensions
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.http.CookieStore
 import io.legado.app.model.SharedJsScope
-import io.legado.app.rhino.Bindings
 import io.legado.app.utils.*
 import org.intellij.lang.annotations.Language
 import org.mozilla.javascript.Scriptable
@@ -228,22 +227,15 @@ interface BaseSource : JsExtensions {
      * 执行JS
      */
     @Throws(Exception::class)
-    fun evalJS(jsStr: String, bindingsConfig: Bindings.() -> Unit = {}): Any? {
-        val bindings = Bindings()
+    fun evalJS(jsStr: String, bindingsConfig: SimpleBindings.() -> Unit = {}): Any? {
+        val bindings = SimpleBindings()
         bindings.apply(bindingsConfig)
         bindings["java"] = this
         bindings["source"] = this
         bindings["baseUrl"] = getKey()
         bindings["cookie"] = CookieStore
         bindings["cache"] = CacheManager
-//        return Rhino.use { scope ->
-//            scope.putBindings(bindings)
-//            getShareScope()?.let {
-//                scope.prototype = it
-//            }
-//            eval(scope, jsStr)
-//        }
-        val context = RhinoScriptEngine.getScriptContext(SimpleBindings(bindings))
+        val context = RhinoScriptEngine.getScriptContext(bindings)
         val scope = RhinoScriptEngine.getRuntimeScope(context)
         getShareScope()?.let {
             scope.prototype = it

+ 4 - 8
app/src/main/java/io/legado/app/help/book/BookExtensions.kt

@@ -3,6 +3,8 @@
 package io.legado.app.help.book
 
 import android.net.Uri
+import com.script.SimpleBindings
+import com.script.rhino.RhinoScriptEngine
 import io.legado.app.constant.*
 import io.legado.app.data.appDb
 import io.legado.app.data.entities.BaseBook
@@ -10,9 +12,6 @@ import io.legado.app.data.entities.Book
 import io.legado.app.data.entities.BookSource
 import io.legado.app.exception.NoStackTraceException
 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 splitties.init.appCtx
 import java.io.File
@@ -236,14 +235,11 @@ fun Book.getExportFileName(suffix: String): String {
     if (jsStr.isNullOrBlank()) {
         return "$name 作者:${getRealAuthor()}.$suffix"
     }
-    val bindings = Bindings()
+    val bindings = SimpleBindings()
     bindings["name"] = name
     bindings["author"] = getRealAuthor()
     return kotlin.runCatching {
-        Rhino.use {
-            it.putBindings(bindings)
-            evaluateString(it, jsStr, "name&author", 1, null)
-        }.toString() + "." + suffix
+        RhinoScriptEngine.eval(jsStr, bindings).toString() + "." + suffix
     }.onFailure {
         AppLog.put("导出书名规则错误,使用默认规则\n${it.localizedMessage}", it)
     }.getOrDefault("${name} 作者:${getRealAuthor()}.$suffix")

+ 10 - 4
app/src/main/java/io/legado/app/help/storage/Backup.kt

@@ -109,9 +109,13 @@ object Backup {
             writeListToJson(appDb.httpTTSDao.all, "httpTTS.json", backupPath)
             writeListToJson(appDb.keyboardAssistsDao.all, "keyboardAssists.json", backupPath)
             writeListToJson(appDb.dictRuleDao.all, "dictRule.json", backupPath)
-            aes.encryptBase64(GSON.toJson(appDb.serverDao.all)).let {
-                FileUtils.createFileIfNotExist(backupPath + File.separator + "servers.json")
-                    .writeText(it)
+            GSON.toJson(appDb.serverDao.all).let { json ->
+                aes.runCatching {
+                    encryptBase64(json)
+                }.getOrDefault(json).let {
+                    FileUtils.createFileIfNotExist(backupPath + File.separator + "servers.json")
+                        .writeText(it)
+                }
             }
             ensureActive()
             GSON.toJson(ReadBookConfig.configList).let {
@@ -137,7 +141,9 @@ object Backup {
                     if (BackupConfig.keyIsNotIgnore(key)) {
                         when (key) {
                             PreferKey.webDavPassword -> {
-                                edit.putString(key, aes.encryptBase64(value.toString()))
+                                edit.putString(key, aes.runCatching {
+                                    encryptBase64(value.toString())
+                                }.getOrDefault(value.toString()))
                             }
 
                             else -> when (value) {

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

@@ -1,10 +1,11 @@
 package io.legado.app.model
 
 import com.google.gson.reflect.TypeToken
+import com.script.SimpleBindings
+import com.script.rhino.RhinoScriptEngine
 import io.legado.app.exception.NoStackTraceException
 import io.legado.app.help.http.newCallStrResponse
 import io.legado.app.help.http.okHttpClient
-import io.legado.app.rhino.Rhino
 import io.legado.app.utils.ACache
 import io.legado.app.utils.GSON
 import io.legado.app.utils.MD5Utils
@@ -31,39 +32,39 @@ object SharedJsScope {
         val key = MD5Utils.md5Encode(jsLib)
         var scope = scopeMap[key]?.get()
         if (scope == null) {
-            Rhino.use {
-                scope = it
-                if (jsLib.isJsonObject()) {
-                    val jsMap: Map<String, String> = GSON.fromJson(
-                        jsLib,
-                        TypeToken.getParameterized(
-                            Map::class.java,
-                            String::class.java,
-                            String::class.java
-                        ).type
-                    )
-                    jsMap.values.forEach { value ->
-                        if (value.isAbsUrl()) {
-                            val fileName = MD5Utils.md5Encode(value)
-                            var js = aCache.getAsString(fileName)
-                            if (js == null) {
-                                js = runBlocking {
-                                    okHttpClient.newCallStrResponse {
-                                        url(value)
-                                    }.body
-                                }
-                                if (js !== null) {
-                                    aCache.put(fileName, js)
-                                } else {
-                                    throw NoStackTraceException("下载jsLib-${value}失败")
-                                }
+            scope = RhinoScriptEngine.run {
+                getRuntimeScope(getScriptContext(SimpleBindings()))
+            }
+            if (jsLib.isJsonObject()) {
+                val jsMap: Map<String, String> = GSON.fromJson(
+                    jsLib,
+                    TypeToken.getParameterized(
+                        Map::class.java,
+                        String::class.java,
+                        String::class.java
+                    ).type
+                )
+                jsMap.values.forEach { value ->
+                    if (value.isAbsUrl()) {
+                        val fileName = MD5Utils.md5Encode(value)
+                        var js = aCache.getAsString(fileName)
+                        if (js == null) {
+                            js = runBlocking {
+                                okHttpClient.newCallStrResponse {
+                                    url(value)
+                                }.body
+                            }
+                            if (js !== null) {
+                                aCache.put(fileName, js)
+                            } else {
+                                throw NoStackTraceException("下载jsLib-${value}失败")
                             }
-                            evaluateString(scope, js, "jsLib", 1, null)
                         }
+                        RhinoScriptEngine.eval(js, scope)
                     }
-                } else {
-                    evaluateString(scope, jsLib, "jsLib", 1, null)
                 }
+            } else {
+                RhinoScriptEngine.eval(jsLib, scope)
             }
             scopeMap[key] = WeakReference(scope)
         }

+ 2 - 10
app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt

@@ -10,7 +10,6 @@ import io.legado.app.help.CacheManager
 import io.legado.app.help.JsExtensions
 import io.legado.app.help.http.CookieStore
 import io.legado.app.model.webBook.WebBook
-import io.legado.app.rhino.Bindings
 import io.legado.app.utils.*
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.withTimeout
@@ -698,7 +697,7 @@ class AnalyzeRule(
      * 执行JS
      */
     fun evalJS(jsStr: String, result: Any? = null): Any? {
-        val bindings = Bindings()
+        val bindings = SimpleBindings()
         bindings["java"] = this
         bindings["cookie"] = CookieStore
         bindings["cache"] = CacheManager
@@ -710,14 +709,7 @@ class AnalyzeRule(
         bindings["title"] = chapter?.title
         bindings["src"] = content
         bindings["nextChapterUrl"] = nextChapterUrl
-//        return Rhino.use { scope ->
-//            scope.putBindings(bindings)
-//            source?.getShareScope()?.let {
-//                scope.prototype = it
-//            }
-//            eval(scope, jsStr)
-//        }
-        val context = RhinoScriptEngine.getScriptContext(SimpleBindings(bindings))
+        val context = RhinoScriptEngine.getScriptContext(bindings)
         val scope = RhinoScriptEngine.getRuntimeScope(context)
         source?.getShareScope()?.let {
             scope.prototype = it

+ 2 - 10
app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt

@@ -20,7 +20,6 @@ import io.legado.app.help.JsExtensions
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.glide.GlideHeaders
 import io.legado.app.help.http.*
-import io.legado.app.rhino.Bindings
 import io.legado.app.utils.*
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.runBlocking
@@ -255,7 +254,7 @@ class AnalyzeUrl(
      * 执行JS
      */
     fun evalJS(jsStr: String, result: Any? = null): Any? {
-        val bindings = Bindings()
+        val bindings = SimpleBindings()
         bindings["java"] = this
         bindings["baseUrl"] = baseUrl
         bindings["cookie"] = CookieStore
@@ -267,14 +266,7 @@ class AnalyzeUrl(
         bindings["book"] = ruleData as? Book
         bindings["source"] = source
         bindings["result"] = result
-//        return Rhino.use { scope ->
-//            scope.putBindings(bindings)
-//            source?.getShareScope()?.let {
-//                scope.prototype = it
-//            }
-//            eval(scope, jsStr)
-//        }
-        val context = RhinoScriptEngine.getScriptContext(SimpleBindings(bindings))
+        val context = RhinoScriptEngine.getScriptContext(bindings)
         val scope = RhinoScriptEngine.getRuntimeScope(context)
         source?.getShareScope()?.let {
             scope.prototype = it

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

@@ -3,6 +3,8 @@ package io.legado.app.model.localBook
 import android.net.Uri
 import android.util.Base64
 import androidx.documentfile.provider.DocumentFile
+import com.script.SimpleBindings
+import com.script.rhino.RhinoScriptEngine
 import io.legado.app.R
 import io.legado.app.constant.*
 import io.legado.app.data.appDb
@@ -19,9 +21,6 @@ import io.legado.app.help.config.AppConfig
 import io.legado.app.lib.webdav.WebDav
 import io.legado.app.lib.webdav.WebDavException
 import io.legado.app.model.analyzeRule.AnalyzeUrl
-import io.legado.app.rhino.Rhino
-import io.legado.app.rhino.eval
-import io.legado.app.rhino.putBinding
 import io.legado.app.utils.*
 import kotlinx.coroutines.runBlocking
 import org.jsoup.nodes.Entities
@@ -271,9 +270,10 @@ object LocalBook {
                 val js =
                     AppConfig.bookImportFileName + "\nJSON.stringify({author:author,name:name})"
                 //在脚本中定义如何分解文件名成书名、作者名
-                val jsonStr = Rhino.use {
-                    it.putBinding("src", tempFileName)
-                    eval(it, js)
+                val jsonStr = RhinoScriptEngine.run {
+                    val bindings = SimpleBindings()
+                    bindings["src"] = tempFileName
+                    eval(js, bindings)
                 }.toString()
                 val bookMess = GSON.fromJsonObject<HashMap<String, String>>(jsonStr)
                     .getOrThrow()

+ 0 - 54
app/src/main/java/io/legado/app/rhino/Bindings.kt

@@ -1,54 +0,0 @@
-/*
- * 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
-
-}

+ 0 - 43
app/src/main/java/io/legado/app/rhino/Rhino.kt

@@ -1,43 +0,0 @@
-package io.legado.app.rhino
-
-import org.mozilla.javascript.Context
-import org.mozilla.javascript.ImporterTopLevel
-import org.mozilla.javascript.Scriptable
-import org.mozilla.javascript.Undefined
-import org.mozilla.javascript.Wrapper
-
-object Rhino {
-
-    inline fun <T> use(block: Context.(Scriptable) -> T): T {
-        return try {
-            val cx = Context.enter()
-            val scope = cx.initStandardObjects(ImporterTopLevel(cx))
-            block.invoke(cx, scope)
-        } finally {
-            Context.exit()
-        }
-    }
-
-    fun unwrapReturnValue(result: Any?): Any? {
-        var result1 = result
-        if (result1 is Wrapper) {
-            result1 = result1.unwrap()
-        }
-        return if (result1 is Undefined) null else result1
-    }
-
-//    init {
-//        ContextFactory.initGlobal(object : RhinoContextFactory() {
-//
-//            override fun makeContext(): Context {
-//                val cx = super.makeContext()
-//                cx.languageVersion = 200
-//                cx.optimizationLevel = -1
-//                cx.setClassShutter(RhinoClassShutter)
-//                return cx
-//            }
-//
-//        })
-//    }
-
-}

+ 0 - 62
app/src/main/java/io/legado/app/rhino/RhinoClassShutter.kt

@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package io.legado.app.rhino
-
-import org.mozilla.javascript.ClassShutter
-
-/**
- * This class prevents script access to certain sensitive classes.
- * Note that this class checks over and above SecurityManager. i.e., although
- * a SecurityManager would pass, class shutter may still prevent access.
- *
- * @author A. Sundararajan
- * @since 1.6
- */
-object RhinoClassShutter : ClassShutter {
-
-    private val protectedClasses by lazy {
-        val protectedClasses = HashMap<Any, Any>()
-        protectedClasses["java.lang.Runtime"] = java.lang.Boolean.TRUE
-        protectedClasses["java.io.File"] = java.lang.Boolean.TRUE
-        protectedClasses["java.security.AccessController"] = java.lang.Boolean.TRUE
-        protectedClasses
-    }
-
-    override fun visibleToScripts(fullClassName: String): Boolean {
-        val sm = System.getSecurityManager()
-        if (sm != null) {
-            val i = fullClassName.lastIndexOf(".")
-            if (i != -1) {
-                try {
-                    sm.checkPackageAccess(fullClassName.substring(0, i))
-                } catch (e: SecurityException) {
-                    return false
-                }
-            }
-        }
-        return protectedClasses[fullClassName] == null
-    }
-
-}

+ 3 - 6
app/src/main/java/io/legado/app/rhino/RhinoExtensions.kt

@@ -2,6 +2,7 @@
 
 package io.legado.app.rhino
 
+import com.script.Bindings
 import org.mozilla.javascript.Context
 import org.mozilla.javascript.Scriptable
 import org.mozilla.javascript.ScriptableObject
@@ -14,9 +15,7 @@ fun Context.eval(
     lineno: Int = 1,
     securityDomain: Any? = null
 ): Any? {
-    return Rhino.unwrapReturnValue(
-        evaluateString(scope, source, sourceName, lineno, securityDomain)
-    )
+    return evaluateString(scope, source, sourceName, lineno, securityDomain)
 }
 
 fun Context.eval(
@@ -26,9 +25,7 @@ fun Context.eval(
     lineno: Int = 1,
     securityDomain: Any? = null
 ): Any? {
-    return Rhino.unwrapReturnValue(
-        evaluateReader(scope, reader, sourceName, lineno, securityDomain)
-    )
+    return evaluateReader(scope, reader, sourceName, lineno, securityDomain)
 }
 
 fun Scriptable.putBinding(key: String, value: Any?) {

+ 6 - 14
app/src/main/java/io/legado/app/utils/JsUtils.kt

@@ -1,25 +1,20 @@
 package io.legado.app.utils
 
+import com.script.SimpleBindings
+import com.script.rhino.RhinoScriptEngine
 import io.legado.app.constant.AppPattern.EXP_PATTERN
-import io.legado.app.rhino.Bindings
-import io.legado.app.rhino.Rhino
-import io.legado.app.rhino.eval
-import io.legado.app.rhino.putBindings
 
 object JsUtils {
 
-    fun evalJs(js: String, bindingsFun: ((Bindings) -> Unit)? = null): String {
-        val bindings = Bindings()
+    fun evalJs(js: String, bindingsFun: ((SimpleBindings) -> Unit)? = null): String {
+        val bindings = SimpleBindings()
         bindingsFun?.invoke(bindings)
         if (js.contains("{{") && js.contains("}}")) {
             val sb = StringBuffer()
             val expMatcher = EXP_PATTERN.matcher(js)
             while (expMatcher.find()) {
                 val result = expMatcher.group(1)?.let { js1 ->
-                    Rhino.use {
-                        it.putBindings(bindings)
-                        eval(it, js1)
-                    }
+                    RhinoScriptEngine.eval(js1, bindings)
                 } ?: ""
                 if (result is String) {
                     expMatcher.appendReplacement(sb, result)
@@ -32,10 +27,7 @@ object JsUtils {
             expMatcher.appendTail(sb)
             return sb.toString()
         }
-        return Rhino.use {
-            it.putBindings(bindings)
-            eval(it, js)
-        }.toString()
+        return RhinoScriptEngine.eval(js, bindings).toString()
     }
 
 

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

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

+ 19 - 35
app/src/test/java/io/legado/app/JsTest.kt

@@ -1,10 +1,8 @@
 package io.legado.app
 
 import com.script.SimpleBindings
+import com.script.rhino.RhinoScriptEngine
 import io.legado.app.data.entities.BookChapter
-import io.legado.app.rhino.Rhino
-import io.legado.app.rhino.eval
-import io.legado.app.rhino.putBinding
 import org.intellij.lang.annotations.Language
 import org.junit.Assert
 import org.junit.Test
@@ -30,29 +28,24 @@ class JsTest {
     @Test
     fun testMap() {
         val map = hashMapOf("id" to "3242532321")
-
+        val bindings = SimpleBindings()
+        bindings["result"] = map
         @Language("js")
         val jsMap = "$=result;id=$.id;id"
-        val result = Rhino.use {
-            val scope = initStandardObjects()
-            scope.putBinding("result", map)
-            evaluateString(scope, jsMap, "xxx", 1, null)
-        }
+        val result = RhinoScriptEngine.eval(jsMap, bindings)
         Assert.assertEquals("3242532321", result)
         @Language("js")
         val jsMap1 = """result.get("id")"""
-        val result1 = Rhino.use {
-            it.putBinding("result", map)
-            evaluateString(it, jsMap1, "xxx", 1, null)
-        }
+        val result1 = RhinoScriptEngine.eval(jsMap1, bindings)
         Assert.assertEquals("3242532321", result1)
     }
 
     @Test
     fun testFor() {
-        val scope = Rhino.use {
-            evaluateString(it, printJs, "print", 1, null)
-            it
+        val scope = RhinoScriptEngine.run {
+            val scope = getRuntimeScope(getScriptContext(SimpleBindings()))
+            eval(printJs, scope)
+            scope
         }
 
         @Language("js")
@@ -74,18 +67,13 @@ class JsTest {
             }
             result
         """.trimIndent()
-        val result = Rhino.use {
-            it.prototype = scope
-            evaluateString(it, jsFor, "jsFor", 1, null)
-        }
+        val result = RhinoScriptEngine.eval(jsFor, scope)
         Assert.assertEquals("12012", result)
     }
 
     @Test
     fun testReturnNull() {
-        val result = Rhino.use {
-            eval(it, "null")
-        }
+        val result = RhinoScriptEngine.eval("null")
         Assert.assertEquals(null, result)
     }
 
@@ -101,9 +89,10 @@ class JsTest {
             .replace(/\;/g,";")
             .replace(/\:/g,":")
         """.trimIndent()
-        val result = Rhino.use {
-            it.putBinding("result", ",.!?…;:")
-            eval(it, js)
+        val result = RhinoScriptEngine.run {
+            val bindings = SimpleBindings()
+            bindings["result"] = ",.!?…;:"
+            eval(js)
         }
         Assert.assertEquals(result, ",。!?……;:")
     }
@@ -116,27 +105,22 @@ class JsTest {
         bindings["chapter"] = chapter
         @Language("js")
         val js = "chapter.title"
-        val result = Rhino.use {
-            it.putBinding("chapter", chapter)
-            eval(it, js)
-        }
+        val result = RhinoScriptEngine.eval(js, bindings)
         Assert.assertEquals(result, "xxxyyy")
     }
 
     @Test
     fun javaListForEach() {
         val list = arrayListOf(1, 2, 3)
-
+        val bindings = SimpleBindings()
+        bindings["list"] = list
         @Language("js")
         val js = """
             var result = 0
             list.forEach(item => {result = result + item})
             result
         """.trimIndent()
-        val result = Rhino.use {
-            it.putBinding("list", list)
-            eval(it, js)
-        }
+        val result = RhinoScriptEngine.eval(js, bindings)
         Assert.assertEquals(result, 6.0)
     }