feat(project): 初始化项目结构和配置

This commit is contained in:
2026-06-10 04:09:02 +08:00
parent 2d301cf1c3
commit 45f883b772
1815 changed files with 315166 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
plugins {
//d 'com.android.library'
//id 'org.jetbrains.kotlin.android'
alias libs.plugins.android.library
alias libs.plugins.kotlin.android
}
android {
compileSdk = compile_sdk_version
namespace = 'com.script'
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
defaultConfig {
minSdk 21
targetSdk 36
consumerProguardFiles "consumer-rules.pro"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
lint {
checkDependencies = true
}
tasks.withType(JavaCompile).tap {
configureEach {
options.compilerArgs << "-Xlint:deprecation"
}
}
}
dependencies {
// api(fileTree(dir: 'lib', include: ['rhino-1.7.14.jar']))
api libs.mozilla.rhino
implementation(libs.kotlinx.coroutines.core)
implementation(libs.okhttp)
implementation(libs.androidx.collection)
// def coroutines_version = '1.7.3'
// implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
}
+54
View File
@@ -0,0 +1,54 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
## Rhino
-keep class
!org.mozilla.javascript.ast.**,
!org.mozilla.javascript.xml.**,
!org.mozilla.javascript.commonjs.**,
!org.mozilla.javascript.optimizer.**,
!org.mozilla.javascript.serialize.**,
org.mozilla.javascript.** { *; }
-dontwarn org.mozilla.javascript.engine.RhinoScriptEngineFactory
### 以下内容是更新rhino1.7.14.jar后IDE提示添加的
-dontwarn java.beans.**
-dontwarn javax.script.**
### 以下内容是更新rhino1.8.0.jar后IDE提示添加的
-dontwarn jdk.dynalink.CallSiteDescriptor
-dontwarn jdk.dynalink.DynamicLinker
-dontwarn jdk.dynalink.DynamicLinkerFactory
-dontwarn jdk.dynalink.NamedOperation
-dontwarn jdk.dynalink.Namespace
-dontwarn jdk.dynalink.NamespaceOperation
-dontwarn jdk.dynalink.Operation
-dontwarn jdk.dynalink.RelinkableCallSite
-dontwarn jdk.dynalink.StandardNamespace
-dontwarn jdk.dynalink.StandardOperation
-dontwarn jdk.dynalink.linker.GuardedInvocation
-dontwarn jdk.dynalink.linker.GuardingDynamicLinker
-dontwarn jdk.dynalink.linker.LinkRequest
-dontwarn jdk.dynalink.linker.LinkerServices
-dontwarn jdk.dynalink.linker.TypeBasedGuardingDynamicLinker
-dontwarn jdk.dynalink.linker.support.CompositeTypeBasedGuardingDynamicLinker
-dontwarn jdk.dynalink.linker.support.Guards
-dontwarn jdk.dynalink.support.ChainedCallSite
BIN
View File
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest>
</manifest>
@@ -0,0 +1,116 @@
/*
* Decompiled with CFR 0.152.
*/
package com.script
import com.script.ScriptContext.Companion.ENGINE_SCOPE
import com.script.ScriptContext.Companion.GLOBAL_SCOPE
import org.mozilla.javascript.Scriptable
import java.io.Reader
import java.io.StringReader
import kotlin.coroutines.CoroutineContext
abstract class AbstractScriptEngine(val bindings: Bindings? = null) : ScriptEngine {
override var context: ScriptContext = SimpleScriptContext()
init {
bindings?.let {
context.setBindings(bindings, ENGINE_SCOPE)
}
}
override fun getBindings(scope: Int): Bindings? {
if (scope == GLOBAL_SCOPE) {
return context.getBindings(GLOBAL_SCOPE)
}
if (scope == ENGINE_SCOPE) {
return context.getBindings(ENGINE_SCOPE)
}
throw IllegalArgumentException("Invalid scope value.")
}
override fun setBindings(bindings: Bindings?, scope: Int) {
when (scope) {
GLOBAL_SCOPE -> {
context.setBindings(bindings, GLOBAL_SCOPE)
}
ENGINE_SCOPE -> {
context.setBindings(bindings, ENGINE_SCOPE)
}
else -> {
throw IllegalArgumentException("Invalid scope value.")
}
}
}
override fun put(key: String, value: Any?) {
getBindings(ENGINE_SCOPE)?.put(key, value)
}
override fun get(key: String): Any? {
return getBindings(ENGINE_SCOPE)?.get(key)
}
override fun eval(reader: Reader, scope: Scriptable): Any? {
return eval(reader, scope, null)
}
override suspend fun evalSuspend(script: String, scope: Scriptable): Any? {
return this.evalSuspend(StringReader(script), scope)
}
override fun eval(script: String, scope: Scriptable): Any? {
return this.eval(StringReader(script), scope)
}
@Throws(ScriptException::class)
override fun eval(reader: Reader, context: ScriptContext): Any? {
return this.eval(reader, getRuntimeScope(context))
}
override fun eval(script: String, scope: Scriptable, coroutineContext: CoroutineContext?): Any? {
return this.eval(StringReader(script), scope, coroutineContext)
}
@Throws(ScriptException::class)
override fun eval(reader: Reader, bindings: Bindings): Any? {
return this.eval(reader, getScriptContext(bindings))
}
@Throws(ScriptException::class)
override fun eval(script: String, bindings: Bindings): Any? {
return this.eval(script, getScriptContext(bindings))
}
@Throws(ScriptException::class)
override fun eval(script: String, bindings: ScriptBindings): Any? {
return this.eval(script, getRuntimeScope(bindings))
}
@Throws(ScriptException::class)
override fun eval(reader: Reader): Any? {
return this.eval(reader, context)
}
@Throws(ScriptException::class)
override fun eval(script: String): Any? {
return this.eval(script, context)
}
@Throws(ScriptException::class)
override fun eval(script: String, context: ScriptContext): Any? {
return this.eval(StringReader(script), context)
}
override fun getScriptContext(bindings: Bindings): ScriptContext {
val ctx = SimpleScriptContext(bindings, context.errorWriter, context.reader, context.writer)
val gs = getBindings(GLOBAL_SCOPE)
if (gs != null) {
ctx.setBindings(gs, GLOBAL_SCOPE)
}
return ctx
}
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Decompiled with CFR 0.152.
*/
package com.script
interface Bindings : MutableMap<String, Any?> {
override fun containsKey(key: String): Boolean
override operator fun get(key: String): Any?
override fun put(key: String, value: Any?): Any?
override fun putAll(from: Map<out String, *>)
override fun remove(key: String): Any?
}
+15
View File
@@ -0,0 +1,15 @@
/*
* Decompiled with CFR 0.152.
*/
package com.script
import java.io.Reader
interface Compilable {
@Throws(ScriptException::class)
fun compile(script: Reader): CompiledScript
@Throws(ScriptException::class)
fun compile(script: String): CompiledScript
}
+50
View File
@@ -0,0 +1,50 @@
/*
* Decompiled with CFR 0.152.
*/
package com.script
import com.script.ScriptContext.Companion.ENGINE_SCOPE
import com.script.ScriptContext.Companion.GLOBAL_SCOPE
import org.mozilla.javascript.Scriptable
import kotlin.coroutines.CoroutineContext
abstract class CompiledScript {
abstract fun getEngine(): ScriptEngine
@Throws(ScriptException::class)
fun eval(context: ScriptContext): Any? {
return eval(getEngine().getRuntimeScope(context))
}
@Throws(ScriptException::class)
fun eval(scope: Scriptable): Any? {
return eval(scope, null)
}
@Throws(ScriptException::class)
abstract fun eval(scope: Scriptable, coroutineContext: CoroutineContext?): Any?
@Throws(ScriptException::class)
abstract suspend fun evalSuspend(scope: Scriptable): Any?
@Throws(ScriptException::class)
fun eval(bindings: Bindings?): Any? {
var ctxt = getEngine().context
if (bindings != null) {
val tempContext = SimpleScriptContext()
tempContext.setBindings(bindings, ENGINE_SCOPE)
tempContext.setBindings(ctxt.getBindings(GLOBAL_SCOPE), GLOBAL_SCOPE)
tempContext.writer = ctxt.writer
tempContext.reader = ctxt.reader
tempContext.errorWriter = ctxt.errorWriter
ctxt = tempContext
}
return this.eval(ctxt)
}
@Throws(ScriptException::class)
fun eval(): Any? {
return this.eval(getEngine().context)
}
}
+16
View File
@@ -0,0 +1,16 @@
/*
* Decompiled with CFR 0.152.
*/
package com.script
interface Invocable {
fun <T> getInterface(clazz: Class<T>): T?
fun <T> getInterface(obj: Any?, paramClass: Class<T>): T?
@Throws(ScriptException::class, NoSuchMethodException::class)
fun invokeFunction(name: String, vararg args: Any): Any?
@Throws(ScriptException::class, NoSuchMethodException::class)
fun invokeMethod(obj: Any?, name: String, vararg args: Any): Any?
}
@@ -0,0 +1,7 @@
package com.script
import org.mozilla.javascript.ContextFactory
open class RhinoContextFactory : ContextFactory() {
}
+46
View File
@@ -0,0 +1,46 @@
package com.script
import org.mozilla.javascript.Context
import org.mozilla.javascript.NativeObject
import org.mozilla.javascript.ScriptableObject
class ScriptBindings : NativeObject() {
companion object {
private val topLevelScope: ScriptableObject by lazy {
val cx = Context.enter()
try {
cx.initStandardObjects()
} finally {
Context.exit()
}
}
}
init {
prototype = topLevelScope
}
operator fun set(key: String, value: Any?) {
Context.enter()
try {
put(key, this, Context.javaToJS(value, this))
} finally {
Context.exit()
}
}
operator fun set(index: Int, value: Any?) {
Context.enter()
try {
put(index, this, Context.javaToJS(value, this))
} finally {
Context.exit()
}
}
fun put(key: String, value: Any?) {
set(key, value)
}
}
@@ -0,0 +1,14 @@
package com.script
import org.mozilla.javascript.Context
inline fun buildScriptBindings(block: (bindings: ScriptBindings) -> Unit): ScriptBindings {
val bindings = ScriptBindings()
Context.enter()
try {
block(bindings)
} finally {
Context.exit()
}
return bindings
}
+37
View File
@@ -0,0 +1,37 @@
/*
* Decompiled with CFR 0.152.
*/
package com.script
import java.io.Reader
import java.io.Writer
interface ScriptContext {
var errorWriter: Writer
var reader: Reader
val scopes: List<Int>
var writer: Writer
fun getAttribute(name: String): Any?
fun getAttribute(name: String, scope: Int): Any?
fun getAttributesScope(name: String): Int
fun getBindings(scope: Int): Bindings?
fun removeAttribute(name: String, scope: Int): Any?
fun setAttribute(name: String, value: Any?, scope: Int)
fun setBindings(bindings: Bindings?, scope: Int)
companion object {
const val ENGINE_SCOPE = 100
const val GLOBAL_SCOPE = 200
}
}
+71
View File
@@ -0,0 +1,71 @@
/*
* Decompiled with CFR 0.152.
*/
package com.script
import org.mozilla.javascript.Scriptable
import java.io.Reader
import kotlin.coroutines.CoroutineContext
interface ScriptEngine {
var context: ScriptContext
fun createBindings(): Bindings?
@Throws(ScriptException::class)
fun eval(reader: Reader, scope: Scriptable): Any?
@Throws(ScriptException::class)
fun eval(reader: Reader, scope: Scriptable, coroutineContext: CoroutineContext?): Any?
@Throws(ScriptException::class)
suspend fun evalSuspend(reader: Reader, scope: Scriptable): Any?
@Throws(ScriptException::class)
fun eval(script: String, scope: Scriptable): Any?
@Throws(ScriptException::class)
suspend fun evalSuspend(script: String, scope: Scriptable): Any?
@Throws(ScriptException::class)
fun eval(script: String, scope: Scriptable, coroutineContext: CoroutineContext?): Any?
@Throws(ScriptException::class)
fun eval(reader: Reader): Any?
@Throws(ScriptException::class)
fun eval(reader: Reader, bindings: Bindings): Any?
@Throws(ScriptException::class)
fun eval(reader: Reader, context: ScriptContext): Any?
@Throws(ScriptException::class)
fun eval(script: String): Any?
@Throws(ScriptException::class)
fun eval(script: String, bindings: Bindings): Any?
@Throws(ScriptException::class)
fun eval(script: String, bindings: ScriptBindings): Any?
@Throws(ScriptException::class)
fun eval(script: String, context: ScriptContext): Any?
fun getRuntimeScope(bindings: ScriptBindings): Scriptable
fun getRuntimeScope(context: ScriptContext): Scriptable
fun getScriptContext(bindings: Bindings): ScriptContext
operator fun get(key: String): Any?
fun getBindings(scope: Int): Bindings?
fun put(key: String, value: Any?)
fun setBindings(bindings: Bindings?, scope: Int)
companion object {
const val FILENAME = "javax.script.filename"
}
}
+54
View File
@@ -0,0 +1,54 @@
/*
* Decompiled with CFR 0.152.
*/
package com.script
class ScriptException : Exception {
var columnNumber: Int
private set
var fileName: String?
private set
var lineNumber: Int
private set
constructor(s: String?) : super(s) {
fileName = null
lineNumber = -1
columnNumber = -1
}
constructor(e: Exception?) : super(e) {
fileName = null
lineNumber = -1
columnNumber = -1
}
constructor(message: String?, fileName2: String?, lineNumber2: Int) : super(message) {
fileName = fileName2
lineNumber = lineNumber2
columnNumber = -1
}
constructor(message: String?, fileName2: String?, lineNumber2: Int, columnNumber2: Int) : super(
message
) {
fileName = fileName2
lineNumber = lineNumber2
columnNumber = columnNumber2
}
override val message: String
get() {
val ret = super.message
if (fileName == null) {
return ret!!
}
var ret2 = "$ret in $fileName"
if (lineNumber != -1) {
ret2 = "$ret2 at line number $lineNumber"
}
return if (columnNumber != -1) {
"$ret2 at column number $columnNumber"
} else ret2
}
}
+54
View File
@@ -0,0 +1,54 @@
/*
* Decompiled with CFR 0.152.
*/
package com.script
class SimpleBindings @JvmOverloads constructor(
private val map: MutableMap<String, Any?> = HashMap()
) : Bindings {
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,0 +1,109 @@
/*
* Decompiled with CFR 0.152.
*/
package com.script
import com.script.ScriptContext.Companion.ENGINE_SCOPE
import com.script.ScriptContext.Companion.GLOBAL_SCOPE
import java.io.InputStreamReader
import java.io.PrintWriter
import java.io.Reader
import java.io.Writer
open class SimpleScriptContext(
private var engineScope: Bindings = SimpleBindings(),
override var errorWriter: Writer = PrintWriter(System.err, true),
override var reader: Reader = InputStreamReader(System.`in`),
override var writer: Writer = PrintWriter(System.out, true)
) : ScriptContext {
private var globalScope: Bindings? = null
override fun setBindings(bindings: Bindings?, scope: Int) {
when (scope) {
ENGINE_SCOPE -> {
if (bindings == null) {
throw NullPointerException("Engine scope cannot be null.")
}
engineScope = bindings
return
}
GLOBAL_SCOPE -> {
globalScope = bindings
return
}
}
throw IllegalArgumentException("Invalid scope value.")
}
override fun getAttribute(name: String): Any? {
return if (engineScope.containsKey(name)) {
this.getAttribute(name, ENGINE_SCOPE)
} else if (globalScope?.containsKey(name) == true) {
this.getAttribute(name, GLOBAL_SCOPE)
} else {
null
}
}
override fun getAttribute(name: String, scope: Int): Any? {
when (scope) {
ENGINE_SCOPE -> {
return engineScope[name]
}
GLOBAL_SCOPE -> {
return globalScope?.get(name)
}
}
throw IllegalArgumentException("Illegal scope value.")
}
override fun removeAttribute(name: String, scope: Int): Any? {
when (scope) {
ENGINE_SCOPE -> {
return getBindings(ENGINE_SCOPE)?.remove(name)
}
GLOBAL_SCOPE -> {
return getBindings(GLOBAL_SCOPE)?.remove(name)
}
}
throw IllegalArgumentException("Illegal scope value.")
}
override fun setAttribute(name: String, value: Any?, scope: Int) {
when (scope) {
ENGINE_SCOPE -> engineScope[name] = value
GLOBAL_SCOPE -> globalScope?.put(name, value)
else -> throw IllegalArgumentException("Illegal scope value.")
}
}
override fun getAttributesScope(name: String): Int {
return if (engineScope.containsKey(name)) {
ENGINE_SCOPE
} else if (globalScope?.containsKey(name) == true) {
GLOBAL_SCOPE
} else {
-1
}
}
override fun getBindings(scope: Int): Bindings? {
if (scope == ENGINE_SCOPE) {
return engineScope
}
if (scope == GLOBAL_SCOPE) {
return globalScope
}
throw IllegalArgumentException("Illegal scope value.")
}
override val scopes: List<Int>
get() = Companion.scopes
companion object {
private val scopes = listOf(ENGINE_SCOPE, GLOBAL_SCOPE)
}
}
@@ -0,0 +1,41 @@
package com.script.rhino
import androidx.collection.LruCache
import kotlin.math.min
class ClassNameMatcher(classNames: List<String>) {
private val sortedClassNames = classNames.sorted()
private val matchCache = LruCache<String, Boolean>(64)
fun match(className: String): Boolean {
matchCache[className]?.let {
return it
}
val match = matchInternal(className)
matchCache.put(className, match)
return match
}
private fun matchInternal(className: String): Boolean {
val index = sortedClassNames.fastBinarySearch { prefix ->
comparePrefix(className, prefix)
}
if (index >= 0) {
return true
}
val prefix = sortedClassNames.getOrNull(-index - 2) ?: return false
return className.getOrNull(prefix.length) == '.' && className.startsWith(prefix)
}
private fun comparePrefix(className: String, prefix: String): Int {
val len = min(className.length, prefix.length)
for (i in 0 ..< len) {
val c1 = className[i]
val c2 = prefix[i]
if (c1 != c2) return c2 - c1
}
return prefix.length - className.length
}
}
@@ -0,0 +1,22 @@
package com.script.rhino
inline fun <T> List<T>.fastBinarySearch(
comparison: (T) -> Int
): Int {
var low = 0
var high = lastIndex
while (low <= high) {
val mid = (low + high).ushr(1) // safe from overflows
val midVal = get(mid)
val cmp = comparison(midVal)
if (cmp < 0)
low = mid + 1
else if (cmp > 0)
high = mid - 1
else
return mid // key found
}
return -(low + 1) // key not found
}
@@ -0,0 +1,294 @@
/*
* Copyright (c) 2005, 2006, 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 com.script.rhino
import com.script.ScriptContext
import org.mozilla.javascript.*
import org.mozilla.javascript.Function
/**
* ExternalScriptable is an implementation of Scriptable
* backed by a JSR 223 ScriptContext instance.
*
* @author Mike Grogan
* @author A. Sundararajan
* @since 1.6
*/
internal class ExternalScriptable @JvmOverloads constructor(
val context: ScriptContext,
private val indexedProps: MutableMap<Any, Any?> = HashMap()
) : Scriptable {
private var prototype: Scriptable? = null
private var parent: Scriptable? = null
private fun isEmpty(name: String): Boolean {
return name == ""
}
override fun getClassName(): String {
return "Global"
}
@Synchronized
override fun get(name: String, start: Scriptable): Any? {
return if (this.isEmpty(name)) {
indexedProps.getOrElse(name) { Scriptable.NOT_FOUND }
} else {
synchronized(context) {
val scope = context.getAttributesScope(name)
return if (scope != -1) {
val value = context.getAttribute(name, scope)
Context.javaToJS(value, this)
} else {
Scriptable.NOT_FOUND
}
}
}
}
@Synchronized
override fun get(index: Int, start: Scriptable): Any? {
return indexedProps.getOrElse(index) { Scriptable.NOT_FOUND }
}
@Synchronized
override fun has(name: String, start: Scriptable): Boolean {
return if (this.isEmpty(name)) {
indexedProps.containsKey(name)
} else {
synchronized(context) { return context.getAttributesScope(name) != -1 }
}
}
@Synchronized
override fun has(index: Int, start: Scriptable): Boolean {
return indexedProps.containsKey(index)
}
override fun put(name: String, start: Scriptable, value: Any?) {
if (start === this) {
synchronized(this) {
if (this.isEmpty(name)) {
indexedProps.put(name, value)
} else {
synchronized(context) {
var scope = context.getAttributesScope(name)
if (scope == -1) {
scope = 100
}
context.setAttribute(name, jsToJava(value), scope)
}
}
}
} else {
start.put(name, start, value)
}
}
override fun put(index: Int, start: Scriptable, value: Any?) {
if (start === this) {
synchronized(this) { indexedProps.put(index, value) }
} else {
start.put(index, start, value)
}
}
@Synchronized
override fun delete(name: String) {
if (this.isEmpty(name)) {
indexedProps.remove(name)
} else {
synchronized(context) {
val scope = context.getAttributesScope(name)
if (scope != -1) {
context.removeAttribute(name, scope)
}
}
}
}
override fun delete(index: Int) {
indexedProps.remove(index)
}
override fun getPrototype(): Scriptable? {
return prototype
}
override fun setPrototype(prototype: Scriptable?) {
this.prototype = prototype
}
override fun getParentScope(): Scriptable? {
return parent
}
override fun setParentScope(parent: Scriptable?) {
this.parent = parent
}
@Synchronized
override fun getIds(): Array<Any> {
val keys = allKeys
val size = keys.size + indexedProps.size
val res = arrayOfNulls<Any>(size)
System.arraycopy(keys, 0, res, 0, keys.size)
var i = keys.size
var index: Any
val var5: Iterator<*> = indexedProps.keys.iterator()
while (var5.hasNext()) {
index = var5.next()!!
res[i++] = index
}
@Suppress("UNCHECKED_CAST")
return res as Array<Any>
}
override fun getDefaultValue(typeHint: Class<*>?): Any {
for (i in 0..1) {
val tryToString: Boolean =
if (typeHint == ScriptRuntime.StringClass) {
i == 0
} else {
i == 1
}
var methodName: String
var args: Array<Any?>
if (tryToString) {
methodName = "toString"
args = ScriptRuntime.emptyArgs
} else {
methodName = "valueOf"
args = arrayOfNulls(1)
val hint: String = when {
typeHint == null -> {
"undefined"
}
typeHint == ScriptRuntime.StringClass -> {
"string"
}
typeHint == ScriptRuntime.ScriptableClass -> {
"object"
}
typeHint == ScriptRuntime.FunctionClass -> {
"function"
}
typeHint != ScriptRuntime.BooleanClass && typeHint != java.lang.Boolean.TYPE -> {
if (typeHint != ScriptRuntime.NumberClass
&& typeHint != ScriptRuntime.ByteClass
&& typeHint != java.lang.Byte.TYPE
&& typeHint != ScriptRuntime.ShortClass
&& typeHint != java.lang.Short.TYPE
&& typeHint != ScriptRuntime.IntegerClass
&& typeHint != Integer.TYPE
&& typeHint != ScriptRuntime.FloatClass
&& typeHint != java.lang.Float.TYPE
&& typeHint != ScriptRuntime.DoubleClass
&& typeHint != java.lang.Double.TYPE
) {
throw Context.reportRuntimeError("Invalid JavaScript value of type $typeHint")
}
"number"
}
else -> {
"boolean"
}
}
args[0] = hint
}
var v = ScriptableObject.getProperty(this, methodName)
if (v is Function) {
val function = v
val cx = Context.enter()
v = try {
function.call(cx, function.parentScope, this, args)
} finally {
Context.exit()
}
if (v != null) {
if (v !is Scriptable) {
return v
}
if (typeHint == ScriptRuntime.ScriptableClass || typeHint == ScriptRuntime.FunctionClass) {
return v
}
if (tryToString && v is Wrapper) {
val u = (v as Wrapper).unwrap()
if (u is String) {
return u
}
}
}
}
}
val arg = if (typeHint == null) "undefined" else typeHint.name
throw Context.reportRuntimeError("找不到对象的默认值 $arg")
}
override fun hasInstance(instance: Scriptable): Boolean {
var proto = instance.prototype
while (proto != null) {
if (proto == this) {
return true
}
proto = proto.prototype
}
return false
}
private val allKeys: Array<String>
get() {
val list = ArrayList<String>()
synchronized(context) {
val iterator: Iterator<*> = context.scopes.iterator()
while (iterator.hasNext()) {
val scope = iterator.next() as Int
val bindings = context.getBindings(scope)
if (bindings != null) {
list.ensureCapacity(bindings.size)
val iterator1: Iterator<*> = bindings.keys.iterator()
while (iterator1.hasNext()) {
val key = iterator1.next() as String
list.add(key)
}
}
}
}
return list.toTypedArray()
}
private fun jsToJava(jsObj: Any?): Any? {
return if (jsObj is Wrapper) {
if (jsObj is NativeJavaClass) {
jsObj
} else {
val obj = jsObj.unwrap()
if (obj !is Number && obj !is String && obj !is Boolean && obj !is Char) obj else jsObj
}
} else {
jsObj
}
}
}
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2005, 2011, 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 com.script.rhino
import com.script.Invocable
import com.script.ScriptException
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy
import java.security.AccessControlContext
import java.security.AccessController
import java.security.PrivilegedExceptionAction
/**
* java.lang.reflect.Proxy based interface implementor. This is meant
* to be used to implement Invocable.getInterface.
*
* @author Mike Grogan
* @since 1.6
*/
@Suppress("UNUSED_PARAMETER")
open class InterfaceImplementor(private val engine: Invocable) {
@Throws(ScriptException::class)
fun <T> getInterface(obj: Any?, clazz: Class<T>?): T? {
return if (clazz != null && clazz.isInterface) {
if (!isImplemented(obj, clazz)) {
null
} else {
val accContext = AccessController.getContext()
clazz.cast(
Proxy.newProxyInstance(
clazz.classLoader,
arrayOf<Class<*>>(clazz),
InterfaceImplementorInvocationHandler(obj, accContext)
)
)
}
} else {
throw IllegalArgumentException("interface Class expected")
}
}
protected open fun isImplemented(obj: Any?, clazz: Class<*>): Boolean {
return true
}
@Throws(ScriptException::class)
protected open fun convertResult(method: Method?, res: Any?): Any? {
return res
}
@Throws(ScriptException::class)
protected fun convertArguments(method: Method?, args: Array<Any>): Array<Any> {
return args
}
private inner class InterfaceImplementorInvocationHandler(
private val obj: Any?,
private val accContext: AccessControlContext
) : InvocationHandler {
@Throws(Throwable::class)
override fun invoke(proxy: Any, method: Method, args: Array<Any>): Any? {
val finalArgs = convertArguments(method, args)
val result = AccessController.doPrivileged(PrivilegedExceptionAction {
if (obj == null) engine.invokeFunction(method.name, *finalArgs)
else engine.invokeMethod(obj, method.name, *finalArgs)
}, accContext)
return convertResult(method, result)
}
}
}
+307
View File
@@ -0,0 +1,307 @@
/*
* 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 com.script.rhino
import org.mozilla.javascript.*
import org.mozilla.javascript.Function
/**
* JSAdapter is java.lang.reflect.Proxy equivalent for JavaScript. JSAdapter
* calls specially named JavaScript methods on an adaptee object when property
* access is attempted on it.
*
* Example:
*
* var y = {
* __get__ : function (name) { ... }
* __has__ : function (name) { ... }
* __put__ : function (name, value) {...}
* __delete__ : function (name) { ... }
* __getIds__ : function () { ... }
* };
*
* var x = new JSAdapter(y);
*
* x.i; // calls y.__get__
* i in x; // calls y.__has__
* x.p = 10; // calls y.__put__
* delete x.p; // calls y.__delete__
* for (i in x) { print(i); } // calls y.__getIds__
*
* If a special JavaScript method is not found in the adaptee, then JSAdapter
* forwards the property access to the adaptee itself.
*
* JavaScript caller of adapter object is isolated from the fact that
* the property access/mutation/deletion are really calls to
* JavaScript methods on adaptee. Use cases include 'smart'
* properties, property access tracing/debugging, encaptulation with
* easy client access - in short JavaScript becomes more "Self" like.
*
* Note that Rhino already supports special properties like __proto__
* (to set, get prototype), __parent__ (to set, get parent scope). We
* follow the same double underscore nameing convention here. Similarly
* the name JSAdapter is derived from JavaAdapter -- which is a facility
* to extend, implement Java classes/interfaces by JavaScript.
*
* @author A. Sundararajan
* @since 1.6
*/
@Suppress("unused", "UNUSED_PARAMETER")
class JSAdapter private constructor(var adaptee: Scriptable) : Scriptable, Function {
private var prototype: Scriptable? = null
private var parent: Scriptable? = null
private var isPrototype = false
override fun getClassName(): String {
return "JSAdapter"
}
override fun get(name: String, start: Scriptable): Any {
val func = getAdapteeFunction(GET_PROP)
return if (func != null) {
this.call(func, arrayOf(name))
} else {
adaptee[name, adaptee]
}
}
override fun get(index: Int, start: Scriptable): Any {
val func = getAdapteeFunction(GET_PROP)
return if (func != null) {
this.call(func, arrayOf(index))
} else {
adaptee[index, adaptee]
}
}
override fun has(name: String, start: Scriptable): Boolean {
val func = getAdapteeFunction(HAS_PROP)
return if (func != null) {
val res = this.call(func, arrayOf(name))
Context.toBoolean(res)
} else {
adaptee.has(name, adaptee)
}
}
override fun has(index: Int, start: Scriptable): Boolean {
val func = getAdapteeFunction(HAS_PROP)
return if (func != null) {
val res = this.call(func, arrayOf(index))
Context.toBoolean(res)
} else {
adaptee.has(index, adaptee)
}
}
override fun put(name: String, start: Scriptable, value: Any) {
if (start === this) {
val func = getAdapteeFunction(PUT_PROP)
if (func != null) {
this.call(func, arrayOf(name, value))
} else {
adaptee.put(name, adaptee, value)
}
} else {
start.put(name, start, value)
}
}
override fun put(index: Int, start: Scriptable, value: Any) {
if (start === this) {
val func = getAdapteeFunction(PUT_PROP)
if (func != null) {
this.call(func, arrayOf(index, value))
} else {
adaptee.put(index, adaptee, value)
}
} else {
start.put(index, start, value)
}
}
override fun delete(name: String) {
val func = getAdapteeFunction(DEL_PROP)
if (func != null) {
this.call(func, arrayOf(name))
} else {
adaptee.delete(name)
}
}
override fun delete(index: Int) {
val func = getAdapteeFunction(DEL_PROP)
if (func != null) {
this.call(func, arrayOf(index))
} else {
adaptee.delete(index)
}
}
override fun getPrototype(): Scriptable? {
return prototype
}
override fun setPrototype(prototype: Scriptable?) {
this.prototype = prototype
}
override fun getParentScope(): Scriptable? {
return parent
}
override fun setParentScope(parent: Scriptable?) {
this.parent = parent
}
override fun getIds(): Array<Any?> {
val func = getAdapteeFunction(GET_PROPIDS)
return if (func == null) {
adaptee.ids
} else {
val val1 = this.call(func, arrayOfNulls(0))
val res: Array<Any?>
when (val1) {
is NativeArray -> {
res = arrayOfNulls(val1.length.toInt())
for (index in res.indices) {
res[index] = mapToId(val1[index, val1])
}
res
}
!is NativeJavaArray -> {
Context.emptyArgs
}
else -> {
val tmp = val1.unwrap()
if (tmp.javaClass == Array<Any>::class.java) {
val array = tmp as Array<*>
res = arrayOfNulls(array.size)
for (index in array.indices) {
res[index] = mapToId(array[index])
}
} else {
res = Context.emptyArgs
}
res
}
}
}
}
override fun hasInstance(scriptable: Scriptable): Boolean {
return if (scriptable is JSAdapter) {
true
} else {
var proto = scriptable.prototype
while (proto != null) {
if (proto == this) {
return true
}
proto = proto.prototype
}
false
}
}
override fun getDefaultValue(hint: Class<*>?): Any {
return adaptee.getDefaultValue(hint)
}
@Throws(RhinoException::class)
override fun call(cx: Context, scope: Scriptable, thisObj: Scriptable, args: Array<Any>): Any {
return if (isPrototype) {
construct(cx, scope, args)
} else {
val tmp = adaptee
if (tmp is Function) {
tmp.call(cx, scope, tmp, args)
} else {
throw Context.reportRuntimeError("TypeError: not a function")
}
}
}
@Throws(RhinoException::class)
override fun construct(cx: Context, scope: Scriptable, args: Array<Any>): Scriptable {
val tmp: Scriptable?
return if (isPrototype) {
tmp = ScriptableObject.getTopLevelScope(scope)
if (args.isNotEmpty()) {
JSAdapter(Context.toObject(args[0], tmp))
} else {
throw Context.reportRuntimeError("JSAdapter requires adaptee")
}
} else {
tmp = adaptee
if (tmp is Function) {
tmp.construct(cx, scope, args)
} else {
throw Context.reportRuntimeError("TypeError: not a constructor")
}
}
}
private fun mapToId(tmp: Any?): Any {
return if (tmp is Double) tmp.toInt() else Context.toString(tmp)
}
private fun getAdapteeFunction(name: String): Function? {
val o = ScriptableObject.getProperty(adaptee, name)
return o as? Function
}
private fun call(func: Function, args: Array<Any?>): Any {
val cx = Context.getCurrentContext()
val thisObj = adaptee
val scope = func.parentScope
return try {
func.call(cx, scope, thisObj, args)
} catch (re: RhinoException) {
throw Context.reportRuntimeError(re.message)
}
}
companion object {
private const val GET_PROP = "__get__"
private const val HAS_PROP = "__has__"
private const val PUT_PROP = "__put__"
private const val DEL_PROP = "__delete__"
private const val GET_PROPIDS = "__getIds__"
@Throws(RhinoException::class)
fun init(cx: Context, scope: Scriptable, sealed: Boolean) {
val obj = JSAdapter(cx.newObject(scope))
obj.parentScope = scope
obj.setPrototype(getFunctionPrototype(scope))
obj.isPrototype = true
ScriptableObject.defineProperty(scope, "JSAdapter", obj, 2)
}
private fun getFunctionPrototype(scope: Scriptable): Scriptable {
return ScriptableObject.getFunctionPrototype(scope)
}
}
}
+104
View File
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2005, 2006, 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 com.script.rhino
import com.script.Invocable
import org.mozilla.javascript.*
import org.mozilla.javascript.Function
/**
* This class implements Rhino-like JavaAdapter to help implement a Java
* interface in JavaScript. We support this using Invocable.getInterface.
* Using this JavaAdapter, script author could write:
*
*
* var r = new java.lang.Runnable() {
* run: function() { script... }
* };
*
*
* r.run();
* new java.lang.Thread(r).start();
*
*
* Note that Rhino's JavaAdapter support allows extending a Java class and/or
* implementing one or more interfaces. This JavaAdapter implementation does
* not support these.
*
* @author A. Sundararajan
* @since 1.6
*/
@Suppress("UNUSED_PARAMETER")
internal class JavaAdapter private constructor(private val engine: Invocable) : ScriptableObject(),
Function {
override fun getClassName(): String {
return "JavaAdapter"
}
@Throws(RhinoException::class)
override fun call(cx: Context, scope: Scriptable, thisObj: Scriptable, args: Array<Any>): Any {
return construct(cx, scope, args)
}
@Throws(RhinoException::class)
override fun construct(cx: Context, scope: Scriptable, args: Array<Any>): Scriptable {
return if (args.size == 2) {
var clazz: Class<*>? = null
val obj = args[0]
if (obj is Wrapper) {
val o = obj.unwrap()
if (o is Class<*> && o.isInterface) {
clazz = o
}
} else if (obj is Class<*> && obj.isInterface) {
clazz = obj
}
if (clazz == null) {
throw Context.reportRuntimeError("JavaAdapter: first arg should be interface Class")
} else {
val topLevel = getTopLevelScope(scope)
Context.toObject(
engine.getInterface(args[1], clazz),
topLevel
)
}
} else {
throw Context.reportRuntimeError("JavaAdapter requires two arguments")
}
}
companion object {
@JvmStatic
@Throws(RhinoException::class)
fun init(cx: Context, scope: Scriptable, sealed: Boolean) {
val topLevel = scope as RhinoTopLevel
val engine: Invocable = topLevel.scriptEngine
val obj = JavaAdapter(engine)
obj.parentScope = scope
obj.prototype = getFunctionPrototype(scope)
putProperty(topLevel, "JavaAdapter", obj)
}
}
}
@@ -0,0 +1,9 @@
package com.script.rhino
import org.mozilla.javascript.Scriptable
fun interface JavaObjectWrapFactory {
fun wrap(scope: Scriptable?, javaObject: Any, staticType: Class<*>?): Scriptable
}
@@ -0,0 +1,44 @@
package com.script.rhino
import org.mozilla.javascript.NativeJavaClass
import org.mozilla.javascript.Scriptable
class ProtectedNativeJavaClass(
scope: Scriptable,
javaClass: Class<*>,
private val protectedName: Set<String> = emptySet()
) : NativeJavaClass(scope, javaClass) {
override fun has(
name: String,
start: Scriptable?
): Boolean {
if (protectedName.contains(name)) {
return false
}
return super.has(name, start)
}
override fun get(name: String, start: Scriptable?): Any? {
if (protectedName.contains(name)) {
return NOT_FOUND
}
return super.get(name, start)
}
override fun put(
name: String,
start: Scriptable?,
value: Any?
) {
if (protectedName.contains(name)) {
return
}
super.put(name, start, value)
}
override fun unwrap(): Any? {
return javaObject.toString()
}
}
@@ -0,0 +1,43 @@
package com.script.rhino
import org.mozilla.javascript.NativeJavaObject
import org.mozilla.javascript.Scriptable
class ReadOnlyJavaObject(scope: Scriptable?, javaObject: Any, staticType: Class<*>?) :
NativeJavaObject(scope, javaObject, staticType) {
override fun has(name: String, start: Scriptable): Boolean {
if (name.length > 3 && name.startsWith("set")) {
val name = name.substring(3).replaceFirstChar { it.lowercase() }
if (super.has(name, start)) {
return false
}
}
return super.has(name, start)
}
override fun get(name: String, start: Scriptable): Any? {
if (name.length > 3 && name.startsWith("set")) {
val name = name.substring(3).replaceFirstChar { it.lowercase() }
if (super.has(name, start)) {
return NOT_FOUND
}
}
return super.get(name, start)
}
override fun put(
name: String?,
start: Scriptable?,
value: Any?
) {
// do nothing
}
companion object {
val factory = JavaObjectWrapFactory { scope, javaObject, staticType ->
ReadOnlyJavaObject(scope, javaObject, staticType)
}
}
}
@@ -0,0 +1,190 @@
/*
* 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 com.script.rhino
import android.os.Build
import org.mozilla.javascript.ClassShutter
import org.mozilla.javascript.Context
import org.mozilla.javascript.Scriptable
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.lang.reflect.Member
import java.nio.file.FileSystem
import java.nio.file.Path
import java.util.Collections
/**
* 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 protectedClassNamesMatcher by lazy {
listOf(
"java.lang.Class",
"java.lang.ClassLoader",
"java.net.URLClassLoader",
"java.lang.Runtime",
"java.lang.ProcessBuilder",
"java.lang.ProcessImpl",
"java.lang.UNIXProcess",
"java.io.File",
"java.io.FileDescriptor",
"java.io.FileInputStream",
"java.io.FileOutputStream",
"java.io.PrintStream",
"java.io.FileReader",
"java.io.FileWriter",
"java.io.PrintWriter",
"java.io.UnixFileSystem",
"java.io.RandomAccessFile",
"java.io.ObjectInputStream",
"java.io.ObjectOutputStream",
"java.security.AccessController",
"java.nio.file.Paths",
"java.nio.file.Files",
"java.nio.file.FileSystems",
"java.util.Formatter",
"sun.misc.Unsafe",
"android.content.Intent",
"android.provider.Settings",
"android.app.ActivityThread",
"android.app.AppGlobals",
"android.os.Looper",
"android.os.Process",
"android.os.FileUtils",
"cn.hutool.core.lang.JarClassLoader",
"cn.hutool.core.lang.Singleton",
"cn.hutool.core.util.RuntimeUtil",
"cn.hutool.core.util.ClassLoaderUtil",
"cn.hutool.core.util.ReflectUtil",
"cn.hutool.core.util.SerializeUtil",
"cn.hutool.core.util.ClassUtil",
"org.mozilla.javascript.DefiningClassLoader",
"io.legado.app.data.AppDatabase",
"io.legado.app.data.AppDatabase_Impl",
"io.legado.app.data.AppDatabaseKt",
"io.legado.app.utils.ContextExtensionsKt",
"androidx.core.content.FileProvider",
"splitties.init.AppCtxKt",
"okio.JvmSystemFileSystem",
"okio.JvmFileHandle",
"okio.NioSystemFileSystem",
"okio.NioFileSystemFileHandle",
"okio.Path",
"android.system",
"android.database",
"androidx.sqlite.db",
"androidx.room",
"cn.hutool.core.io",
"cn.hutool.core.bean",
"cn.hutool.core.lang.reflect",
"dalvik.system",
"java.nio.file",
"java.lang.reflect",
"java.lang.invoke",
"io.legado.app.data.dao",
"com.script",
"org.mozilla",
"sun",
"libcore",
).let { ClassNameMatcher(it) }
}
private val systemClassProtectedName by lazy {
Collections.unmodifiableSet(hashSetOf("load", "loadLibrary", "exit"))
}
private val protectedClasses by lazy {
arrayOf(
ClassLoader::class.java,
Class::class.java,
Member::class.java,
Context::class.java,
ObjectInputStream::class.java,
ObjectOutputStream::class.java,
okio.FileSystem::class.java,
okio.FileHandle::class.java,
okio.Path::class.java,
android.content.Context::class.java,
) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
arrayOf(FileSystem::class.java, Path::class.java)
} else {
emptyArray()
}
}
fun visibleToScripts(obj: Any): Boolean {
when (obj) {
is ClassLoader,
is Class<*>,
is Member,
is Context,
is ObjectInputStream,
is ObjectOutputStream,
is okio.FileSystem,
is okio.FileHandle,
is okio.Path,
is android.content.Context -> return false
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
when (obj) {
is FileSystem,
is Path -> return false
}
}
return visibleToScripts(obj.javaClass.name)
}
fun visibleToScripts(clazz: Class<*>): Boolean {
protectedClasses.forEach {
if (it.isAssignableFrom(clazz)) {
return false
}
}
return true
}
fun wrapJavaClass(scope: Scriptable, javaClass: Class<*>): Scriptable {
return when (javaClass) {
System::class.java -> {
ProtectedNativeJavaClass(scope, javaClass, systemClassProtectedName)
}
else -> ProtectedNativeJavaClass(scope, javaClass)
}
}
override fun visibleToScripts(fullClassName: String): Boolean {
return !protectedClassNamesMatcher.match(fullClassName)
}
}
@@ -0,0 +1,135 @@
/*
* Copyright (c) 2005, 2006, 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 com.script.rhino
import com.script.CompiledScript
import com.script.ScriptEngine
import com.script.ScriptException
import kotlinx.coroutines.Job
import kotlinx.coroutines.asContextElement
import kotlinx.coroutines.withContext
import org.mozilla.javascript.Context
import org.mozilla.javascript.ContinuationPending
import org.mozilla.javascript.JavaScriptException
import org.mozilla.javascript.RhinoException
import org.mozilla.javascript.Script
import org.mozilla.javascript.Scriptable
import java.io.IOException
import kotlin.coroutines.CoroutineContext
/**
* Represents compiled JavaScript code.
*
* @author Mike Grogan
* @since 1.6
*/
internal class RhinoCompiledScript(
private val engine: RhinoScriptEngine,
private val script: Script
) : CompiledScript() {
override fun getEngine(): ScriptEngine {
return engine
}
override fun eval(scope: Scriptable, coroutineContext: CoroutineContext?): Any? {
val cx = Context.enter() as RhinoContext
val previousCoroutineContext = cx.coroutineContext
if (coroutineContext != null && coroutineContext[Job] != null) {
cx.coroutineContext = coroutineContext
}
cx.allowScriptRun = true
cx.recursiveCount++
val result: Any?
try {
cx.checkRecursive()
val ret = script.exec(cx, scope)
result = engine.unwrapReturnValue(ret)
} catch (re: RhinoException) {
val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
val msg: String = if (re is JavaScriptException) {
re.value.toString()
} else {
re.toString()
}
val se = ScriptException(msg, re.sourceName(), line)
se.initCause(re)
throw se
} finally {
cx.coroutineContext = previousCoroutineContext
cx.allowScriptRun = false
cx.recursiveCount--
Context.exit()
}
return result
}
override suspend fun evalSuspend(scope: Scriptable): Any? {
val cx = Context.enter() as RhinoContext
var ret: Any?
withContext(VMBridgeReflect.contextLocal.asContextElement()) {
cx.allowScriptRun = true
cx.recursiveCount++
try {
cx.checkRecursive()
try {
ret = cx.executeScriptWithContinuations(script, scope)
} catch (e: ContinuationPending) {
var pending = e
while (true) {
try {
@Suppress("UNCHECKED_CAST")
val suspendFunction = pending.applicationState as suspend () -> Any?
val functionResult = suspendFunction()
val continuation = pending.continuation
ret = cx.resumeContinuation(continuation, scope, functionResult)
break
} catch (e: ContinuationPending) {
pending = e
}
}
}
} catch (re: RhinoException) {
val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
val msg: String = if (re is JavaScriptException) {
re.value.toString()
} else {
re.toString()
}
val se = ScriptException(msg, re.sourceName(), line)
se.initCause(re)
throw se
} catch (var14: IOException) {
throw ScriptException(var14)
} finally {
cx.allowScriptRun = false
cx.recursiveCount--
Context.exit()
}
}
return engine.unwrapReturnValue(ret)
}
}
@@ -0,0 +1,31 @@
package com.script.rhino
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.ensureActive
import org.mozilla.javascript.Context
import org.mozilla.javascript.ContextFactory
import kotlin.coroutines.CoroutineContext
class RhinoContext(factory: ContextFactory) : Context(factory) {
var coroutineContext: CoroutineContext? = null
var allowScriptRun = false
var recursiveCount = 0
@Throws(RhinoInterruptError::class)
fun ensureActive() {
try {
coroutineContext?.ensureActive()
} catch (e: CancellationException) {
throw RhinoInterruptError(e)
}
}
@Throws(RhinoRecursionError::class)
fun checkRecursive() {
if (recursiveCount >= 10) {
throw RhinoRecursionError()
}
}
}
@@ -0,0 +1,5 @@
package com.script.rhino
class RhinoInterruptError(override val cause: Throwable) : Error()
class RhinoRecursionError(): Error("Maximum recursion depth exceeded.")
@@ -0,0 +1,65 @@
package com.script.rhino
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.supervisorScope
import org.mozilla.javascript.Context
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.coroutines.ContinuationInterceptor
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext
val rhinoContext: RhinoContext
get() = Context.getCurrentContext() as RhinoContext
val rhinoContextOrNull: RhinoContext?
get() = Context.getCurrentContext() as? RhinoContext
@Suppress("LEAKED_IN_PLACE_LAMBDA", "WRONG_INVOCATION_KIND")
@OptIn(ExperimentalContracts::class)
inline fun <T> suspendContinuation(crossinline block: suspend CoroutineScope.() -> T): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
val cx = Context.enter()
try {
val pending = cx.captureContinuation()
pending.applicationState = suspend {
supervisorScope {
block()
}
}
throw pending
} catch (e: IllegalStateException) {
return runBlocking { block() }
} finally {
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()
}
}
@@ -0,0 +1,446 @@
/*
* Copyright (c) 2005, 2011, 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 com.script.rhino
import com.script.AbstractScriptEngine
import com.script.Bindings
import com.script.Compilable
import com.script.CompiledScript
import com.script.Invocable
import com.script.ScriptBindings
import com.script.ScriptContext
import com.script.ScriptException
import com.script.SimpleBindings
import kotlinx.coroutines.Job
import kotlinx.coroutines.asContextElement
import kotlinx.coroutines.withContext
import org.mozilla.javascript.Callable
import org.mozilla.javascript.ConsString
import org.mozilla.javascript.Context
import org.mozilla.javascript.ContextFactory
import org.mozilla.javascript.ContinuationPending
import org.mozilla.javascript.Function
import org.mozilla.javascript.JavaScriptException
import org.mozilla.javascript.RhinoException
import org.mozilla.javascript.Scriptable
import org.mozilla.javascript.ScriptableObject
import org.mozilla.javascript.Undefined
import org.mozilla.javascript.Wrapper
import java.io.IOException
import java.io.Reader
import java.io.StringReader
import java.lang.reflect.Method
import java.security.AccessControlContext
import java.security.AccessControlException
import java.security.AccessController
import java.security.AllPermission
import java.security.PrivilegedAction
import kotlin.coroutines.CoroutineContext
/**
* Implementation of `ScriptEngine` using the Mozilla Rhino
* interpreter.
*
* @author Mike Grogan
* @author A. Sundararajan
* @since 1.6
*/
@Suppress("MemberVisibilityCanBePrivate")
object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
var accessContext: AccessControlContext? = null
private var topLevel: RhinoTopLevel? = null
private val indexedProps: MutableMap<Any, Any?>
private val implementor: InterfaceImplementor
fun eval(js: String, bindingsConfig: ScriptBindings.() -> Unit = {}): Any? {
val bindings = ScriptBindings()
Context.enter()
try {
bindings.apply(bindingsConfig)
} finally {
Context.exit()
}
return eval(js, bindings)
}
override fun eval(
reader: Reader,
scope: Scriptable,
coroutineContext: CoroutineContext?
): Any? {
val cx = Context.enter() as RhinoContext
val previousCoroutineContext = cx.coroutineContext
if (coroutineContext != null && coroutineContext[Job] != null) {
cx.coroutineContext = coroutineContext
}
cx.allowScriptRun = true
cx.recursiveCount++
val ret: Any?
try {
cx.checkRecursive()
var filename = this["javax.script.filename"] as? String
filename = filename ?: "<Unknown source>"
ret = cx.evaluateReader(scope, reader, filename, 1, null)
} catch (re: RhinoException) {
val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
val msg: String = if (re is JavaScriptException) {
re.value.toString()
} else {
re.toString()
}
val se = ScriptException(msg, re.sourceName(), line)
se.initCause(re)
throw se
} catch (var14: IOException) {
throw ScriptException(var14)
} finally {
cx.coroutineContext = previousCoroutineContext
cx.allowScriptRun = false
cx.recursiveCount--
Context.exit()
}
return unwrapReturnValue(ret)
}
@Throws(ContinuationPending::class)
override suspend fun evalSuspend(reader: Reader, scope: Scriptable): Any? {
val cx = Context.enter() as RhinoContext
var ret: Any?
withContext(VMBridgeReflect.contextLocal.asContextElement()) {
cx.allowScriptRun = true
cx.recursiveCount++
try {
cx.checkRecursive()
var filename = this@RhinoScriptEngine["javax.script.filename"] as? String
filename = filename ?: "<Unknown source>"
val script = cx.compileReader(reader, filename, 1, null)
try {
ret = cx.executeScriptWithContinuations(script, scope)
} catch (e: ContinuationPending) {
var pending = e
while (true) {
try {
@Suppress("UNCHECKED_CAST")
val suspendFunction = pending.applicationState as suspend () -> Any?
val functionResult = suspendFunction()
val continuation = pending.continuation
ret = cx.resumeContinuation(continuation, scope, functionResult)
break
} catch (e: ContinuationPending) {
pending = e
}
}
}
} catch (re: RhinoException) {
val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
val msg: String = if (re is JavaScriptException) {
re.value.toString()
} else {
re.toString()
}
val se = ScriptException(msg, re.sourceName(), line)
se.initCause(re)
throw se
} catch (var14: IOException) {
throw ScriptException(var14)
} finally {
cx.allowScriptRun = false
cx.recursiveCount--
Context.exit()
}
}
return unwrapReturnValue(ret)
}
override fun createBindings(): Bindings {
return SimpleBindings()
}
@Throws(ScriptException::class, NoSuchMethodException::class)
override fun invokeFunction(name: String, vararg args: Any): Any? {
return this.invoke(null, name, *args)
}
@Throws(ScriptException::class, NoSuchMethodException::class)
override fun invokeMethod(obj: Any?, name: String, vararg args: Any): Any? {
return if (obj == null) {
throw IllegalArgumentException("脚本对象不能为空")
} else {
this.invoke(obj, name, *args)
}
}
@Suppress("UNCHECKED_CAST")
@Throws(ScriptException::class, NoSuchMethodException::class)
private operator fun invoke(thiz: Any?, name: String?, vararg args: Any?): Any? {
var thiz1 = thiz
val cx = Context.enter()
val var11: Any?
try {
if (name == null) {
throw NullPointerException("方法名为空")
}
if (thiz1 != null && thiz1 !is Scriptable) {
thiz1 = Context.toObject(thiz1, topLevel)
}
val engineScope = getRuntimeScope(context)
val localScope = thiz1 ?: engineScope
val obj = ScriptableObject.getProperty(localScope, name) as? Function
?: throw NoSuchMethodException("no such method: $name")
var scope = obj.parentScope
if (scope == null) {
scope = engineScope
}
val result = obj.call(cx, scope, localScope, wrapArguments(args as? Array<Any?>))
var11 = unwrapReturnValue(result)
} catch (re: RhinoException) {
val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
val se = ScriptException(re.toString(), re.sourceName(), line)
se.initCause(re)
throw se
} finally {
Context.exit()
}
return var11
}
override fun <T> getInterface(clazz: Class<T>): T? {
return try {
implementor.getInterface(null, clazz)
} catch (_: ScriptException) {
null
}
}
override fun <T> getInterface(obj: Any?, paramClass: Class<T>): T? {
return if (obj == null) {
throw IllegalArgumentException("脚本对象不能为空")
} else {
try {
implementor.getInterface(obj, paramClass)
} catch (_: ScriptException) {
null
}
}
}
override fun getRuntimeScope(context: ScriptContext): Scriptable {
val newScope: Scriptable = ExternalScriptable(context, indexedProps)
val cx = Context.enter()
try {
newScope.prototype = RhinoTopLevel(cx, this)
} finally {
Context.exit()
}
//newScope.put("context", newScope, context)
return newScope
}
override fun getRuntimeScope(bindings: ScriptBindings): Scriptable {
val cx = Context.enter()
try {
bindings.prototype = cx.initStandardObjects()
} finally {
Context.exit()
}
return bindings
}
@Throws(ScriptException::class)
override fun compile(script: String): CompiledScript {
return this.compile(StringReader(script) as Reader)
}
@Throws(ScriptException::class)
override fun compile(script: Reader): CompiledScript {
val cx = Context.enter()
val ret: RhinoCompiledScript
try {
var fileName = this["javax.script.filename"] as? String
if (fileName == null) {
fileName = "<Unknown Source>"
}
val scr = cx.compileReader(script, fileName, 1, null)
ret = RhinoCompiledScript(this, scr)
} catch (var9: Exception) {
throw ScriptException(var9)
} finally {
Context.exit()
}
return ret
}
fun wrapArguments(args: Array<Any?>?): Array<Any?> {
return if (args == null) {
Context.emptyArgs
} else {
val res = arrayOfNulls<Any>(args.size)
for (i in res.indices) {
res[i] = Context.javaToJS(args[i], topLevel)
}
res
}
}
fun unwrapReturnValue(result: Any?): Any? {
var result1 = result
if (result1 is Wrapper) {
result1 = result1.unwrap()
}
if (result1 is ConsString) {
result1 = result1.toString()
}
return if (result1 is Undefined) null else result1
}
init {
ContextFactory.initGlobal(object : ContextFactory() {
override fun makeContext(): Context {
val cx = RhinoContext(this)
cx.languageVersion = Context.VERSION_ES6
cx.setInterpretedMode(true)
cx.setClassShutter(RhinoClassShutter)
cx.wrapFactory = RhinoWrapFactory
cx.instructionObserverThreshold = 10000
cx.maximumInterpreterStackDepth = 1000
return cx
}
override fun hasFeature(cx: Context, featureIndex: Int): Boolean {
@Suppress("UNUSED_EXPRESSION")
return when (featureIndex) {
Context.FEATURE_ENABLE_JAVA_MAP_ACCESS -> true
else -> super.hasFeature(cx, featureIndex)
}
}
override fun observeInstructionCount(cx: Context, instructionCount: Int) {
if (cx is RhinoContext) {
cx.ensureActive()
}
}
override fun doTopCall(
callable: Callable,
cx: Context,
scope: Scriptable,
thisObj: Scriptable?,
args: Array<Any>
): Any? {
var accContext: AccessControlContext? = null
val global = ScriptableObject.getTopLevelScope(scope)
val globalProto = global.prototype
if (globalProto is RhinoTopLevel) {
accContext = globalProto.accessContext
}
return if (accContext != null) AccessController.doPrivileged(
PrivilegedAction {
superDoTopCall(callable, cx, scope, thisObj, args)
}, accContext
) else superDoTopCall(
callable,
cx,
scope,
thisObj,
args
)
}
private fun superDoTopCall(
callable: Callable,
cx: Context,
scope: Scriptable,
thisObj: Scriptable?,
args: Array<Any>
): Any? {
try {
if (cx is RhinoContext) {
if (!cx.allowScriptRun) {
error("Not allow run script in unauthorized way.")
}
cx.ensureActive()
}
return super.doTopCall(callable, cx, scope, thisObj, args)
} catch (e: RhinoInterruptError) {
throw e.cause
}
}
})
if (System.getSecurityManager() != null) {
try {
AccessController.checkPermission(AllPermission())
} catch (_: AccessControlException) {
accessContext = AccessController.getContext()
}
}
val cx = Context.enter()
try {
topLevel = RhinoTopLevel(cx, this)
} finally {
Context.exit()
}
indexedProps = HashMap()
implementor = object : InterfaceImplementor(this) {
override fun isImplemented(obj: Any?, clazz: Class<*>): Boolean {
var obj1 = obj
return try {
if (obj1 != null && obj1 !is Scriptable) {
obj1 = Context.toObject(obj1, topLevel)
}
val engineScope = getRuntimeScope(context)
val localScope = obj1 ?: engineScope
val methods = clazz.methods
val methodsSize = methods.size
for (index in 0 until methodsSize) {
val method = methods[index]
if (method.declaringClass != Any::class.java) {
if (ScriptableObject.getProperty(
localScope,
method.name
) !is Function
) {
return false
}
}
}
true
} finally {
Context.exit()
}
}
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)
}
}
}
}
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2005, 2010, 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 com.script.rhino
import com.script.Bindings
import com.script.ScriptContext
import com.script.SimpleScriptContext
import org.mozilla.javascript.Context
import org.mozilla.javascript.Function
import org.mozilla.javascript.ImporterTopLevel
import org.mozilla.javascript.Scriptable
import org.mozilla.javascript.Synchronizer
import org.mozilla.javascript.Wrapper
import java.security.AccessControlContext
/**
* This class serves as top level scope for Rhino. This class adds
* 3 top level functions (bindings, scope, sync) and two constructors
* (JSAdapter, JavaAdapter).
*
* @author A. Sundararajan
* @since 1.6
*/
@Suppress("UNUSED_PARAMETER", "unused")
class RhinoTopLevel(cx: Context, val scriptEngine: RhinoScriptEngine) :
ImporterTopLevel(cx, System.getSecurityManager() != null) {
init {
// LazilyLoadedCtor(this, "JSAdapter", "com.script.rhino.JSAdapter", false)
// JavaAdapter.init(cx, this, false)
// val names = arrayOf("bindings", "scope", "sync")
// defineFunctionProperties(names, RhinoTopLevel::class.java, 2)
}
val accessContext: AccessControlContext?
get() = scriptEngine.accessContext
companion object {
@JvmStatic
fun bindings(
cx: Context,
thisObj: Scriptable?,
args: Array<Any?>,
funObj: Function?
): Any {
if (args.size == 1) {
var arg = args[0]
if (arg is Wrapper) {
arg = arg.unwrap()
}
if (arg is ExternalScriptable) {
val ctx = arg.context
val bind = ctx.getBindings(100)
return Context.javaToJS(bind, getTopLevelScope(thisObj))
}
}
return Context.getUndefinedValue()
}
@JvmStatic
fun scope(cx: Context, thisObj: Scriptable?, args: Array<Any?>, funObj: Function?): Any {
if (args.size == 1) {
var arg = args[0]
if (arg is Wrapper) {
arg = arg.unwrap()
}
if (arg is Bindings) {
val ctx: ScriptContext = SimpleScriptContext()
ctx.setBindings(arg as Bindings?, 100)
val res: Scriptable = ExternalScriptable(ctx)
res.prototype = getObjectPrototype(thisObj)
res.parentScope = getTopLevelScope(thisObj)
return res
}
}
return Context.getUndefinedValue()
}
@JvmStatic
fun sync(cx: Context, thisObj: Scriptable?, args: Array<Any?>, funObj: Function?): Any {
return if (args.size == 1 && args[0] is Function) {
Synchronizer(args[0] as Function?)
} else {
throw Context.reportRuntimeError("wrong argument(s) for sync")
}
}
}
}
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2005, 2006, 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 com.script.rhino
import org.mozilla.javascript.Context
import org.mozilla.javascript.NativeJavaPackage
import org.mozilla.javascript.ScriptRuntime
import org.mozilla.javascript.Scriptable
import org.mozilla.javascript.WrapFactory
/**
* This wrap factory is used for security reasons. JSR 223 script
* engine interface and JavaScript engine classes are run as bootstrap
* classes. For example, java.lang.Class.forName method (when called without
* class loader) uses caller's class loader. This may be exploited by script
* authors to access classes otherwise not accessible. For example,
* classes in sun.* namespace are normally not accessible to untrusted
* code and hence should not be accessible to JavaScript run from
* untrusted code.
*
* @author A. Sundararajan
* @since 1.6
*/
object RhinoWrapFactory : WrapFactory() {
private val factories = hashMapOf<Class<*>, JavaObjectWrapFactory>()
override fun wrapAsJavaObject(
cx: Context,
scope: Scriptable?,
javaObject: Any,
staticType: Class<*>?
): Scriptable? {
if (!RhinoClassShutter.visibleToScripts(javaObject)) {
return null
}
return wrapOrNull(scope, javaObject, staticType)
?: super.wrapAsJavaObject(cx, scope, javaObject, staticType)
}
override fun wrapJavaClass(
cx: Context,
scope: Scriptable,
javaClass: Class<*>
): Scriptable {
if (!RhinoClassShutter.visibleToScripts(javaClass)) {
@Suppress("DEPRECATION")
val pkg = NativeJavaPackage(javaClass.name, null)
ScriptRuntime.setObjectProtoAndParent(pkg, scope)
return pkg
}
return RhinoClassShutter.wrapJavaClass(scope, javaClass)
}
private fun wrapOrNull(
scope: Scriptable?,
javaObject: Any,
staticType: Class<*>?
): Scriptable? {
return factories[javaObject.javaClass]?.wrap(scope, javaObject, staticType)
}
fun register(clazz: Class<*>, factory: JavaObjectWrapFactory) {
if (!factories.contains(clazz)) {
factories.put(clazz, factory)
}
}
}
@@ -0,0 +1,20 @@
package com.script.rhino
import org.mozilla.javascript.VMBridge
object VMBridgeReflect {
val instance: VMBridge by lazy {
VMBridge::class.java.getDeclaredField("instance").apply {
isAccessible = true
}.get(null) as VMBridge
}
val contextLocal: ThreadLocal<Any> by lazy {
@Suppress("UNCHECKED_CAST")
instance::class.java.getDeclaredField("contextLocal").apply {
isAccessible = true
}.get(null) as ThreadLocal<Any>
}
}