kunfei 3 سال پیش
والد
کامیت
d086c2efcd

+ 1 - 0
app/src/main/java/io/legado/app/constant/AppConst.kt

@@ -5,6 +5,7 @@ import android.content.pm.PackageManager
 import android.provider.Settings
 import android.provider.Settings
 import androidx.annotation.Keep
 import androidx.annotation.Keep
 import com.script.rhino.RhinoScriptEngine
 import com.script.rhino.RhinoScriptEngine
+
 import io.legado.app.BuildConfig
 import io.legado.app.BuildConfig
 import io.legado.app.utils.channel
 import io.legado.app.utils.channel
 import splitties.init.appCtx
 import splitties.init.appCtx

+ 1 - 0
book/build.gradle

@@ -1,5 +1,6 @@
 plugins {
 plugins {
     id 'com.android.library'
     id 'com.android.library'
+    id 'org.jetbrains.kotlin.android'
 }
 }
 
 
 android {
 android {

+ 3 - 2
rhino/build.gradle

@@ -1,5 +1,6 @@
 plugins {
 plugins {
     id 'com.android.library'
     id 'com.android.library'
+    id 'org.jetbrains.kotlin.android'
 }
 }
 
 
 android {
 android {
@@ -22,8 +23,8 @@ android {
 
 
     }
     }
     compileOptions {
     compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
+        sourceCompatibility JavaVersion.VERSION_11
+        targetCompatibility JavaVersion.VERSION_11
     }
     }
     lint {
     lint {
         checkDependencies true
         checkDependencies true

+ 169 - 360
rhino/src/main/java/com/script/rhino/ExternalScriptable.kt

@@ -22,24 +22,11 @@
  * or visit www.oracle.com if you need additional information or have any
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  * questions.
  */
  */
+package com.script.rhino
 
 
-package com.script.rhino;
-
-import com.script.Bindings;
-import com.script.ScriptContext;
-
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.Function;
-import org.mozilla.javascript.NativeJavaClass;
-import org.mozilla.javascript.ScriptRuntime;
-import org.mozilla.javascript.Scriptable;
-import org.mozilla.javascript.ScriptableObject;
-import org.mozilla.javascript.Wrapper;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
+import com.script.ScriptContext
+import org.mozilla.javascript.*
+import org.mozilla.javascript.Function
 
 
 /**
 /**
  * ExternalScriptable is an implementation of Scriptable
  * ExternalScriptable is an implementation of Scriptable
@@ -49,430 +36,252 @@ import java.util.Map;
  * @author A. Sundararajan
  * @author A. Sundararajan
  * @since 1.6
  * @since 1.6
  */
  */
-
-final class ExternalScriptable implements Scriptable {
-    /* Underlying ScriptContext that we use to store
-     * named variables of this scope.
-     */
-    private ScriptContext context;
-
-    /* JavaScript allows variables to be named as numbers (indexed
-     * properties). This way arrays, objects (scopes) are treated uniformly.
-     * Note that JSR 223 API supports only String named variables and
-     * so we can't store these in Bindings. Also, JavaScript allows name
-     * of the property name to be even empty String! Again, JSR 223 API
-     * does not support empty name. So, we use the following fallback map
-     * to store such variables of this scope. This map is not exposed to
-     * JSR 223 API. We can just script objects "as is" and need not convert.
-     */
-    private Map<Object, Object> indexedProps;
-
-    // my prototype
-    private Scriptable prototype;
-    // my parent scope, if any
-    private Scriptable parent;
-
-    ExternalScriptable(ScriptContext context) {
-        this(context, new HashMap<Object, Object>());
-    }
-
-    ExternalScriptable(ScriptContext context, Map<Object, Object> indexedProps) {
+internal class ExternalScriptable @JvmOverloads constructor(
+    context: ScriptContext?,
+    indexedProps: MutableMap<Any, Any> = HashMap()
+) : Scriptable {
+    val context: ScriptContext
+    private val indexedProps: MutableMap<Any, Any>
+    private var prototype: Scriptable? = null
+    private var parent: Scriptable? = null
+
+    init {
         if (context == null) {
         if (context == null) {
-            throw new NullPointerException("context is null");
+            throw NullPointerException("context is null")
+        } else {
+            this.context = context
+            this.indexedProps = indexedProps
         }
         }
-        this.context = context;
-        this.indexedProps = indexedProps;
-    }
-
-    ScriptContext getContext() {
-        return context;
     }
     }
 
 
-    private boolean isEmpty(String name) {
-        return name.equals("");
+    private fun isEmpty(name: String): Boolean {
+        return name == ""
     }
     }
 
 
-    /**
-     * Return the name of the class.
-     */
-    public String getClassName() {
-        return "Global";
+    override fun getClassName(): String {
+        return "Global"
     }
     }
 
 
-    /**
-     * Returns the value of the named property or NOT_FOUND.
-     *
-     * If the property was created using defineProperty, the
-     * appropriate getter method is called.
-     *
-     * @param name the name of the property
-     * @param start the object in which the lookup began
-     * @return the value of the property (may be null), or NOT_FOUND
-     */
-    public synchronized Object get(String name, Scriptable start) {
-        if (isEmpty(name)) {
-            if (indexedProps.containsKey(name)) {
-                return indexedProps.get(name);
-            } else {
-                return NOT_FOUND;
-            }
+    @Synchronized
+    override fun get(name: String, start: Scriptable): Any {
+        return if (this.isEmpty(name)) {
+            indexedProps.getOrElse(name) { Scriptable.NOT_FOUND }
         } else {
         } else {
-            synchronized (context) {
-                int scope = context.getAttributesScope(name);
-                if (scope != -1) {
-                    Object value = context.getAttribute(name, scope);
-                    return Context.javaToJS(value, this);
+            synchronized(context) {
+                val scope = context.getAttributesScope(name)
+                return if (scope != -1) {
+                    val value = context.getAttribute(name, scope)
+                    Context.javaToJS(value, this)
                 } else {
                 } else {
-                    return NOT_FOUND;
+                    Scriptable.NOT_FOUND
                 }
                 }
             }
             }
         }
         }
     }
     }
 
 
-    /**
-     * Returns the value of the indexed property or NOT_FOUND.
-     *
-     * @param index the numeric index for the property
-     * @param start the object in which the lookup began
-     * @return the value of the property (may be null), or NOT_FOUND
-     */
-    public synchronized Object get(int index, Scriptable start) {
-        if (indexedProps.containsKey(index)) {
-            return indexedProps.get(index);
-        } else {
-            return NOT_FOUND;
-        }
+    @Synchronized
+    override fun get(index: Int, start: Scriptable): Any {
+        return indexedProps.getOrElse(index) { Scriptable.NOT_FOUND }
     }
     }
 
 
-    /**
-     * Returns true if the named property is defined.
-     *
-     * @param name the name of the property
-     * @param start the object in which the lookup began
-     * @return true if and only if the property was found in the object
-     */
-    public synchronized boolean has(String name, Scriptable start) {
-        if (isEmpty(name)) {
-            return indexedProps.containsKey(name);
+    @Synchronized
+    override fun has(name: String, start: Scriptable): Boolean {
+        return if (this.isEmpty(name)) {
+            indexedProps.containsKey(name)
         } else {
         } else {
-            synchronized (context) {
-                return context.getAttributesScope(name) != -1;
-            }
+            synchronized(context) { return context.getAttributesScope(name) != -1 }
         }
         }
     }
     }
 
 
-    /**
-     * Returns true if the property index is defined.
-     *
-     * @param index the numeric index for the property
-     * @param start the object in which the lookup began
-     * @return true if and only if the property was found in the object
-     */
-    public synchronized boolean has(int index, Scriptable start) {
-        return indexedProps.containsKey(index);
+    @Synchronized
+    override fun has(index: Int, start: Scriptable): Boolean {
+        return indexedProps.containsKey(index)
     }
     }
 
 
-    /**
-     * Sets the value of the named property, creating it if need be.
-     *
-     * @param name the name of the property
-     * @param start the object whose property is being set
-     * @param value value to set the property to
-     */
-    public void put(String name, Scriptable start, Object value) {
-        if (start == this) {
-            synchronized (this) {
-                if (isEmpty(name)) {
-                    indexedProps.put(name, value);
+    override fun put(name: String, start: Scriptable, value: Any) {
+        if (start === this) {
+            synchronized(this) {
+                if (this.isEmpty(name)) {
+                    indexedProps.put(name, value)
                 } else {
                 } else {
-                    synchronized (context) {
-                        int scope = context.getAttributesScope(name);
+                    synchronized(context) {
+                        var scope = context.getAttributesScope(name)
                         if (scope == -1) {
                         if (scope == -1) {
-                            scope = ScriptContext.ENGINE_SCOPE;
+                            scope = 100
                         }
                         }
-                        context.setAttribute(name, jsToJava(value), scope);
+                        context.setAttribute(name, jsToJava(value), scope)
                     }
                     }
                 }
                 }
             }
             }
         } else {
         } else {
-            start.put(name, start, value);
+            start.put(name, start, value)
         }
         }
     }
     }
 
 
-    /**
-     * Sets the value of the indexed property, creating it if need be.
-     *
-     * @param index the numeric index for the property
-     * @param start the object whose property is being set
-     * @param value value to set the property to
-     */
-    public void put(int index, Scriptable start, Object value) {
-        if (start == this) {
-            synchronized (this) {
-                indexedProps.put(index, value);
-            }
+    override fun put(index: Int, start: Scriptable, value: Any) {
+        if (start === this) {
+            synchronized(this) { indexedProps.put(index, value) }
         } else {
         } else {
-            start.put(index, start, value);
+            start.put(index, start, value)
         }
         }
     }
     }
 
 
-    /**
-     * Removes a named property from the object.
-     *
-     * If the property is not found, no action is taken.
-     *
-     * @param name the name of the property
-     */
-    public synchronized void delete(String name) {
-        if (isEmpty(name)) {
-            indexedProps.remove(name);
+    @Synchronized
+    override fun delete(name: String) {
+        if (this.isEmpty(name)) {
+            indexedProps.remove(name)
         } else {
         } else {
-            synchronized (context) {
-                int scope = context.getAttributesScope(name);
+            synchronized(context) {
+                val scope = context.getAttributesScope(name)
                 if (scope != -1) {
                 if (scope != -1) {
-                    context.removeAttribute(name, scope);
+                    context.removeAttribute(name, scope)
                 }
                 }
             }
             }
         }
         }
     }
     }
 
 
-    /**
-     * Removes the indexed property from the object.
-     *
-     * If the property is not found, no action is taken.
-     *
-     * @param index the numeric index for the property
-     */
-    public void delete(int index) {
-        indexedProps.remove(index);
+    override fun delete(index: Int) {
+        indexedProps.remove(index)
     }
     }
 
 
-    /**
-     * Get the prototype of the object.
-     * @return the prototype
-     */
-    public Scriptable getPrototype() {
-        return prototype;
+    override fun getPrototype(): Scriptable? {
+        return prototype
     }
     }
 
 
-    /**
-     * Set the prototype of the object.
-     * @param prototype the prototype to set
-     */
-    public void setPrototype(Scriptable prototype) {
-        this.prototype = prototype;
+    override fun setPrototype(prototype: Scriptable?) {
+        this.prototype = prototype
     }
     }
 
 
-    /**
-     * Get the parent scope of the object.
-     * @return the parent scope
-     */
-    public Scriptable getParentScope() {
-        return parent;
+    override fun getParentScope(): Scriptable? {
+        return parent
     }
     }
 
 
-    /**
-     * Set the parent scope of the object.
-     * @param parent the parent scope to set
-     */
-    public void setParentScope(Scriptable parent) {
-        this.parent = parent;
+    override fun setParentScope(parent: Scriptable?) {
+        this.parent = parent
     }
     }
 
 
-     /**
-     * Get an array of property ids.
-     *
-     * Not all property ids need be returned. Those properties
-     * whose ids are not returned are considered non-enumerable.
-     *
-     * @return an array of Objects. Each entry in the array is either
-     *         a java.lang.String or a java.lang.Number
-     */
-    public synchronized Object[] getIds() {
-        String[] keys = getAllKeys();
-        int size = keys.length + indexedProps.size();
-        Object[] res = new Object[size];
-        System.arraycopy(keys, 0, res, 0, keys.length);
-        int i = keys.length;
-        // now add all indexed properties
-        for (Object index : indexedProps.keySet()) {
-            res[i++] = index;
+    @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
         }
         }
-        return res;
+        @Suppress("UNCHECKED_CAST")
+        return res as Array<Any>
     }
     }
 
 
-    /**
-     * Get the default value of the object with a given hint.
-     * The hints are String.class for type String, Number.class for type
-     * Number, Scriptable.class for type Object, and Boolean.class for
-     * type Boolean. <p>
-     *
-     * A <code>hint</code> of null means "no hint".
-     *
-     * See ECMA 8.6.2.6.
-     *
-     * @param typeHint the type hint
-     * @return the default value
-     */
-    public Object getDefaultValue(Class typeHint) {
-        for (int i=0; i < 2; i++) {
-            boolean tryToString;
-            if (typeHint == ScriptRuntime.StringClass) {
-                tryToString = (i == 0);
-            } else {
-                tryToString = (i == 1);
-            }
-
-            String methodName;
-            Object[] args;
+    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) {
             if (tryToString) {
-                methodName = "toString";
-                args = ScriptRuntime.emptyArgs;
+                methodName = "toString"
+                args = ScriptRuntime.emptyArgs
             } else {
             } else {
-                methodName = "valueOf";
-                args = new Object[1];
-                String hint;
-                if (typeHint == null) {
-                    hint = "undefined";
+                methodName = "valueOf"
+                args = arrayOfNulls(1)
+                val hint: String = if (typeHint == null) {
+                    "undefined"
                 } else if (typeHint == ScriptRuntime.StringClass) {
                 } else if (typeHint == ScriptRuntime.StringClass) {
-                    hint = "string";
+                    "string"
                 } else if (typeHint == ScriptRuntime.ScriptableClass) {
                 } else if (typeHint == ScriptRuntime.ScriptableClass) {
-                    hint = "object";
+                    "object"
                 } else if (typeHint == ScriptRuntime.FunctionClass) {
                 } else if (typeHint == ScriptRuntime.FunctionClass) {
-                    hint = "function";
-                } else if (typeHint == ScriptRuntime.BooleanClass
-                           || typeHint == Boolean.TYPE)
-                {
-                    hint = "boolean";
-                } else if (typeHint == ScriptRuntime.NumberClass ||
-                         typeHint == ScriptRuntime.ByteClass ||
-                         typeHint == Byte.TYPE ||
-                         typeHint == ScriptRuntime.ShortClass ||
-                         typeHint == Short.TYPE ||
-                         typeHint == ScriptRuntime.IntegerClass ||
-                         typeHint == Integer.TYPE ||
-                         typeHint == ScriptRuntime.FloatClass ||
-                         typeHint == Float.TYPE ||
-                         typeHint == ScriptRuntime.DoubleClass ||
-                         typeHint == Double.TYPE)
-                {
-                    hint = "number";
+                    "function"
+                } else if (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 {
                 } else {
-                    throw Context.reportRuntimeError(
-                        "Invalid JavaScript value of type " +
-                                typeHint);
+                    "boolean"
                 }
                 }
-                args[0] = hint;
-            }
-            Object v = ScriptableObject.getProperty(this, methodName);
-            if (!(v instanceof Function))
-                continue;
-            Function fun = (Function) v;
-            Context cx = RhinoScriptEngine.enterContext();
-            try {
-                v = fun.call(cx, fun.getParentScope(), this, args);
-            } finally {
-                cx.exit();
+                args[0] = hint
             }
             }
-            if (v != null) {
-                if (!(v instanceof Scriptable)) {
-                    return v;
+            var v = ScriptableObject.getProperty(this, methodName)
+            if (v is Function) {
+                val `fun` = v
+                val cx = Context.enter()
+                v = try {
+                    `fun`.call(cx, `fun`.parentScope, this, args)
+                } finally {
+                    Context.exit()
                 }
                 }
-                if (typeHint == ScriptRuntime.ScriptableClass
-                    || typeHint == ScriptRuntime.FunctionClass)
-                {
-                    return v;
-                }
-                if (tryToString && v instanceof Wrapper) {
-                    // Let a wrapped java.lang.String pass for a primitive
-                    // string.
-                    Object u = ((Wrapper)v).unwrap();
-                    if (u instanceof String)
-                        return u;
+                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
+                        }
+                    }
                 }
                 }
             }
             }
         }
         }
-        // fall through to error
-        String arg = (typeHint == null) ? "undefined" : typeHint.getName();
-        throw Context.reportRuntimeError(
-                  "Cannot find default value for object " + arg);
+        val arg = if (typeHint == null) "undefined" else typeHint.name
+        throw Context.reportRuntimeError("找不到对象的默认值 $arg")
     }
     }
 
 
-    /**
-     * Implements the instanceof operator.
-     *
-     * @param instance The value that appeared on the LHS of the instanceof
-     *              operator
-     * @return true if "this" appears in value's prototype chain
-     *
-     */
-    public boolean hasInstance(Scriptable instance) {
-        // Default for JS objects (other than Function) is to do prototype
-        // chasing.
-        Scriptable proto = instance.getPrototype();
+    override fun hasInstance(instance: Scriptable): Boolean {
+        var proto = instance.prototype
         while (proto != null) {
         while (proto != null) {
-            if (proto.equals(this)) return true;
-            proto = proto.getPrototype();
+            if (proto == this) {
+                return true
+            }
+            proto = proto.prototype
         }
         }
-        return false;
+        return false
     }
     }
 
 
-    private String[] getAllKeys() {
-        ArrayList<String> list = new ArrayList<String>();
-        synchronized (context) {
-            for (int scope : context.getScopes()) {
-                Bindings bindings = context.getBindings(scope);
-                if (bindings != null) {
-                    list.ensureCapacity(bindings.size());
-                    for (String key : bindings.keySet()) {
-                        list.add(key);
+    private val allKeys: Array<String>
+        get() {
+            val list = ArrayList<String>()
+            synchronized(context) {
+                val var3: Iterator<*> = context.scopes.iterator()
+                while (var3.hasNext()) {
+                    val scope = var3.next() as Int
+                    val bindings = context.getBindings(scope)
+                    if (bindings != null) {
+                        list.ensureCapacity(bindings.size)
+                        val var6: Iterator<*> = bindings.keys.iterator()
+                        while (var6.hasNext()) {
+                            val key = var6.next() as String
+                            list.add(key)
+                        }
                     }
                     }
                 }
                 }
             }
             }
+            return list.toTypedArray()
         }
         }
-        String[] res = new String[list.size()];
-        list.toArray(res);
-        return res;
-    }
-
-   /**
-    * We convert script values to the nearest Java value.
-    * We unwrap wrapped Java objects so that access from
-    * Bindings.get() would return "workable" value for Java.
-    * But, at the same time, we need to make few special cases
-    * and hence the following function is used.
-    */
-    private Object jsToJava(Object jsObj) {
-        if (jsObj instanceof Wrapper) {
-            Wrapper njb = (Wrapper) jsObj;
-            /* importClass feature of ImporterTopLevel puts
-             * NativeJavaClass in global scope. If we unwrap
-             * it, importClass won't work.
-             */
-            if (njb instanceof NativeJavaClass) {
-                return njb;
-            }
 
 
-            /* script may use Java primitive wrapper type objects
-             * (such as java.lang.Integer, java.lang.Boolean etc)
-             * explicitly. If we unwrap, then these script objects
-             * will become script primitive types. For example,
-             *
-             *    var x = new java.lang.Double(3.0); print(typeof x);
-             *
-             * will print 'number'. We don't want that to happen.
-             */
-            Object obj = njb.unwrap();
-            if (obj instanceof Number || obj instanceof String ||
-                obj instanceof Boolean || obj instanceof Character) {
-                // special type wrapped -- we just leave it as is.
-                return njb;
+    private fun jsToJava(jsObj: Any): Any {
+        return if (jsObj is Wrapper) {
+            if (jsObj is NativeJavaClass) {
+                jsObj
             } else {
             } else {
-                // return unwrapped object for any other object.
-                return obj;
+                val obj = jsObj.unwrap()
+                if (obj !is Number && obj !is String && obj !is Boolean && obj !is Char) obj else jsObj
             }
             }
-        } else { // not-a-Java-wrapper
-            return jsObj;
+        } else {
+            jsObj
         }
         }
     }
     }
-}
+}

+ 53 - 75
rhino/src/main/java/com/script/rhino/InterfaceImplementor.kt

@@ -22,97 +22,75 @@
  * or visit www.oracle.com if you need additional information or have any
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  * questions.
  */
  */
+package com.script.rhino
 
 
-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
 
 
-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
  * java.lang.reflect.Proxy based interface implementor. This is meant
  * to be used to implement Invocable.getInterface.
  * to be used to implement Invocable.getInterface.
  *
  *
  * @author Mike Grogan
  * @author Mike Grogan
  * @since 1.6
  * @since 1.6
  */
  */
-public class InterfaceImplementor {
-
-    private Invocable engine;
-
-    /** Creates a new instance of Invocable */
-    public InterfaceImplementor(Invocable engine) {
-        this.engine = engine;
-    }
-
-    private final class InterfaceImplementorInvocationHandler
-            implements InvocationHandler {
-        private Object thiz;
-        private AccessControlContext accCtxt;
-
-        public InterfaceImplementorInvocationHandler(Object thiz,
-                                                     AccessControlContext accCtxt) {
-            this.thiz = thiz;
-            this.accCtxt = accCtxt;
-        }
-
-        public Object invoke(Object proxy , Method method, Object[] args)
-                throws java.lang.Throwable {
-            // give chance to convert input args
-            args = convertArguments(method, args);
-            Object result;
-            final Method m = method;
-            final Object[] a = args;
-            result = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
-                public Object run() throws Exception {
-                    if (thiz == null) {
-                        return engine.invokeFunction(m.getName(), a);
-                    } else {
-                        return engine.invokeMethod(thiz, m.getName(), a);
-                    }
-                }
-            }, accCtxt);
-            // give chance to convert the method result
-            return convertResult(method, result);
+open class InterfaceImplementor(private val engine: Invocable) {
+    @Throws(ScriptException::class)
+    fun <T> getInterface(thiz: Any?, iface: Class<T>?): T? {
+        return if (iface != null && iface.isInterface) {
+            if (!isImplemented(thiz, iface)) {
+                null
+            } else {
+                val accCtxt = AccessController.getContext()
+                iface.cast(
+                    Proxy.newProxyInstance(
+                        iface.classLoader,
+                        arrayOf<Class<*>>(iface),
+                        InterfaceImplementorInvocationHandler(thiz, accCtxt)
+                    )
+                )
+            }
+        } else {
+            throw IllegalArgumentException("interface Class expected")
         }
         }
     }
     }
 
 
-    public <T> T getInterface(Object thiz, Class<T> iface)
-            throws ScriptException {
-        if (iface == null || !iface.isInterface()) {
-            throw new IllegalArgumentException("interface Class expected");
-        }
-        if (! isImplemented(thiz, iface)) {
-            return null;
-        }
-        AccessControlContext accCtxt = AccessController.getContext();
-        return iface.cast(Proxy.newProxyInstance(iface.getClassLoader(),
-                new Class[]{iface},
-                new InterfaceImplementorInvocationHandler(thiz, accCtxt)));
+    protected open fun isImplemented(thiz: Any?, iface: Class<*>): Boolean {
+        return true
     }
     }
 
 
-    protected boolean isImplemented(Object thiz, Class<?> iface) {
-        return true;
+    @Throws(ScriptException::class)
+    protected open fun convertResult(method: Method?, res: Any): Any {
+        return res
     }
     }
 
 
-    // called to convert method result after invoke
-    protected Object convertResult(Method method, Object res)
-            throws ScriptException {
-        // default is identity conversion
-        return res;
+    @Throws(ScriptException::class)
+    protected fun convertArguments(method: Method?, args: Array<Any>): Array<Any> {
+        return args
     }
     }
 
 
-    // called to convert method arguments before invoke
-    protected Object[] convertArguments(Method method, Object[] args)
-            throws ScriptException {
-        // default is identity conversion
-        return args;
+    private inner class InterfaceImplementorInvocationHandler(
+        private val thiz: Any?,
+        private val accCtxt: 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 (thiz == null) engine.invokeFunction(
+                    method.name,
+                    *finalArgs
+                ) else engine.invokeMethod(
+                    thiz, method.name, *finalArgs
+                )
+            } as PrivilegedExceptionAction<Any>, accCtxt)
+            return convertResult(method, result)
+        }
     }
     }
 }
 }

+ 162 - 199
rhino/src/main/java/com/script/rhino/JSAdapter.kt

@@ -22,16 +22,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  * questions.
  */
  */
+package com.script.rhino
 
 
-package com.script.rhino;
-
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.Function;
-import org.mozilla.javascript.NativeArray;
-import org.mozilla.javascript.NativeJavaArray;
-import org.mozilla.javascript.RhinoException;
-import org.mozilla.javascript.Scriptable;
-import org.mozilla.javascript.ScriptableObject;
+import org.mozilla.javascript.*
+import org.mozilla.javascript.Function
 
 
 /**
 /**
  * JSAdapter is java.lang.reflect.Proxy equivalent for JavaScript. JSAdapter
  * JSAdapter is java.lang.reflect.Proxy equivalent for JavaScript. JSAdapter
@@ -40,21 +34,21 @@ import org.mozilla.javascript.ScriptableObject;
  *
  *
  * Example:
  * Example:
  *
  *
- *    var y = {
- *                __get__    : function (name) { ... }
- *                __has__    : function (name) { ... }
- *                __put__    : function (name, value) {...}
- *                __delete__ : function (name) { ... }
- *                __getIds__ : function () { ... }
- *            };
+ * var y = {
+ * __get__    : function (name) { ... }
+ * __has__    : function (name) { ... }
+ * __put__    : function (name, value) {...}
+ * __delete__ : function (name) { ... }
+ * __getIds__ : function () { ... }
+ * };
  *
  *
- *    var x = new JSAdapter(y);
+ * 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__
+ * 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
  * If a special JavaScript method is not found in the adaptee, then JSAdapter
  * forwards the property access to the adaptee itself.
  * forwards the property access to the adaptee itself.
@@ -74,270 +68,239 @@ import org.mozilla.javascript.ScriptableObject;
  * @author A. Sundararajan
  * @author A. Sundararajan
  * @since 1.6
  * @since 1.6
  */
  */
-public final class JSAdapter implements Scriptable, Function {
-    private JSAdapter(Scriptable obj) {
-        setAdaptee(obj);
-    }
-
-    // initializer to setup JSAdapter prototype in the given scope
-    public static void init(Context cx, Scriptable scope, boolean sealed)
-    throws RhinoException {
-        JSAdapter obj = new JSAdapter(cx.newObject(scope));
-        obj.setParentScope(scope);
-        obj.setPrototype(getFunctionPrototype(scope));
-        obj.isPrototype = true;
-        ScriptableObject.defineProperty(scope, "JSAdapter",  obj,
-                ScriptableObject.DONTENUM);
-    }
+class JSAdapter private constructor(val adaptee: Scriptable) : Scriptable, Function {
+    private var prototype: Scriptable? = null
+    private var parent: Scriptable? = null
+    private var isPrototype = false
 
 
-    public String getClassName() {
-        return "JSAdapter";
+    override fun getClassName(): String {
+        return "JSAdapter"
     }
     }
 
 
-    public Object get(String name, Scriptable start) {
-        Function func = getAdapteeFunction(GET_PROP);
-        if (func != null) {
-            return call(func, new Object[] { name });
+    override fun get(name: String, start: Scriptable): Any {
+        val func = getAdapteeFunction(GET_PROP)
+        return if (func != null) {
+            this.call(func, arrayOf(name))
         } else {
         } else {
-            start = getAdaptee();
-            return start.get(name, start);
+            adaptee[name, adaptee]
         }
         }
     }
     }
 
 
-    public Object get(int index, Scriptable start) {
-        Function func = getAdapteeFunction(GET_PROP);
-        if (func != null) {
-            return call(func, new Object[] {index});
+    override fun get(index: Int, start: Scriptable): Any {
+        val func = getAdapteeFunction(GET_PROP)
+        return if (func != null) {
+            this.call(func, arrayOf(index))
         } else {
         } else {
-            start = getAdaptee();
-            return start.get(index, start);
+            adaptee[index, adaptee]
         }
         }
     }
     }
 
 
-    public boolean has(String name, Scriptable start) {
-        Function func = getAdapteeFunction(HAS_PROP);
-        if (func != null) {
-            Object res = call(func, new Object[] { name });
-            return Context.toBoolean(res);
+    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 {
         } else {
-            start = getAdaptee();
-            return start.has(name, start);
+            adaptee.has(name, adaptee)
         }
         }
     }
     }
 
 
-    public boolean has(int index, Scriptable start) {
-        Function func = getAdapteeFunction(HAS_PROP);
-        if (func != null) {
-            Object res = call(func, new Object[] {index});
-            return Context.toBoolean(res);
+    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 {
         } else {
-            start = getAdaptee();
-            return start.has(index, start);
+            adaptee.has(index, adaptee)
         }
         }
     }
     }
 
 
-    public void put(String name, Scriptable start, Object value) {
-        if (start == this) {
-            Function func = getAdapteeFunction(PUT_PROP);
+    override fun put(name: String, start: Scriptable, value: Any) {
+        if (start === this) {
+            val func = getAdapteeFunction(PUT_PROP)
             if (func != null) {
             if (func != null) {
-                call(func, new Object[] { name, value });
+                this.call(func, arrayOf(name, value))
             } else {
             } else {
-                start = getAdaptee();
-                start.put(name, start, value);
+                adaptee.put(name, adaptee, value)
             }
             }
         } else {
         } else {
-            start.put(name, start, value);
+            start.put(name, start, value)
         }
         }
     }
     }
 
 
-    public void put(int index, Scriptable start, Object value) {
-        if (start == this) {
-            Function func = getAdapteeFunction(PUT_PROP);
-            if( func != null) {
-                call(func, new Object[] {index, 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 {
             } else {
-                start = getAdaptee();
-                start.put(index, start, value);
+                adaptee.put(index, adaptee, value)
             }
             }
         } else {
         } else {
-            start.put(index, start, value);
+            start.put(index, start, value)
         }
         }
     }
     }
 
 
-    public void delete(String name) {
-        Function func = getAdapteeFunction(DEL_PROP);
+    override fun delete(name: String) {
+        val func = getAdapteeFunction(DEL_PROP)
         if (func != null) {
         if (func != null) {
-            call(func, new Object[] { name });
+            this.call(func, arrayOf(name))
         } else {
         } else {
-            getAdaptee().delete(name);
+            adaptee.delete(name)
         }
         }
     }
     }
 
 
-    public void delete(int index) {
-        Function func = getAdapteeFunction(DEL_PROP);
+    override fun delete(index: Int) {
+        val func = getAdapteeFunction(DEL_PROP)
         if (func != null) {
         if (func != null) {
-            call(func, new Object[] {index});
+            this.call(func, arrayOf(index))
         } else {
         } else {
-            getAdaptee().delete(index);
+            adaptee.delete(index)
         }
         }
     }
     }
 
 
-    public Scriptable getPrototype() {
-        return prototype;
+    override fun getPrototype(): Scriptable? {
+        return prototype
     }
     }
 
 
-    public void setPrototype(Scriptable prototype) {
-        this.prototype = prototype;
+    override fun setPrototype(prototype: Scriptable?) {
+        this.prototype = prototype
     }
     }
 
 
-    public Scriptable getParentScope() {
-        return parent;
+    override fun getParentScope(): Scriptable? {
+        return parent
     }
     }
 
 
-    public void setParentScope(Scriptable parent) {
-        this.parent = parent;
+    override fun setParentScope(parent: Scriptable?) {
+        this.parent = parent
     }
     }
 
 
-    public Object[] getIds() {
-        Function func = getAdapteeFunction(GET_PROPIDS);
-        if (func != null) {
-            Object val = call(func, new Object[0]);
-            // in most cases, adaptee would return native JS array
-            if (val instanceof NativeArray) {
-                NativeArray array = (NativeArray) val;
-                Object[] res = new Object[(int)array.getLength()];
-                for (int index = 0; index < res.length; index++) {
-                    res[index] = mapToId(array.get(index, array));
+    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
                 }
                 }
-                return res;
-            } else if (val instanceof NativeJavaArray) {
-                // may be attempt wrapped Java array
-                Object tmp = ((NativeJavaArray)val).unwrap();
-                Object[] res;
-                if (tmp.getClass() == Object[].class) {
-                    Object[]  array = (Object[]) tmp;
-                    res = new Object[array.length];
-                    for (int index = 0; index < array.length; index++) {
-                        res[index] = mapToId(array[index]);
+                !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
                     }
                     }
-                } else {
-                    // just return an empty array
-                    res = Context.emptyArgs;
+                    res
                 }
                 }
-                return res;
-            } else {
-                // some other return type, just return empty array
-                return Context.emptyArgs;
             }
             }
-        } else {
-            return getAdaptee().getIds();
         }
         }
     }
     }
 
 
-    public boolean hasInstance(Scriptable scriptable) {
-        if (scriptable instanceof JSAdapter) {
-            return true;
+    override fun hasInstance(scriptable: Scriptable): Boolean {
+        return if (scriptable is JSAdapter) {
+            true
         } else {
         } else {
-            Scriptable proto = scriptable.getPrototype();
+            var proto = scriptable.prototype
             while (proto != null) {
             while (proto != null) {
-                if (proto.equals(this)) return true;
-                proto = proto.getPrototype();
+                if (proto == this) {
+                    return true
+                }
+                proto = proto.prototype
             }
             }
-            return false;
+            false
         }
         }
     }
     }
 
 
-    public Object getDefaultValue(Class hint) {
-        return getAdaptee().getDefaultValue(hint);
+    override fun getDefaultValue(hint: Class<*>?): Any {
+        return adaptee.getDefaultValue(hint)
     }
     }
 
 
-    public Object call(Context cx, Scriptable scope, Scriptable thisObj,
-            Object[] args)
-            throws RhinoException {
-        if (isPrototype) {
-            return construct(cx, scope, args);
+    @Throws(RhinoException::class)
+    override fun call(cx: Context, scope: Scriptable, thisObj: Scriptable, args: Array<Any>): Any {
+        return if (isPrototype) {
+            construct(cx, scope, args)
         } else {
         } else {
-            Scriptable tmp = getAdaptee();
-            if (tmp instanceof Function) {
-                return ((Function)tmp).call(cx, scope, tmp, args);
+            val tmp = adaptee
+            if (tmp is Function) {
+                tmp.call(cx, scope, tmp, args)
             } else {
             } else {
-                throw Context.reportRuntimeError("TypeError: not a function");
+                throw Context.reportRuntimeError("TypeError: not a function")
             }
             }
         }
         }
     }
     }
 
 
-    public Scriptable construct(Context cx, Scriptable scope, Object[] args)
-    throws RhinoException {
-        if (isPrototype) {
-            Scriptable topLevel = ScriptableObject.getTopLevelScope(scope);
-            JSAdapter newObj;
-            if (args.length > 0) {
-                newObj = new JSAdapter(Context.toObject(args[0], topLevel));
+    @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.size > 0) {
+                JSAdapter(Context.toObject(args[0], tmp))
             } else {
             } else {
-                throw Context.reportRuntimeError("JSAdapter requires adaptee");
+                throw Context.reportRuntimeError("JSAdapter requires adaptee")
             }
             }
-            return newObj;
         } else {
         } else {
-            Scriptable tmp = getAdaptee();
-            if (tmp instanceof Function) {
-                return ((Function)tmp).construct(cx, scope, args);
+            tmp = adaptee
+            if (tmp is Function) {
+                tmp.construct(cx, scope, args)
             } else {
             } else {
-                throw Context.reportRuntimeError("TypeError: not a constructor");
+                throw Context.reportRuntimeError("TypeError: not a constructor")
             }
             }
         }
         }
     }
     }
 
 
-    public Scriptable getAdaptee() {
-        return adaptee;
+    private fun mapToId(tmp: Any?): Any {
+        return if (tmp is Double) tmp.toInt() else Context.toString(tmp)
     }
     }
 
 
-    public void setAdaptee(Scriptable adaptee) {
-        if (adaptee == null) {
-            throw new NullPointerException("adaptee can not be null");
-        }
-        this.adaptee = adaptee;
+    private fun getAdapteeFunction(name: String): Function? {
+        val o = ScriptableObject.getProperty(adaptee, name)
+        return if (o is Function) o else null
     }
     }
 
 
-    //-- internals only below this point
-
-    // map a property id. Property id can only be an Integer or String
-    private Object mapToId(Object tmp) {
-        if (tmp instanceof Double) {
-            return ((Double) tmp).intValue();
-        } else {
-            return Context.toString(tmp);
+    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 (var7: RhinoException) {
+            throw Context.reportRuntimeError(var7.message)
         }
         }
     }
     }
 
 
-    private static Scriptable getFunctionPrototype(Scriptable scope) {
-        return ScriptableObject.getFunctionPrototype(scope);
-    }
+    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__"
 
 
-    private Function getAdapteeFunction(String name) {
-        Object o = ScriptableObject.getProperty(getAdaptee(), name);
-        return (o instanceof Function)? (Function)o : null;
-    }
+        @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 Object call(Function func, Object[] args) {
-        Context cx = Context.getCurrentContext();
-        Scriptable thisObj = getAdaptee();
-        Scriptable scope = func.getParentScope();
-        try {
-            return func.call(cx, scope, thisObj, args);
-        } catch (RhinoException re) {
-            throw Context.reportRuntimeError(re.getMessage());
+        private fun getFunctionPrototype(scope: Scriptable): Scriptable {
+            return ScriptableObject.getFunctionPrototype(scope)
         }
         }
     }
     }
-
-    private Scriptable prototype;
-    private Scriptable parent;
-    private Scriptable adaptee;
-    private boolean isPrototype;
-
-    // names of adaptee JavaScript functions
-    private static final String GET_PROP = "__get__";
-    private static final String HAS_PROP = "__has__";
-    private static final String PUT_PROP = "__put__";
-    private static final String DEL_PROP = "__delete__";
-    private static final String GET_PROPIDS = "__getIds__";
-}
+}

+ 51 - 62
rhino/src/main/java/com/script/rhino/JavaAdapter.kt

@@ -22,31 +22,26 @@
  * or visit www.oracle.com if you need additional information or have any
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  * questions.
  */
  */
+package com.script.rhino
 
 
-package com.script.rhino;
-
-import com.script.Invocable;
-
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.Function;
-import org.mozilla.javascript.RhinoException;
-import org.mozilla.javascript.Scriptable;
-import org.mozilla.javascript.ScriptableObject;
-import org.mozilla.javascript.Wrapper;
-
-
+import com.script.Invocable
+import org.mozilla.javascript.*
+import org.mozilla.javascript.Function
 
 
 /**
 /**
  * This class implements Rhino-like JavaAdapter to help implement a Java
  * This class implements Rhino-like JavaAdapter to help implement a Java
  * interface in JavaScript. We support this using Invocable.getInterface.
  * interface in JavaScript. We support this using Invocable.getInterface.
  * Using this JavaAdapter, script author could write:
  * Using this JavaAdapter, script author could write:
  *
  *
- *    var r = new java.lang.Runnable() {
- *                run: function() { script... }
- *            };
  *
  *
- *    r.run();
- *    new java.lang.Thread(r).start();
+ * 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
  * Note that Rhino's JavaAdapter support allows extending a Java class and/or
  * implementing one or more interfaces. This JavaAdapter implementation does
  * implementing one or more interfaces. This JavaAdapter implementation does
@@ -55,60 +50,54 @@ import org.mozilla.javascript.Wrapper;
  * @author A. Sundararajan
  * @author A. Sundararajan
  * @since 1.6
  * @since 1.6
  */
  */
-final class JavaAdapter extends ScriptableObject implements Function {
-    private JavaAdapter(Invocable engine) {
-        this.engine = engine;
+internal class JavaAdapter private constructor(private val engine: Invocable) : ScriptableObject(),
+    Function {
+    override fun getClassName(): String {
+        return "JavaAdapter"
     }
     }
 
 
-    static void init(Context cx, Scriptable scope, boolean sealed)
-    throws RhinoException {
-        RhinoTopLevel topLevel = (RhinoTopLevel) scope;
-        Invocable engine = topLevel.getScriptEngine();
-        JavaAdapter obj = new JavaAdapter(engine);
-        obj.setParentScope(scope);
-        obj.setPrototype(getFunctionPrototype(scope));
-        /*
-         * Note that we can't use defineProperty. A property of this
-         * name is already defined in Context.initStandardObjects. We
-         * simply overwrite the property value!
-         */
-        ScriptableObject.putProperty(topLevel, "JavaAdapter", obj);
+    @Throws(RhinoException::class)
+    override fun call(cx: Context, scope: Scriptable, thisObj: Scriptable, args: Array<Any>): Any {
+        return construct(cx, scope, args)
     }
     }
 
 
-    public String getClassName() {
-        return "JavaAdapter";
-    }
-
-    public Object call(Context cx, Scriptable scope, Scriptable thisObj,
-            Object[] args) throws RhinoException {
-        return construct(cx, scope, args);
-    }
-
-    public Scriptable construct(Context cx, Scriptable scope, Object[] args)
-    throws RhinoException {
-        if (args.length == 2) {
-            Class<?> clazz = null;
-            Object obj1 = args[0];
-            if (obj1 instanceof Wrapper) {
-                Object o = ((Wrapper)obj1).unwrap();
-                if (o instanceof Class && ((Class)o).isInterface()) {
-                    clazz = (Class) o;
-                }
-            } else if (obj1 instanceof Class) {
-                if (((Class)obj1).isInterface()) {
-                    clazz = (Class) obj1;
+    @Throws(RhinoException::class)
+    override fun construct(cx: Context, scope: Scriptable, args: Array<Any>): Scriptable {
+        return if (args.size == 2) {
+            var clazz: Class<*>? = null
+            val obj1 = args[0]
+            if (obj1 is Wrapper) {
+                val o = obj1.unwrap()
+                if (o is Class<*> && o.isInterface) {
+                    clazz = o
                 }
                 }
+            } else if (obj1 is Class<*> && obj1.isInterface) {
+                clazz = obj1
             }
             }
             if (clazz == null) {
             if (clazz == null) {
-                throw Context.reportRuntimeError("JavaAdapter: first arg should be interface Class");
+                throw Context.reportRuntimeError("JavaAdapter: first arg should be interface Class")
+            } else {
+                val topLevel = getTopLevelScope(scope)
+                Context.toObject(
+                    engine.getInterface(args[1], clazz),
+                    topLevel
+                )
             }
             }
-
-            Scriptable topLevel = ScriptableObject.getTopLevelScope(scope);
-            return cx.toObject(engine.getInterface(args[1],  clazz), topLevel);
         } else {
         } else {
-            throw Context.reportRuntimeError("JavaAdapter requires two arguments");
+            throw Context.reportRuntimeError("JavaAdapter requires two arguments")
         }
         }
     }
     }
 
 
-    private Invocable engine;
-}
+    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)
+        }
+    }
+}

+ 30 - 39
rhino/src/main/java/com/script/rhino/RhinoClassShutter.kt

@@ -22,13 +22,9 @@
  * or visit www.oracle.com if you need additional information or have any
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  * questions.
  */
  */
+package com.script.rhino
 
 
-package com.script.rhino;
-
-import org.mozilla.javascript.ClassShutter;
-
-import java.util.HashMap;
-import java.util.Map;
+import org.mozilla.javascript.ClassShutter
 
 
 /**
 /**
  * This class prevents script access to certain sensitive classes.
  * This class prevents script access to certain sensitive classes.
@@ -38,43 +34,38 @@ import java.util.Map;
  * @author A. Sundararajan
  * @author A. Sundararajan
  * @since 1.6
  * @since 1.6
  */
  */
-final class RhinoClassShutter implements ClassShutter {
-    private static Map<String, Boolean> protectedClasses;
-    private static RhinoClassShutter theInstance;
-
-    private RhinoClassShutter() {
-    }
-
-    static synchronized ClassShutter getInstance() {
-        if (theInstance == null) {
-            theInstance = new RhinoClassShutter();
-            protectedClasses = new HashMap<String, Boolean>();
-
-            // For now, we just have AccessController. Allowing scripts
-            // to this class will allow it to execute doPrivileged in
-            // bootstrap context. We can add more classes for other reasons.
-            protectedClasses.put("java.lang.Class", Boolean.TRUE);
-            protectedClasses.put("java.lang.Runtime", Boolean.TRUE);
-            protectedClasses.put("java.io.File", Boolean.TRUE);
-            protectedClasses.put("java.security.AccessController", Boolean.TRUE);
-        }
-        return theInstance;
-    }
-
-    public boolean visibleToScripts(String fullClassName) {
-        // first do the security check.
-        SecurityManager sm = System.getSecurityManager();
+internal class RhinoClassShutter private constructor() : ClassShutter {
+    override fun visibleToScripts(fullClassName: String): Boolean {
+        val sm = System.getSecurityManager()
         if (sm != null) {
         if (sm != null) {
-            int i = fullClassName.lastIndexOf(".");
+            val i = fullClassName.lastIndexOf(".")
             if (i != -1) {
             if (i != -1) {
                 try {
                 try {
-                    sm.checkPackageAccess(fullClassName.substring(0, i));
-                } catch (SecurityException se) {
-                    return false;
+                    sm.checkPackageAccess(fullClassName.substring(0, i))
+                } catch (var5: SecurityException) {
+                    return false
                 }
                 }
             }
             }
         }
         }
-        // now, check is it a protected class.
-        return protectedClasses.get(fullClassName) == null;
+        return protectedClasses[fullClassName] == null
+    }
+
+    companion object {
+
+        @JvmStatic
+        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
+        }
+
+        @JvmStatic
+        val instance: ClassShutter by lazy {
+            val theInstance = RhinoClassShutter()
+            theInstance
+        }
+
     }
     }
-}
+}

+ 30 - 47
rhino/src/main/java/com/script/rhino/RhinoCompiledScript.kt

@@ -22,20 +22,13 @@
  * or visit www.oracle.com if you need additional information or have any
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  * questions.
  */
  */
+package com.script.rhino
 
 
-package com.script.rhino;
-
-import com.script.CompiledScript;
-import com.script.ScriptContext;
-import com.script.ScriptEngine;
-import com.script.ScriptException;
-
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.JavaScriptException;
-import org.mozilla.javascript.RhinoException;
-import org.mozilla.javascript.Script;
-import org.mozilla.javascript.Scriptable;
-
+import com.script.CompiledScript
+import com.script.ScriptContext
+import com.script.ScriptEngine
+import com.script.ScriptException
+import org.mozilla.javascript.*
 
 
 /**
 /**
  * Represents compiled JavaScript code.
  * Represents compiled JavaScript code.
@@ -43,46 +36,36 @@ import org.mozilla.javascript.Scriptable;
  * @author Mike Grogan
  * @author Mike Grogan
  * @since 1.6
  * @since 1.6
  */
  */
-final class RhinoCompiledScript extends CompiledScript {
+internal class RhinoCompiledScript(
+    private val engine: RhinoScriptEngine,
+    private val script: Script
+) : CompiledScript() {
 
 
-    private com.script.rhino.RhinoScriptEngine engine;
-    private Script script;
-
-
-    RhinoCompiledScript(com.script.rhino.RhinoScriptEngine engine, Script script) {
-        this.engine = engine;
-        this.script = script;
-    }
-
-    public Object eval(ScriptContext context) throws ScriptException {
-
-        Object result = null;
-        Context cx = RhinoScriptEngine.enterContext();
+    @Throws(ScriptException::class)
+    override fun eval(context: ScriptContext): Any? {
+        val cx = Context.enter()
+        val result: Any?
         try {
         try {
-
-            Scriptable scope = engine.getRuntimeScope(context);
-            Object ret = script.exec(cx, scope);
-            result = engine.unwrapReturnValue(ret);
-        } catch (RhinoException re) {
-            int line = (line = re.lineNumber()) == 0 ? -1 : line;
-            String msg;
-            if (re instanceof JavaScriptException) {
-                msg = String.valueOf(((JavaScriptException)re).getValue());
+            val scope = engine.getRuntimeScope(context)
+            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 {
             } else {
-                msg = re.toString();
+                re.toString()
             }
             }
-            ScriptException se = new ScriptException(msg, re.sourceName(), line);
-            se.initCause(re);
-            throw se;
+            val se = ScriptException(msg, re.sourceName(), line)
+            se.initCause(re)
+            throw se
         } finally {
         } finally {
-            Context.exit();
+            Context.exit()
         }
         }
-
-        return result;
+        return result
     }
     }
 
 
-    public ScriptEngine getEngine() {
-        return engine;
+    override fun getEngine(): ScriptEngine {
+        return engine
     }
     }
-
-}
+}

+ 289 - 371
rhino/src/main/java/com/script/rhino/RhinoScriptEngine.kt

@@ -22,440 +22,358 @@
  * or visit www.oracle.com if you need additional information or have any
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  * 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.ScriptContext;
-import com.script.ScriptEngine;
-import com.script.ScriptException;
-import com.script.SimpleBindings;
-
-import org.mozilla.javascript.Callable;
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.ContextFactory;
-import org.mozilla.javascript.Function;
-import org.mozilla.javascript.JavaScriptException;
-import org.mozilla.javascript.RhinoException;
-import org.mozilla.javascript.Script;
-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 java.util.HashMap;
-import java.util.Map;
-
+package com.script.rhino
+
+import com.script.*
+import com.script.rhino.RhinoClassShutter.Companion.instance
+import org.intellij.lang.annotations.Language
+import org.mozilla.javascript.*
+import org.mozilla.javascript.Function
+import java.io.IOException
+import java.io.Reader
+import java.io.StringReader
+import java.lang.reflect.Method
+import java.security.*
 
 
 /**
 /**
- * Implementation of <code>ScriptEngine</code> using the Mozilla Rhino
+ * Implementation of `ScriptEngine` using the Mozilla Rhino
  * interpreter.
  * interpreter.
  *
  *
  * @author Mike Grogan
  * @author Mike Grogan
  * @author A. Sundararajan
  * @author A. Sundararajan
  * @since 1.6
  * @since 1.6
  */
  */
-public final class RhinoScriptEngine extends AbstractScriptEngine
-        implements Invocable, Compilable {
-
-    private static final boolean DEBUG = false;
-
-    private AccessControlContext accCtxt;
-
-    /* Scope where standard JavaScript objects and our
-     * extensions to it are stored. Note that these are not
-     * user defined engine level global variables. These are
-     * variables have to be there on all compliant ECMAScript
-     * scopes. We put these standard objects in this top level.
-     */
-    private com.script.rhino.RhinoTopLevel topLevel;
-
-    /* map used to store indexed properties in engine scope
-     * refer to comment on 'indexedProps' in ExternalScriptable.java.
-     */
-    private Map<Object, Object> indexedProps;
-
-    private InterfaceImplementor implementor;
-
-    private static final int languageVersion = getLanguageVersion();
-    private static final int optimizationLevel = getOptimizationLevel();
-
-    static {
-        ContextFactory.initGlobal(new ContextFactory() {
-            /**
-             * Create new Context instance to be associated with the current thread.
-             */
-            @Override
-            protected Context makeContext() {
-                Context cx = super.makeContext();
-                cx.setLanguageVersion(languageVersion);
-                cx.setOptimizationLevel(optimizationLevel);
-                cx.setClassShutter(com.script.rhino.RhinoClassShutter.getInstance());
-                cx.setWrapFactory(com.script.rhino.RhinoWrapFactory.getInstance());
-                return cx;
-            }
-
-            /**
-             * Execute top call to script or function. When the runtime is about to
-             * execute a script or function that will create the first stack frame
-             * with scriptable code, it calls this method to perform the real call.
-             * In this way execution of any script happens inside this function.
-             */
-            @Override
-            protected Object doTopCall(final Callable callable,
-                                       final Context cx, final Scriptable scope,
-                                       final Scriptable thisObj, final Object[] args) {
-                AccessControlContext accCtxt = null;
-                Scriptable global = ScriptableObject.getTopLevelScope(scope);
-                Scriptable globalProto = global.getPrototype();
-                if (globalProto instanceof com.script.rhino.RhinoTopLevel) {
-                    accCtxt = ((com.script.rhino.RhinoTopLevel) globalProto).getAccessContext();
-                }
-
-                if (accCtxt != null) {
-                    return AccessController.doPrivileged(new PrivilegedAction<Object>() {
-                        public Object run() {
-                            return superDoTopCall(callable, cx, scope, thisObj, args);
-                        }
-                    }, accCtxt);
-                } else {
-                    return superDoTopCall(callable, cx, scope, thisObj, args);
-                }
-            }
-
-            private Object superDoTopCall(Callable callable,
-                                          Context cx, Scriptable scope,
-                                          Scriptable thisObj, Object[] args) {
-                return super.doTopCall(callable, cx, scope, thisObj, args);
-            }
-        });
-    }
-
-    private static final String RHINO_JS_VERSION = "rhino.js.version";
-
-    private static int getLanguageVersion() {
-        return Context.VERSION_1_8;
-    }
-
-    private static final String RHINO_OPT_LEVEL = "rhino.opt.level";
-
-    private static int getOptimizationLevel() {
-        int optLevel = -1;
-        // disable optimizer under security manager, for now.
-        if (System.getSecurityManager() == null) {
-            optLevel = Integer.getInteger(RHINO_OPT_LEVEL, -1);
-        }
-        return optLevel;
-    }
-
-    /**
-     * Creates a new instance of RhinoScriptEngine
-     */
-    public RhinoScriptEngine() {
-        if (System.getSecurityManager() != null) {
-            try {
-                AccessController.checkPermission(new AllPermission());
-            } catch (AccessControlException ace) {
-                accCtxt = AccessController.getContext();
-            }
-        }
-
-        Context cx = enterContext();
-        try {
-            topLevel = new RhinoTopLevel(cx, this);
-        } finally {
-            cx.exit();
-        }
-
-        indexedProps = new HashMap<Object, Object>();
-
-        //construct object used to implement getInterface
-        implementor = new InterfaceImplementor(this) {
-            protected boolean isImplemented(Object thiz, Class<?> iface) {
-                Context cx = enterContext();
-                try {
-                    if (thiz != null && !(thiz instanceof Scriptable)) {
-                        thiz = cx.toObject(thiz, topLevel);
-                    }
-                    Scriptable engineScope = getRuntimeScope(context);
-                    Scriptable localScope = (thiz != null) ? (Scriptable) thiz :
-                            engineScope;
-                    for (Method method : iface.getMethods()) {
-                        // ignore methods of java.lang.Object class
-                        if (method.getDeclaringClass() == Object.class) {
-                            continue;
-                        }
-                        Object obj = ScriptableObject.getProperty(localScope, method.getName());
-                        if (!(obj instanceof Function)) {
-                            return false;
-                        }
-                    }
-                    return true;
-                } finally {
-                    cx.exit();
-                }
-            }
-
-            protected Object convertResult(Method method, Object res)
-                    throws ScriptException {
-                Class desiredType = method.getReturnType();
-                if (desiredType == Void.TYPE) {
-                    return null;
-                } else {
-                    return Context.jsToJava(res, desiredType);
-                }
-            }
-        };
-    }
-
-    public Object eval(Reader reader, ScriptContext ctxt)
-            throws ScriptException {
-        Object ret;
-
-        Context cx = enterContext();
+class RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
+    var accessContext: AccessControlContext? = null
+    private var topLevel: RhinoTopLevel? = null
+    private val indexedProps: MutableMap<Any, Any>
+    private val implementor: InterfaceImplementor
+
+    @Throws(ScriptException::class)
+    override fun eval(reader: Reader, ctxt: ScriptContext): Any {
+        val cx = Context.enter()
+        val ret: Any
         try {
         try {
-            Scriptable scope = getRuntimeScope(ctxt);
-            String filename = (String) get(ScriptEngine.FILENAME);
-            filename = filename == null ? "<Unknown source>" : filename;
-
-            ret = cx.evaluateReader(scope, reader, filename, 1, null);
-        } catch (RhinoException re) {
-            if (DEBUG) re.printStackTrace();
-            int line = (line = re.lineNumber()) == 0 ? -1 : line;
-            String msg;
-            if (re instanceof JavaScriptException) {
-                msg = String.valueOf(((JavaScriptException) re).getValue());
+            val scope = getRuntimeScope(ctxt)
+            var filename = this["javax.script.filename"] as? String
+            filename = filename ?: "<Unknown source>"
+            ret = cx.evaluateReader(scope, reader, filename, 1, null as Any?)
+        } catch (re: RhinoException) {
+            val line = if (re.lineNumber() == 0) -1 else re.lineNumber()
+            val msg: String = if (re is JavaScriptException) {
+                re.value.toString()
             } else {
             } else {
-                msg = re.toString();
+                re.toString()
             }
             }
-            ScriptException se = new ScriptException(msg, re.sourceName(), line);
-            se.initCause(re);
-            throw se;
-        } catch (IOException ee) {
-            throw new ScriptException(ee);
+            val se = ScriptException(msg, re.sourceName(), line)
+            se.initCause(re)
+            throw se
+        } catch (var14: IOException) {
+            throw ScriptException(var14)
         } finally {
         } finally {
-            cx.exit();
+            Context.exit()
         }
         }
-
-        return unwrapReturnValue(ret);
+        return unwrapReturnValue(ret)!!
     }
     }
 
 
-    public Object eval(String script, ScriptContext ctxt) throws ScriptException {
-        if (script == null) {
-            throw new NullPointerException("null script");
+    @Throws(ScriptException::class)
+    override fun eval(script: String?, ctxt: ScriptContext): Any {
+        return if (script == null) {
+            throw NullPointerException("null script")
+        } else {
+            this.eval(StringReader(script) as Reader, ctxt)
         }
         }
-        return eval(new StringReader(script), ctxt);
     }
     }
 
 
-    public Bindings createBindings() {
-        return new SimpleBindings();
+    override fun createBindings(): Bindings {
+        return SimpleBindings()
     }
     }
 
 
-    //Invocable methods
-    public Object invokeFunction(String name, Object... args)
-            throws ScriptException, NoSuchMethodException {
-        return invoke(null, name, args);
+    @Throws(ScriptException::class, NoSuchMethodException::class)
+    override fun invokeFunction(name: String, vararg args: Any): Any {
+        return this.invoke(null as Any?, name, *args)
     }
     }
 
 
-    public Object invokeMethod(Object thiz, String name, Object... args)
-            throws ScriptException, NoSuchMethodException {
-        if (thiz == null) {
-            throw new IllegalArgumentException("script object can not be null");
+    @Throws(ScriptException::class, NoSuchMethodException::class)
+    override fun invokeMethod(thiz: Any?, name: String, vararg args: Any): Any {
+        return if (thiz == null) {
+            throw IllegalArgumentException("脚本对象不能为空")
+        } else {
+            this.invoke(thiz, name, *args)
         }
         }
-        return invoke(thiz, name, args);
     }
     }
 
 
-    private Object invoke(Object thiz, String name, Object... args)
-            throws ScriptException, NoSuchMethodException {
-        Context cx = enterContext();
+    @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 {
         try {
             if (name == null) {
             if (name == null) {
-                throw new NullPointerException("method name is null");
+                throw NullPointerException("方法名为空")
             }
             }
-
-            if (thiz != null && !(thiz instanceof Scriptable)) {
-                thiz = cx.toObject(thiz, topLevel);
+            if (thiz1 != null && thiz1 !is Scriptable) {
+                thiz1 = Context.toObject(thiz1, topLevel)
             }
             }
-
-            Scriptable engineScope = getRuntimeScope(context);
-            Scriptable localScope = (thiz != null) ? (Scriptable) thiz :
-                    engineScope;
-            Object obj = ScriptableObject.getProperty(localScope, name);
-            if (!(obj instanceof Function)) {
-                throw new NoSuchMethodException("no such method: " + name);
-            }
-
-            Function func = (Function) obj;
-            Scriptable scope = func.getParentScope();
+            val engineScope = getRuntimeScope(context)
+            val localScope = if (thiz1 != null) thiz1 as Scriptable else engineScope
+            val obj = ScriptableObject.getProperty(localScope, name) as? Function
+                ?: throw NoSuchMethodException("no such method: $name")
+            val func = obj
+            var scope = func.parentScope
             if (scope == null) {
             if (scope == null) {
-                scope = engineScope;
+                scope = engineScope
             }
             }
-            Object result = func.call(cx, scope, localScope,
-                    wrapArguments(args));
-            return unwrapReturnValue(result);
-        } catch (RhinoException re) {
-            if (DEBUG) re.printStackTrace();
-            int line = (line = re.lineNumber()) == 0 ? -1 : line;
-            ScriptException se = new ScriptException(re.toString(), re.sourceName(), line);
-            se.initCause(re);
-            throw se;
+            val result = func.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 {
         } finally {
-            cx.exit();
+            Context.exit()
         }
         }
+        return var11
     }
     }
 
 
-    public <T> T getInterface(Class<T> clasz) {
-        try {
-            return implementor.getInterface(null, clasz);
-        } catch (ScriptException e) {
-            return null;
+    override fun <T> getInterface(clasz: Class<T>): T? {
+        return try {
+            implementor.getInterface(null as Any?, clasz)
+        } catch (var3: ScriptException) {
+            null
         }
         }
     }
     }
 
 
-    public <T> T getInterface(Object thiz, Class<T> clasz) {
-        if (thiz == null) {
-            throw new IllegalArgumentException("script object can not be null");
-        }
-
-        try {
-            return implementor.getInterface(thiz, clasz);
-        } catch (ScriptException e) {
-            return null;
+    override fun <T> getInterface(thiz: Any?, clasz: Class<T>): T? {
+        return if (thiz == null) {
+            throw IllegalArgumentException("脚本对象不能为空")
+        } else {
+            try {
+                implementor.getInterface(thiz, clasz)
+            } catch (var4: ScriptException) {
+                null
+            }
         }
         }
     }
     }
 
 
-    private static final String printSource =
-            "function print(str, newline) {                \n" +
-                    "    if (typeof(str) == 'undefined') {         \n" +
-                    "        str = 'undefined';                    \n" +
-                    "    } else if (str == null) {                 \n" +
-                    "        str = 'null';                         \n" +
-                    "    }                                         \n" +
-                    "    var out = context.getWriter();            \n" +
-                    "    if (!(out instanceof java.io.PrintWriter))\n" +
-                    "        out = new java.io.PrintWriter(out);   \n" +
-                    "    out.print(String(str));                   \n" +
-                    "    if (newline) out.print('\\n');            \n" +
-                    "    out.flush();                              \n" +
-                    "}\n" +
-                    "function println(str) {                       \n" +
-                    "    print(str, true);                         \n" +
-                    "}";
-
-    Scriptable getRuntimeScope(ScriptContext ctxt) {
-        if (ctxt == null) {
-            throw new NullPointerException("null script context");
-        }
-
-        // we create a scope for the given ScriptContext
-        Scriptable newScope = new com.script.rhino.ExternalScriptable(ctxt, indexedProps);
-
-        // Set the prototype of newScope to be 'topLevel' so that
-        // JavaScript standard objects are visible from the scope.
-        newScope.setPrototype(topLevel);
-
-        // define "context" variable in the new scope
-        newScope.put("context", newScope, ctxt);
-
-        // define "print", "println" functions in the new scope
-        Context cx = enterContext();
-        try {
-            cx.evaluateString(newScope, printSource, "print", 1, null);
-        } finally {
-            cx.exit();
+    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 as Any?
+                )
+            } finally {
+                Context.exit()
+            }
+            newScope
         }
         }
-        return newScope;
     }
     }
 
 
-
-    //Compilable methods
-    public CompiledScript compile(String script) throws ScriptException {
-        return compile(new StringReader(script));
+    @Throws(ScriptException::class)
+    override fun compile(script: String): CompiledScript {
+        return this.compile(StringReader(script) as Reader)
     }
     }
 
 
-    public CompiledScript compile(java.io.Reader script) throws ScriptException {
-        CompiledScript ret = null;
-        Context cx = enterContext();
-
+    @Throws(ScriptException::class)
+    override fun compile(script: Reader): CompiledScript {
+        val cx = Context.enter()
+        val ret: RhinoCompiledScript
         try {
         try {
-            String fileName = (String) get(ScriptEngine.FILENAME);
+            var fileName = this["javax.script.filename"] as? String
             if (fileName == null) {
             if (fileName == null) {
-                fileName = "<Unknown Source>";
+                fileName = "<Unknown Source>"
             }
             }
-
-            Scriptable scope = getRuntimeScope(context);
-            @SuppressWarnings("deprecation")
-            Script scr = cx.compileReader(scope, script, fileName, 1, null);
-            ret = new RhinoCompiledScript(this, scr);
-        } catch (Exception e) {
-            if (DEBUG) e.printStackTrace();
-            throw new ScriptException(e);
+            val scr = cx.compileReader(script, fileName, 1, null as Any?)
+            ret = RhinoCompiledScript(this, scr)
+        } catch (var9: Exception) {
+            throw ScriptException(var9)
         } finally {
         } finally {
-            cx.exit();
+            Context.exit()
         }
         }
-        return ret;
+        return ret
     }
     }
 
 
-
-    //package-private helpers
-
-    static Context enterContext() {
-        // call this always so that initializer of this class runs
-        // and initializes custom wrap factory and class shutter.
-        return Context.enter();
+    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
+        }
     }
     }
 
 
-    AccessControlContext getAccessContext() {
-        return accCtxt;
+    fun unwrapReturnValue(result: Any?): Any? {
+        var result1 = result
+        if (result1 is Wrapper) {
+            result1 = result1.unwrap()
+        }
+        return if (result1 is Undefined) null else result1
     }
     }
 
 
-    Object[] wrapArguments(Object[] args) {
-        if (args == null) {
-            return Context.emptyArgs;
+    init {
+        if (System.getSecurityManager() != null) {
+            try {
+                AccessController.checkPermission(AllPermission())
+            } catch (var6: AccessControlException) {
+                accessContext = AccessController.getContext()
+            }
         }
         }
-        Object[] res = new Object[args.length];
-        for (int i = 0; i < res.length; i++) {
-            res[i] = Context.javaToJS(args[i], topLevel);
+        val cx = Context.enter()
+        try {
+            topLevel = RhinoTopLevel(cx, this)
+        } finally {
+            Context.exit()
         }
         }
-        return res;
-    }
+        indexedProps = HashMap()
+        implementor = object : InterfaceImplementor(this) {
+            override fun isImplemented(thiz: Any?, iface: Class<*>): Boolean {
+                var thiz1 = thiz
+                return try {
+                    if (thiz1 != null && thiz1 !is Scriptable) {
+                        thiz1 = Context.toObject(
+                            thiz1,
+                            topLevel
+                        )
+                    }
+                    val engineScope =
+                        getRuntimeScope(context)
+                    val localScope =
+                        if (thiz1 != null) thiz1 as Scriptable else engineScope
+                    val var5 = iface.methods
+                    val var6 = var5.size
+                    for (var7 in 0 until var6) {
+                        val method = var5[var7]
+                        if (method.declaringClass != Any::class.java) {
+                            val obj =
+                                ScriptableObject.getProperty(localScope, method.name) as? Function
+                            obj ?: return false
+                        }
+                    }
+                    true
+                } finally {
+                    Context.exit()
+                }
+            }
 
 
-    Object unwrapReturnValue(Object result) {
-        if (result instanceof Wrapper) {
-            result = ((Wrapper) result).unwrap();
+            override fun convertResult(method: Method?, res: Any): Any {
+                val desiredType = method!!.returnType
+                return (if (desiredType == Void.TYPE) null else Context.jsToJava(
+                    res,
+                    desiredType
+                ))!!
+            }
         }
         }
-
-        return result instanceof Undefined ? null : result;
     }
     }
 
 
-    /*
-    public static void main(String[] args) throws Exception {
-        if (args.length == 0) {
-            System.out.println("No file specified");
-            return;
-        }
+    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() {
+                override fun makeContext(): Context {
+                    val cx = super.makeContext()
+                    cx.languageVersion = 200
+                    cx.optimizationLevel = -1
+                    cx.setClassShutter(instance)
+                    cx.wrapFactory = RhinoWrapFactory.instance
+                    return cx
+                }
 
 
-        InputStreamReader r = new InputStreamReader(new FileInputStream(args[0]));
-        ScriptEngine engine = new RhinoScriptEngine();
+                override fun doTopCall(
+                    callable: Callable,
+                    cx: Context,
+                    scope: Scriptable,
+                    thisObj: Scriptable,
+                    args: Array<Any>
+                ): Any {
+                    var accCtxt: AccessControlContext? = null
+                    val global = ScriptableObject.getTopLevelScope(scope)
+                    val globalProto = global.prototype
+                    if (globalProto is RhinoTopLevel) {
+                        accCtxt = globalProto.accessContext
+                    }
+                    return if (accCtxt != null) AccessController.doPrivileged(
+                        PrivilegedAction {
+                            superDoTopCall(
+                                callable,
+                                cx,
+                                scope,
+                                thisObj,
+                                args
+                            )
+                        } as PrivilegedAction<Any>, accCtxt) else superDoTopCall(
+                        callable,
+                        cx,
+                        scope,
+                        thisObj,
+                        args
+                    )
+                }
 
 
-        engine.put("x", "y");
-        engine.put(ScriptEngine.FILENAME, args[0]);
-        engine.eval(r);
-        System.out.println(engine.get("x"));
+                private fun superDoTopCall(
+                    callable: Callable,
+                    cx: Context,
+                    scope: Scriptable,
+                    thisObj: Scriptable,
+                    args: Array<Any>
+                ): Any {
+                    return super.doTopCall(callable, cx, scope, thisObj, args)
+                }
+            })
+        }
     }
     }
-    */
-}
+}

+ 61 - 131
rhino/src/main/java/com/script/rhino/RhinoTopLevel.kt

@@ -22,24 +22,14 @@
  * or visit www.oracle.com if you need additional information or have any
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  * questions.
  */
  */
+package com.script.rhino
 
 
-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.LazilyLoadedCtor;
-import org.mozilla.javascript.Scriptable;
-import org.mozilla.javascript.ScriptableObject;
-import org.mozilla.javascript.Synchronizer;
-import org.mozilla.javascript.Wrapper;
-
-import java.security.AccessControlContext;
-
+import com.script.Bindings
+import com.script.ScriptContext
+import com.script.SimpleScriptContext
+import org.mozilla.javascript.*
+import org.mozilla.javascript.Function
+import java.security.AccessControlContext
 
 
 /**
 /**
  * This class serves as top level scope for Rhino. This class adds
  * This class serves as top level scope for Rhino. This class adds
@@ -49,129 +39,69 @@ import java.security.AccessControlContext;
  * @author A. Sundararajan
  * @author A. Sundararajan
  * @since 1.6
  * @since 1.6
  */
  */
-public final class RhinoTopLevel extends ImporterTopLevel {
-    RhinoTopLevel(Context cx, RhinoScriptEngine engine) {
-        // second boolean parameter to super constructor tells whether
-        // to seal standard JavaScript objects or not. If security manager
-        // is present, we seal the standard objects.
-        super(cx, System.getSecurityManager() != null);
-        this.engine = engine;
+@Suppress("UNUSED_PARAMETER")
+class RhinoTopLevel internal constructor(cx: Context?, val scriptEngine: RhinoScriptEngine) :
+    ImporterTopLevel(cx, System.getSecurityManager() != null) {
 
 
-        // initialize JSAdapter lazily. Reduces footprint & startup time.
-        new LazilyLoadedCtor(this, "JSAdapter",
-                "com.sun.script.javascript.JSAdapter",
-                false);
+    init {
+        LazilyLoadedCtor(this, "JSAdapter", "com.sun.script.javascript.JSAdapter", false)
+        JavaAdapter.init(cx, this, false)
+        val names = arrayOf("bindings", "scope", "sync")
+        defineFunctionProperties(names, RhinoTopLevel::class.java, 2)
+    }
 
 
-        /*
-         * initialize JavaAdapter. We can't lazy initialize this because
-         * lazy initializer attempts to define a new property. But, JavaAdapter
-         * is an exisiting property that we overwrite.
-         */
-        com.script.rhino.JavaAdapter.init(cx, this, false);
+    val accessContext: AccessControlContext?
+        get() = scriptEngine.accessContext
 
 
-        // add top level functions
-        String names[] = { "bindings", "scope", "sync"  };
-        defineFunctionProperties(names, RhinoTopLevel.class,
-                ScriptableObject.DONTENUM);
-    }
+    companion object {
 
 
-    /**
-     * The bindings function takes a JavaScript scope object
-     * of type ExternalScriptable and returns the underlying Bindings
-     * instance.
-     *
-     *    var page = scope(pageBindings);
-     *    with (page) {
-     *       // code that uses page scope
-     *    }
-     *    var b = bindings(page);
-     *    // operate on bindings here.
-     */
-    public static Object bindings(Context cx, Scriptable thisObj, Object[] args,
-            Function funObj) {
-        if (args.length == 1) {
-            Object arg = args[0];
-            if (arg instanceof Wrapper) {
-                arg = ((Wrapper)arg).unwrap();
-            }
-            if (arg instanceof com.script.rhino.ExternalScriptable) {
-                ScriptContext ctx = ((com.script.rhino.ExternalScriptable)arg).getContext();
-                Bindings bind = ctx.getBindings(ScriptContext.ENGINE_SCOPE);
-                return Context.javaToJS(bind,
-                           ScriptableObject.getTopLevelScope(thisObj));
+        @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()
         }
         }
-        return cx.getUndefinedValue();
-    }
 
 
-    /**
-     * The scope function creates a new JavaScript scope object
-     * with given Bindings object as backing store. This can be used
-     * to create a script scope based on arbitrary Bindings instance.
-     * For example, in webapp scenario, a 'page' level Bindings instance
-     * may be wrapped as a scope and code can be run in JavaScripe 'with'
-     * statement:
-     *
-     *    var page = scope(pageBindings);
-     *    with (page) {
-     *       // code that uses page scope
-     *    }
-     */
-    public static Object scope(Context cx, Scriptable thisObj, Object[] args,
-            Function funObj) {
-        if (args.length == 1) {
-            Object arg = args[0];
-            if (arg instanceof Wrapper) {
-                arg = ((Wrapper)arg).unwrap();
-            }
-            if (arg instanceof Bindings) {
-                ScriptContext ctx = new SimpleScriptContext();
-                ctx.setBindings((Bindings)arg, ScriptContext.ENGINE_SCOPE);
-                Scriptable res = new com.script.rhino.ExternalScriptable(ctx);
-                res.setPrototype(ScriptableObject.getObjectPrototype(thisObj));
-                res.setParentScope(ScriptableObject.getTopLevelScope(thisObj));
-                return res;
+        @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()
         }
         }
-        return cx.getUndefinedValue();
-    }
 
 
-    /**
-     * The sync function creates a synchronized function (in the sense
-     * of a Java synchronized method) from an existing function. The
-     * new function synchronizes on the <code>this</code> object of
-     * its invocation.
-     * {@code
-     * js> var o = { f : sync(function(x) {
-     *       print("entry");
-     *       Packages.java.lang.Thread.sleep(x*1000);
-     *       print("exit");
-     *     })};
-     * js> thread(function() {o.f(5);});
-     * entry
-     * js> thread(function() {o.f(5);});
-     * js>
-     * exit
-     * entry
-     * exit
-     * }
-     */
-    public static Object sync(Context cx, Scriptable thisObj, Object[] args,
-            Function funObj) {
-        if (args.length == 1 && args[0] instanceof Function) {
-            return new Synchronizer((Function)args[0]);
-        } else {
-            throw Context.reportRuntimeError("wrong argument(s) for sync");
+        @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")
+            }
         }
         }
     }
     }
-
-    RhinoScriptEngine getScriptEngine() {
-        return engine;
-    }
-
-    AccessControlContext getAccessContext() {
-        return engine.getAccessContext();
-    }
-
-    private RhinoScriptEngine engine;
-}
+}

+ 77 - 111
rhino/src/main/java/com/script/rhino/RhinoWrapFactory.kt

@@ -22,18 +22,14 @@
  * or visit www.oracle.com if you need additional information or have any
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  * questions.
  */
  */
+package com.script.rhino
 
 
-package com.script.rhino;
-
-import org.mozilla.javascript.ClassShutter;
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.NativeJavaObject;
-import org.mozilla.javascript.Scriptable;
-import org.mozilla.javascript.WrapFactory;
-
-import java.lang.reflect.Member;
-import java.lang.reflect.Modifier;
-
+import org.mozilla.javascript.Context
+import org.mozilla.javascript.NativeJavaObject
+import org.mozilla.javascript.Scriptable
+import org.mozilla.javascript.WrapFactory
+import java.lang.reflect.Member
+import java.lang.reflect.Modifier
 
 
 /**
 /**
  * This wrap factory is used for security reasons. JSR 223 script
  * This wrap factory is used for security reasons. JSR 223 script
@@ -48,118 +44,88 @@ import java.lang.reflect.Modifier;
  * @author A. Sundararajan
  * @author A. Sundararajan
  * @since 1.6
  * @since 1.6
  */
  */
-final class RhinoWrapFactory extends WrapFactory {
-    private RhinoWrapFactory() {}
-    private static RhinoWrapFactory theInstance;
-
-    static synchronized WrapFactory getInstance() {
-        if (theInstance == null) {
-            theInstance = new RhinoWrapFactory();
-        }
-        return theInstance;
-    }
-
-    // We use instance of this class to wrap security sensitive
-    // Java object. Please refer below.
-    private static class RhinoJavaObject extends NativeJavaObject {
-        RhinoJavaObject(Scriptable scope, Object obj, Class type) {
-            // we pass 'null' to object. NativeJavaObject uses
-            // passed 'type' to reflect fields and methods when
-            // object is null.
-            super(scope, null, type);
-
-            // Now, we set actual object. 'javaObject' is protected
-            // field of NativeJavaObject.
-            javaObject = obj;
-        }
-
-        @Override
-        public Object get(String name, Scriptable start) {
-            if (name.equals("getClass") || name.equals("exec")) {
-                return NOT_FOUND;
-            }
-            return super.get(name, start);
-        }
-    }
+internal class RhinoWrapFactory private constructor() : WrapFactory() {
 
 
-    public Scriptable wrapAsJavaObject(Context cx, Scriptable scope,
-            Object javaObject, Class staticType) {
-        if (scope != null) {
-            scope.delete("Packages");
-        }
-        SecurityManager sm = System.getSecurityManager();
-        ClassShutter classShutter = RhinoClassShutter.getInstance();
-        if (javaObject instanceof ClassLoader) {
-            // Check with Security Manager whether we can expose a
-            // ClassLoader...
-            if (sm != null) {
-                sm.checkPermission(new RuntimePermission("getClassLoader"));
-            }
-            // if we fall through here, check permission succeeded.
-            return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
+    override fun wrapAsJavaObject(
+        cx: Context,
+        scope: Scriptable?,
+        javaObject: Any,
+        staticType: Class<*>?
+    ): Scriptable? {
+        scope?.delete("Packages")
+        val sm = System.getSecurityManager()
+        val classShutter = RhinoClassShutter.instance
+        return if (javaObject is ClassLoader) {
+            sm?.checkPermission(RuntimePermission("getClassLoader"))
+            super.wrapAsJavaObject(cx, scope, javaObject, staticType)
         } else {
         } else {
-            String name = null;
-            if (javaObject instanceof Class) {
-                name = ((Class)javaObject).getName();
-            } else if (javaObject instanceof Member) {
-                Member member = (Member) javaObject;
-                // Check member access. Don't allow reflective access to
-                // non-public members. Note that we can't call checkMemberAccess
-                // because that expects exact stack depth!
-                if (sm != null && !Modifier.isPublic(member.getModifiers())) {
-                    return null;
+            var name: String? = null
+            if (javaObject is Class<*>) {
+                name = javaObject.name
+            } else if (javaObject is Member) {
+                if (sm != null && !Modifier.isPublic(javaObject.modifiers)) {
+                    return null
                 }
                 }
-                name = member.getDeclaringClass().getName();
+                name = javaObject.declaringClass.name
             }
             }
-            // Now, make sure that no ClassShutter prevented Class or Member
-            // of it is accessed reflectively. Note that ClassShutter may
-            // prevent access to a class, even though SecurityManager permit.
             if (name != null) {
             if (name != null) {
-                if (!classShutter.visibleToScripts(name)) {
-                    return null;
+                if (!classShutter.visibleToScripts(name)) null else super.wrapAsJavaObject(
+                    cx,
+                    scope,
+                    javaObject,
+                    staticType
+                )
+            } else {
+                var dynamicType: Class<*>? = javaObject.javaClass
+                name = dynamicType!!.name
+                if (classShutter.visibleToScripts(name)) {
+                    super.wrapAsJavaObject(cx, scope, javaObject, staticType)
                 } else {
                 } else {
-                    return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
+                    var type: Class<*>? = null
+                    if (staticType != null && staticType.isInterface) {
+                        type = staticType
+                    } else {
+                        while (dynamicType != null) {
+                            dynamicType = dynamicType.superclass
+                            name = dynamicType.name
+                            if (classShutter.visibleToScripts(name)) {
+                                type = dynamicType
+                                break
+                            }
+                        }
+                        assert(type != null) { "java.lang.Object 不可访问" }
+                    }
+                    RhinoJavaObject(scope, javaObject, type)
                 }
                 }
             }
             }
         }
         }
+    }
 
 
-        // we have got some non-reflective object.
-        Class dynamicType = javaObject.getClass();
-        String name = dynamicType.getName();
-        if (!classShutter.visibleToScripts(name)) {
-            // Object of some sensitive class (such as sun.net.www.*
-            // objects returned from public method of java.net.URL class.
-            // We expose this object as though it is an object of some
-            // super class that is safe for access.
+    private class RhinoJavaObject(
+        scope: Scriptable?,
+        obj: Any?,
+        type: Class<*>?
+    ) : NativeJavaObject(scope, null as Any?, type) {
+        init {
+            javaObject = obj
+        }
 
 
-            Class type = null;
+        override fun get(name: String, start: Scriptable): Any {
+            return if (name != "getClass" && name != "exec") super.get(name, start) else NOT_FOUND
+        }
+    }
 
 
-            // Whenever a Java Object is wrapped, we are passed with a
-            // staticType which is the type found from environment. For
-            // example, method return type known from signature. The dynamic
-            // type would be the actual Class of the actual returned object.
-            // If the staticType is an interface, we just use that type.
-            if (staticType != null && staticType.isInterface()) {
-                type = staticType;
-            } else {
-                // dynamicType is always a class type and never an interface.
-                // find an accessible super class of the dynamic type.
-                while (dynamicType != null) {
-                    dynamicType = dynamicType.getSuperclass();
-                    name = dynamicType.getName();
-                    if (classShutter.visibleToScripts(name)) {
-                         type = dynamicType; break;
-                    }
+    companion object {
+        private var theInstance: RhinoWrapFactory? = null
+
+        @JvmStatic
+        @get:Synchronized
+        val instance: WrapFactory?
+            get() {
+                if (theInstance == null) {
+                    theInstance = RhinoWrapFactory()
                 }
                 }
-                // atleast java.lang.Object has to be accessible. So, when
-                // we reach here, type variable should not be null.
-                assert type != null:
-                       "even java.lang.Object is not accessible?";
+                return theInstance
             }
             }
-            // create custom wrapper with the 'safe' type.
-            return new RhinoJavaObject(scope, javaObject, type);
-        } else {
-            return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
-        }
     }
     }
-}
+}