feat(rhino): java object and class can custom prototype in javascript
This commit is contained in:
@@ -5,7 +5,7 @@ module.exports = function(__runtime__, scope){
|
||||
var __obj__ = new java.lang.Object();
|
||||
|
||||
for(var method in __selector__){
|
||||
if(!__obj__[method] && !scope[method]){
|
||||
if(!(method in __obj__) && !(method in scope)){
|
||||
scope[method] = (function(method) {
|
||||
return function(){
|
||||
var s = selector();
|
||||
|
||||
@@ -5,6 +5,8 @@ import android.util.Log;
|
||||
|
||||
import com.stardust.autojs.BuildConfig;
|
||||
import com.stardust.autojs.rhino.AndroidContextFactory;
|
||||
import com.stardust.autojs.rhino.NativeJavaClassWithPrototype;
|
||||
import com.stardust.autojs.rhino.NativeJavaObjectWithPrototype;
|
||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||
import com.stardust.autojs.script.JavaScriptSource;
|
||||
import com.stardust.autojs.script.StringScriptSource;
|
||||
@@ -15,6 +17,9 @@ import com.stardust.pio.UncheckedIOException;
|
||||
import org.mozilla.javascript.Callable;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ImporterTopLevel;
|
||||
import org.mozilla.javascript.NativeJavaClass;
|
||||
import org.mozilla.javascript.NativeJavaObject;
|
||||
import org.mozilla.javascript.NativeObject;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
import org.mozilla.javascript.commonjs.module.RequireBuilder;
|
||||
@@ -28,6 +33,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
@@ -158,6 +164,9 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
|
||||
|
||||
private class WrapFactory extends org.mozilla.javascript.WrapFactory {
|
||||
|
||||
|
||||
private ConcurrentHashMap<Class, NativeJavaClassWithPrototype> mJavaClasses = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Object wrap(Context cx, Scriptable scope, Object obj, Class<?> staticType) {
|
||||
if (obj instanceof String) {
|
||||
@@ -165,11 +174,28 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
|
||||
}
|
||||
if (staticType == UiObjectCollection.class) {
|
||||
return getRuntime().bridges.asArray(obj);
|
||||
|
||||
}
|
||||
return super.wrap(cx, scope, obj, staticType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject, Class<?> staticType) {
|
||||
NativeJavaObjectWithPrototype obj = new NativeJavaObjectWithPrototype(scope, javaObject, staticType);
|
||||
NativeJavaClassWithPrototype clazz = mJavaClasses.get(obj.getClass());
|
||||
if (clazz == null) {
|
||||
clazz = (NativeJavaClassWithPrototype) wrapJavaClass(cx, scope, obj.getClass());
|
||||
}
|
||||
obj.setPrototype(clazz);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Scriptable wrapJavaClass(Context cx, Scriptable scope, Class<?> javaClass) {
|
||||
NativeJavaClassWithPrototype clazz = new NativeJavaClassWithPrototype(scope, javaClass);
|
||||
mJavaClasses.put(javaClass, clazz);
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
private class InterruptibleAndroidContextFactory extends AndroidContextFactory {
|
||||
@@ -193,10 +219,6 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
|
||||
return cx;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doTopCall(Callable callable, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
|
||||
return super.doTopCall(callable, cx, scope, thisObj, args);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.stardust.autojs.rhino;
|
||||
|
||||
import org.mozilla.javascript.EvaluatorException;
|
||||
import org.mozilla.javascript.NativeJavaClass;
|
||||
import org.mozilla.javascript.NativeObject;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2018/4/4.
|
||||
*/
|
||||
|
||||
public class NativeJavaClassWithPrototype extends NativeJavaClass {
|
||||
|
||||
private static final Object NULL = new Object();
|
||||
private ConcurrentHashMap<String, Object> mProperties = new ConcurrentHashMap();
|
||||
|
||||
public NativeJavaClassWithPrototype(Scriptable scope, Class<?> javaClass) {
|
||||
super(scope, javaClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(String name, Scriptable start) {
|
||||
return mProperties.containsKey(name) || super.has(name, start) || (prototype != null && prototype.has(name, start))
|
||||
|| name.equals("prototype");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String name, Scriptable start) {
|
||||
if (name.equals("prototype")) {
|
||||
return prototype;
|
||||
}
|
||||
Object value = mProperties.get(name);
|
||||
if (value != null) {
|
||||
return unwrapValue(value);
|
||||
}
|
||||
try {
|
||||
value = super.get(name, start);
|
||||
} catch (EvaluatorException e) {
|
||||
if (!memberNotFound(e)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
if (value != Scriptable.NOT_FOUND) {
|
||||
return value;
|
||||
}
|
||||
if (prototype == null) {
|
||||
return Scriptable.NOT_FOUND;
|
||||
}
|
||||
return prototype.get(name, start);
|
||||
}
|
||||
|
||||
private Object unwrapValue(Object value) {
|
||||
if (value == NULL)
|
||||
return null;
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String name, Scriptable start, Object value) {
|
||||
if (name.equals("prototype")) {
|
||||
prototype = (Scriptable) value;
|
||||
return;
|
||||
}
|
||||
if (mProperties.containsKey(name)) {
|
||||
mProperties.put(name, wrapValue(value));
|
||||
}
|
||||
try {
|
||||
super.put(name, start, value);
|
||||
} catch (EvaluatorException e) {
|
||||
if (memberNotFound(e)) {
|
||||
mProperties.put(name, wrapValue(value));
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object wrapValue(Object value) {
|
||||
if (value == null)
|
||||
return NULL;
|
||||
return value;
|
||||
}
|
||||
|
||||
private static boolean memberNotFound(EvaluatorException e) {
|
||||
return e.getMessage() != null && e.getMessage().startsWith("Java class \"com.stardust.autojs.rhino.NativeJavaObjectWithPrototype\"");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.stardust.autojs.rhino;
|
||||
|
||||
import org.mozilla.javascript.NativeJavaObject;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2018/4/4.
|
||||
*/
|
||||
|
||||
public class NativeJavaObjectWithPrototype extends NativeJavaObject {
|
||||
|
||||
|
||||
public NativeJavaObjectWithPrototype(Scriptable scope, Object javaObject, Class<?> staticType) {
|
||||
super(scope, javaObject, staticType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(String name, Scriptable start) {
|
||||
return super.has(name, start) || (prototype != null && prototype.has(name, start))
|
||||
|| name.equals("prototype");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String name, Scriptable start) {
|
||||
if (name.equals("prototype")) {
|
||||
return prototype;
|
||||
}
|
||||
Object o = super.get(name, start);
|
||||
if (o != Scriptable.NOT_FOUND) {
|
||||
return o;
|
||||
}
|
||||
if (prototype == null) {
|
||||
return o;
|
||||
}
|
||||
return prototype.get(name, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String name, Scriptable start, Object value) {
|
||||
if (name.equals("prototype")) {
|
||||
prototype = (Scriptable) value;
|
||||
return;
|
||||
}
|
||||
super.put(name, start, value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user