diff --git a/autojs/src/main/assets/modules/__selector__.js b/autojs/src/main/assets/modules/__selector__.js index 68c203cc..afb8739b 100644 --- a/autojs/src/main/assets/modules/__selector__.js +++ b/autojs/src/main/assets/modules/__selector__.js @@ -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(); diff --git a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java index dbeac413..b20c540a 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java @@ -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 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); - } } diff --git a/autojs/src/main/java/com/stardust/autojs/rhino/NativeJavaClassWithPrototype.java b/autojs/src/main/java/com/stardust/autojs/rhino/NativeJavaClassWithPrototype.java new file mode 100644 index 00000000..8541f020 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/rhino/NativeJavaClassWithPrototype.java @@ -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 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\""); + } + +} diff --git a/autojs/src/main/java/com/stardust/autojs/rhino/NativeJavaObjectWithPrototype.java b/autojs/src/main/java/com/stardust/autojs/rhino/NativeJavaObjectWithPrototype.java new file mode 100644 index 00000000..0a5ae184 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/rhino/NativeJavaObjectWithPrototype.java @@ -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); + } +} diff --git a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.java b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.java index a209e0a8..203410d3 100644 --- a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.java +++ b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.java @@ -54,6 +54,7 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi @Override public void onAccessibilityEvent(final AccessibilityEvent event) { + instance = this; Log.v(TAG, "onAccessibilityEvent: " + event); if (!containsAllEventTypes && !eventTypes.contains(event.getEventType())) return;