This commit is contained in:
kunfei 2023-03-25 13:56:34 +08:00
parent 56f9b734c3
commit f9b0fc34fa
5 changed files with 76 additions and 96 deletions

View File

@ -1,7 +1,5 @@
package io.legado.app
import com.script.SimpleBindings
import io.legado.app.constant.SCRIPT_ENGINE
import org.junit.Assert.assertEquals
import org.junit.Test
@ -12,21 +10,10 @@ import org.junit.Test
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
@Test
fun jsTest() {
val map = hashMapOf("id" to "3242532321")
map["id"] = "12314123"
val bindings = SimpleBindings()
bindings["result"] = map
val js = "$=result;id=$.id;id"
val result = SCRIPT_ENGINE.eval(js, bindings)?.toString()
assertEquals("12314123", result)
}
}

View File

@ -0,0 +1,52 @@
package io.legado.app
import com.script.SimpleBindings
import io.legado.app.constant.SCRIPT_ENGINE
import org.intellij.lang.annotations.Language
import org.junit.Assert
import org.junit.Test
class JsTest {
@Test
fun testMap() {
val map = hashMapOf("id" to "3242532321")
map["id"] = "12314123"
val bindings = SimpleBindings()
bindings["result"] = map
@Language("js")
val jsMap = "$=result;id=$.id;id"
val result = SCRIPT_ENGINE.eval(jsMap, bindings)?.toString()
Assert.assertEquals("12314123", result)
}
@Test
fun testFor() {
@Language("js")
val jsFor = """
let result = 0
let a=[1,2,3]
let l=a.length
for (let i = 0;i<l;i++){
result = result + a[i]
}
for (let o of a){
result = result + o
}
for (let o in a){
result = result + o
}
result
""".trimIndent()
val result = SCRIPT_ENGINE.eval(jsFor).toString()
Assert.assertEquals("12012", result)
}
@Test
fun testReturnNull() {
val result = SCRIPT_ENGINE.eval("null")
Assert.assertEquals(null, result)
}
}

Binary file not shown.

View File

@ -48,12 +48,12 @@ open class InterfaceImplementor(private val engine: Invocable) {
if (!isImplemented(thiz, iface)) {
null
} else {
val accCtxt = AccessController.getContext()
val accContext = AccessController.getContext()
iface.cast(
Proxy.newProxyInstance(
iface.classLoader,
arrayOf<Class<*>>(iface),
InterfaceImplementorInvocationHandler(thiz, accCtxt)
InterfaceImplementorInvocationHandler(thiz, accContext)
)
)
}
@ -67,7 +67,7 @@ open class InterfaceImplementor(private val engine: Invocable) {
}
@Throws(ScriptException::class)
protected open fun convertResult(method: Method?, res: Any): Any {
protected open fun convertResult(method: Method?, res: Any): Any? {
return res
}
@ -78,10 +78,11 @@ open class InterfaceImplementor(private val engine: Invocable) {
private inner class InterfaceImplementorInvocationHandler(
private val thiz: Any?,
private val accCtxt: AccessControlContext
private val accContext: AccessControlContext
) : InvocationHandler {
@Throws(Throwable::class)
override fun invoke(proxy: Any, method: Method, args: Array<Any>): Any {
override fun invoke(proxy: Any, method: Method, args: Array<Any>): Any? {
val finalArgs = convertArguments(method, args)
val result = AccessController.doPrivileged(PrivilegedExceptionAction {
if (thiz == null) engine.invokeFunction(
@ -90,8 +91,9 @@ open class InterfaceImplementor(private val engine: Invocable) {
) else engine.invokeMethod(
thiz, method.name, *finalArgs
)
} as PrivilegedExceptionAction<Any>, accCtxt)
} as PrivilegedExceptionAction<Any>, accContext)
return convertResult(method, result)
}
}
}

View File

@ -156,48 +156,11 @@ class RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
}
}
fun getRuntimeScope(ctxt: ScriptContext?): Scriptable {
return if (ctxt == null) {
throw NullPointerException("脚本context为空")
} else {
val newScope: Scriptable = ExternalScriptable(ctxt, indexedProps)
newScope.prototype = topLevel
newScope.put("context", newScope, ctxt)
/*
val cx = Context.enter()
try {
@Language("js")
val js = """
function print(str, newline) {
if (typeof(str) == 'undefined') {
str = 'undefined';
} else if (str == null) {
str = 'null';
}
var out = context.getWriter();
if (!(out instanceof java.io.PrintWriter))
out = new java.io.PrintWriter(out);
out.print(String(str));
if (newline) out.print('\\n');
out.flush();
}
function println(str) {
print(str, true);
}
""".trimIndent()
cx.evaluateString(
newScope,
js,
"print",
1,
null
)
} finally {
Context.exit()
}
*/
newScope
}
fun getRuntimeScope(context: ScriptContext): Scriptable {
val newScope: Scriptable = ExternalScriptable(context, indexedProps)
newScope.prototype = topLevel
newScope.put("context", newScope, context)
return newScope
}
@Throws(ScriptException::class)
@ -260,6 +223,7 @@ class RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
}
indexedProps = HashMap()
implementor = object : InterfaceImplementor(this) {
override fun isImplemented(thiz: Any?, iface: Class<*>): Boolean {
var thiz1 = thiz
return try {
@ -289,12 +253,11 @@ class RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
}
}
override fun convertResult(method: Method?, res: Any): Any {
val desiredType = method!!.returnType
return (if (desiredType == Void.TYPE) null else Context.jsToJava(
res,
desiredType
))!!
override fun convertResult(method: Method?, res: Any): Any? {
method ?: return null
val desiredType = method.returnType
if (desiredType == Void.TYPE) return null
return Context.jsToJava(res, desiredType)
}
}
}
@ -302,30 +265,6 @@ class RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
@Suppress("unused")
companion object {
private const val DEBUG = false
/*
@Language("js")
private val printSource = """
function print(str, newline) {
if (typeof str == "undefined") {
str = "undefined";
} else if (str == null) {
str = "null";
}
var out = context.getWriter();
if (!(out instanceof java.io.PrintWriter))
out = new java.io.PrintWriter(out);
out.print(String(str));
if (newline) out.print("\\n");
out.flush();
}
function println(str) {
print(str, true);
}
""".trimIndent()
*/
init {
ContextFactory.initGlobal(object : ContextFactory() {
@ -352,16 +291,16 @@ class RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
thisObj: Scriptable,
args: Array<Any>
): Any? {
var accCtxt: AccessControlContext? = null
var accContext: AccessControlContext? = null
val global = ScriptableObject.getTopLevelScope(scope)
val globalProto = global.prototype
if (globalProto is RhinoTopLevel) {
accCtxt = globalProto.accessContext
accContext = globalProto.accessContext
}
return if (accCtxt != null) AccessController.doPrivileged(
return if (accContext != null) AccessController.doPrivileged(
PrivilegedAction {
superDoTopCall(callable, cx, scope, thisObj, args)
} as PrivilegedAction<*>, accCtxt) else superDoTopCall(
} as PrivilegedAction<*>, accContext) else superDoTopCall(
callable,
cx,
scope,