diff --git a/autojs/src/main/assets/modules/__bridges__.js b/autojs/src/main/assets/modules/__bridges__.js index 015d3e2c..0a06cf4e 100644 --- a/autojs/src/main/assets/modules/__bridges__.js +++ b/autojs/src/main/assets/modules/__bridges__.js @@ -42,23 +42,6 @@ function wrap(value){ return value; } -bridges.asArray = function (list) { - var arr = []; - for (var i = 0; i < list.size(); i++) { - arr.push(list.get(i)); - } - for (var key in list) { - if (typeof (key) == 'number') - continue; - var v = list[key]; - if (typeof (v) == 'function') { - arr[key] = v.bind(list); - } else { - arr[key] = v; - } - } - return arr; -}; bridges.toArray = function (iterable) { var iterator = iterable.iterator(); var arr = []; diff --git a/autojs/src/main/java/com/stardust/autojs/AutoJs.java b/autojs/src/main/java/com/stardust/autojs/AutoJs.java index a4a913ec..4669d431 100644 --- a/autojs/src/main/java/com/stardust/autojs/AutoJs.java +++ b/autojs/src/main/java/com/stardust/autojs/AutoJs.java @@ -13,7 +13,6 @@ import com.stardust.app.SimpleActivityLifecycleCallbacks; import com.stardust.autojs.core.accessibility.AccessibilityBridge; import com.stardust.autojs.core.console.GlobalStardustConsole; import com.stardust.autojs.core.console.StardustConsole; -import com.stardust.autojs.core.image.OpenCVHelper; import com.stardust.autojs.core.image.capture.ScreenCaptureRequestActivity; import com.stardust.autojs.core.image.capture.ScreenCaptureRequester; import com.stardust.autojs.core.record.accessibility.AccessibilityActionRecorder; @@ -21,10 +20,10 @@ import com.stardust.autojs.core.util.Shell; import com.stardust.autojs.engine.LoopBasedJavaScriptEngine; import com.stardust.autojs.engine.RootAutomatorEngine; import com.stardust.autojs.engine.ScriptEngineManager; +import com.stardust.autojs.rhino.InterruptibleAndroidContextFactory; import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.accessibility.AccessibilityConfig; import com.stardust.autojs.runtime.api.AppUtils; -import com.stardust.autojs.runtime.api.Console; import com.stardust.autojs.script.AutoFileSource; import com.stardust.autojs.script.JavaScriptSource; import com.stardust.util.ScreenMetrics; @@ -34,8 +33,10 @@ import com.stardust.view.accessibility.AccessibilityNotificationObserver; import com.stardust.view.accessibility.AccessibilityService; import com.stardust.view.accessibility.LayoutInspector; -import org.opencv.android.BaseLoaderCallback; -import org.opencv.android.OpenCVLoader; +import org.mozilla.javascript.ContextFactory; +import org.mozilla.javascript.Scriptable; + +import java.io.File; /** * Created by Stardust on 2017/11/29. @@ -105,11 +106,15 @@ public abstract class AutoJs { engine.setRuntime(createRuntime()); return engine; }); - LoopBasedJavaScriptEngine.initEngine(); + initContextFactory(); mScriptEngineManager.registerEngine(AutoFileSource.ENGINE, () -> new RootAutomatorEngine(mContext)); } + protected void initContextFactory() { + ContextFactory.initGlobal(new InterruptibleAndroidContextFactory(new File(mContext.getCacheDir(), "classes"))); + } + protected ScriptRuntime createRuntime() { return new ScriptRuntime.Builder() .setConsole(new StardustConsole(mUiHandler, mGlobalConsole)) diff --git a/autojs/src/main/java/com/stardust/autojs/core/looper/MainThreadProxy.java b/autojs/src/main/java/com/stardust/autojs/core/looper/MainThreadProxy.java index a0685154..eee76c62 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/looper/MainThreadProxy.java +++ b/autojs/src/main/java/com/stardust/autojs/core/looper/MainThreadProxy.java @@ -1,7 +1,5 @@ package com.stardust.autojs.core.looper; -import android.content.pm.PackageManager; - import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.lang.ThreadCompat; diff --git a/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java b/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java index 70a685f6..70d8cd79 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java +++ b/autojs/src/main/java/com/stardust/autojs/core/looper/TimerThread.java @@ -4,16 +4,12 @@ import android.os.Handler; import android.os.Looper; import android.support.annotation.CallSuper; -import com.stardust.autojs.ScriptEngineService; import com.stardust.autojs.engine.RhinoJavaScriptEngine; -import com.stardust.autojs.runtime.ScriptBridges; import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.concurrent.VolatileBox; import com.stardust.lang.ThreadCompat; -import org.mozilla.javascript.NativeArray; - import java.util.concurrent.ConcurrentHashMap; /** @@ -43,6 +39,7 @@ public class TimerThread extends ThreadCompat { mRuntime.loopers.prepare(); mTimer = new Timer(mRuntime, mMaxCallbackUptimeMillisForAllThreads); sTimerMap.put(Thread.currentThread(), mTimer); + ((RhinoJavaScriptEngine) mRuntime.engines.myEngine()).enterContext(); notifyRunning(); new Handler().post(mTarget); try { @@ -54,6 +51,7 @@ public class TimerThread extends ThreadCompat { } finally { onExit(); mTimer = null; + org.mozilla.javascript.Context.exit(); sTimerMap.remove(Thread.currentThread(), mTimer); } } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/ViewExtras.java b/autojs/src/main/java/com/stardust/autojs/core/ui/ViewExtras.java index 7cf5ca84..d63bc945 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/ViewExtras.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/ViewExtras.java @@ -1,5 +1,6 @@ package com.stardust.autojs.core.ui; +import android.util.Log; import android.view.View; import com.stardust.autojs.R; @@ -13,6 +14,7 @@ import org.mozilla.javascript.Scriptable; public class ViewExtras { + private static final String LOG_TAG = "ViewExtras"; private NativeView mNativeView; private ViewAttributes mViewAttributes; @@ -20,6 +22,7 @@ public class ViewExtras { public static ViewExtras get(View view) { ViewExtras extras; Object tag = view.getTag(R.id.view_tag_view_extras); + Log.d(LOG_TAG, "view = " + view + ", tag = " + tag); if (tag instanceof ViewExtras) { extras = (ViewExtras) tag; } else { @@ -34,7 +37,7 @@ public class ViewExtras { ViewExtras extras = get(view); ViewAttributes attributes = extras.getViewAttributes(); if (attributes == null) { - attributes = ViewAttributesFactory.create(parser, view); + attributes = ViewAttributesFactory.create(parser, view); extras.setViewAttributes(attributes); } return attributes; diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ResourceParser.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ResourceParser.java index 0c6b3f62..1d444169 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ResourceParser.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/ResourceParser.java @@ -11,7 +11,6 @@ public class ResourceParser { private final Drawables mDrawables; - public ResourceParser(Drawables drawables) { mDrawables = drawables; } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTabLayout.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTabLayout.java index 07551f03..9ae92acd 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTabLayout.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsTabLayout.java @@ -25,8 +25,4 @@ public class JsTabLayout extends TabLayout { public JsTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } - - public void setupWithViewPager(NativeObject viewPager) { - setupWithViewPager(UI.unwrapJsViewObject(viewPager, ViewPager.class)); - } } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsToolbar.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsToolbar.java index ec7c4828..5c9fe28d 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsToolbar.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/JsToolbar.java @@ -8,12 +8,8 @@ import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.widget.Toolbar; import android.util.AttributeSet; -import android.util.Log; import com.stardust.autojs.R; -import com.stardust.autojs.runtime.api.UI; - -import org.mozilla.javascript.NativeObject; public class JsToolbar extends Toolbar { @@ -47,9 +43,4 @@ public class JsToolbar extends Toolbar { } return (Activity) context; } - - public void setupWithDrawer(NativeObject object) { - setupWithDrawer(UI.unwrapJsViewObject(object, DrawerLayout.class)); - } - } diff --git a/autojs/src/main/java/com/stardust/autojs/engine/LoopBasedJavaScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/LoopBasedJavaScriptEngine.java index fed1877b..6f1dee1b 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/LoopBasedJavaScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/LoopBasedJavaScriptEngine.java @@ -88,9 +88,5 @@ public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine { super.init(); } - public static void initEngine(){ - RhinoJavaScriptEngine.initEngine(); - } - } 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 a7dc7563..49131f9c 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java @@ -1,25 +1,23 @@ package com.stardust.autojs.engine; -import android.os.Looper; import android.util.Log; import android.view.View; -import com.stardust.app.GlobalAppContext; import com.stardust.autojs.BuildConfig; import com.stardust.autojs.core.ui.ViewExtras; -import com.stardust.autojs.core.ui.nativeview.NativeView; -import com.stardust.autojs.rhino.AndroidContextFactory; import com.stardust.autojs.rhino.RhinoAndroidHelper; -import com.stardust.autojs.runtime.exception.ScriptInterruptedException; +import com.stardust.autojs.rhino.TopLevelScope; +import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.script.JavaScriptSource; import com.stardust.autojs.script.StringScriptSource; +import com.stardust.automator.UiObject; import com.stardust.automator.UiObjectCollection; import com.stardust.pio.PFiles; import com.stardust.pio.UncheckedIOException; import org.mozilla.javascript.Context; -import org.mozilla.javascript.ContextFactory; -import org.mozilla.javascript.ImporterTopLevel; +import org.mozilla.javascript.NativeArray; +import org.mozilla.javascript.NativeJavaObject; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.commonjs.module.RequireBuilder; @@ -28,9 +26,10 @@ import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptPr import java.io.File; import java.io.IOException; import java.io.Reader; +import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.Locale; -import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; /** @@ -44,18 +43,17 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { private static final String LOG_TAG = "RhinoJavaScriptEngine"; private static final String MODULES_PATH = "modules"; - private static int contextCount = 0; private static StringScriptSource sInitScript; private static final ConcurrentHashMap sContextEngineMap = new ConcurrentHashMap<>(); private Context mContext; - private Scriptable mScriptable; + private TopLevelScope mScriptable; private Thread mThread; private android.content.Context mAndroidContext; public RhinoJavaScriptEngine(android.content.Context context) { mAndroidContext = context; - mContext = createContext(); + mContext = enterContext(); mScriptable = createScope(mContext); } @@ -92,8 +90,6 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { Log.d(LOG_TAG, "on destroy"); sContextEngineMap.remove(getContext()); Context.exit(); - contextCount--; - Log.d(LOG_TAG, "contextCount = " + contextCount); } public Thread getThread() { @@ -142,15 +138,14 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { return mScriptable; } - protected Scriptable createScope(Context context) { - ImporterTopLevel importerTopLevel = new ImporterTopLevel(); - importerTopLevel.initStandardObjects(context, false); - return importerTopLevel; + protected TopLevelScope createScope(Context context) { + TopLevelScope topLevelScope = new TopLevelScope(); + topLevelScope.initStandardObjects(context, false); + return topLevelScope; } - public Context createContext() { + public Context enterContext() { Context context = new RhinoAndroidHelper(mAndroidContext).enterContext(); - contextCount++; setupContext(context); sContextEngineMap.put(context, this); return context; @@ -163,12 +158,6 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { context.setWrapFactory(new WrapFactory()); } - public static void initEngine() { - if (!ContextFactory.hasExplicitGlobal()) { - android.content.Context context = GlobalAppContext.get(); - ContextFactory.initGlobal(new InterruptibleAndroidContextFactory(new File(context.getCacheDir(), "classes"))); - } - } public static RhinoJavaScriptEngine getEngineOfContext(Context context) { return sContextEngineMap.get(context); @@ -178,43 +167,34 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { @Override public Object wrap(Context cx, Scriptable scope, Object obj, Class staticType) { + Object result; if (obj instanceof String) { - return getRuntime().bridges.toString(obj.toString()); + result = getRuntime().bridges.toString(obj.toString()); + } else if (staticType == UiObjectCollection.class) { + UiObjectCollection collection = (UiObjectCollection) obj; + Object[] array = new Object[collection.size()]; + for (int i = 0; i < array.length; i++) { + array[i] = wrapAsJavaObject(cx, scope, collection.get(i), UiObject.class); + } + NativeArray nativeArray = new NativeArray(array); + nativeArray.setPrototype(new NativeJavaObject(scope, collection, staticType)); + result = nativeArray; + } else { + result = super.wrap(cx, scope, obj, staticType); } - if (staticType == UiObjectCollection.class) { - return getRuntime().bridges.asArray(obj); - } - return super.wrap(cx, scope, obj, staticType); + return result; } @Override public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject, Class staticType) { + Scriptable result; if (javaObject instanceof View) { - return ViewExtras.getNativeView(scope, (View) javaObject, staticType, getRuntime()); + result = ViewExtras.getNativeView(scope, (View) javaObject, staticType, getRuntime()); + } else { + result = super.wrapAsJavaObject(cx, scope, javaObject, staticType); } - return super.wrapAsJavaObject(cx, scope, javaObject, staticType); - } - } - - private static class InterruptibleAndroidContextFactory extends AndroidContextFactory { - - public InterruptibleAndroidContextFactory(File cacheDirectory) { - super(cacheDirectory); - } - - - @Override - protected void observeInstructionCount(Context cx, int instructionCount) { - if (Thread.currentThread().isInterrupted() && Looper.myLooper() != Looper.getMainLooper()) { - throw new ScriptInterruptedException(); - } - } - - @Override - protected Context makeContext() { - Context cx = super.makeContext(); - cx.setInstructionObserverThreshold(10000); - return cx; + //Log.d(LOG_TAG, "wrapAsJavaObject: java = " + javaObject + ", result = " + result + ", scope = " + scope); + return result; } } diff --git a/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java b/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java index 82132b67..99277160 100644 --- a/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java +++ b/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java @@ -230,10 +230,6 @@ public class ScriptExecuteActivity extends AppCompatActivity { } } - public void setSupportActionBar(@Nullable NativeObject toolbar) { - super.setSupportActionBar(UI.unwrapJsViewObject(toolbar, Toolbar.class)); - } - private static class ActivityScriptExecution extends ScriptExecution.AbstractScriptExecution { private ScriptEngine mScriptEngine; diff --git a/autojs/src/main/java/com/stardust/autojs/rhino/InterruptibleAndroidContextFactory.java b/autojs/src/main/java/com/stardust/autojs/rhino/InterruptibleAndroidContextFactory.java new file mode 100644 index 00000000..b3daa1e4 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/rhino/InterruptibleAndroidContextFactory.java @@ -0,0 +1,55 @@ +package com.stardust.autojs.rhino; + +import android.os.Looper; +import android.util.Log; + +import com.stardust.autojs.runtime.exception.ScriptInterruptedException; + +import org.mozilla.javascript.Context; + +import java.io.File; +import java.util.concurrent.atomic.AtomicInteger; + +public class InterruptibleAndroidContextFactory extends AndroidContextFactory { + + private AtomicInteger mContextCount = new AtomicInteger(); + private static final String LOG_TAG = "ContextFactory"; + + /** + * Create a new factory. It will cache generated code in the given directory + * + * @param cacheDirectory the cache directory + */ + public InterruptibleAndroidContextFactory(File cacheDirectory) { + super(cacheDirectory); + } + + @Override + protected void observeInstructionCount(Context cx, int instructionCount) { + if (Thread.currentThread().isInterrupted() && Looper.myLooper() != Looper.getMainLooper()) { + throw new ScriptInterruptedException(); + } + } + + @Override + protected Context makeContext() { + Context cx = super.makeContext(); + cx.setInstructionObserverThreshold(10000); + return cx; + } + + @Override + protected void onContextCreated(Context cx) { + super.onContextCreated(cx); + int i = mContextCount.incrementAndGet(); + Log.d(LOG_TAG, "onContextCreated: count = " + i); + } + + @Override + protected void onContextReleased(Context cx) { + super.onContextReleased(cx); + int i = mContextCount.decrementAndGet(); + Log.d(LOG_TAG, "onContextReleased: count = " + i); + } + +} diff --git a/autojs/src/main/java/com/stardust/autojs/rhino/TopLevelScope.java b/autojs/src/main/java/com/stardust/autojs/rhino/TopLevelScope.java new file mode 100644 index 00000000..338faade --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/rhino/TopLevelScope.java @@ -0,0 +1,6 @@ +package com.stardust.autojs.rhino; + +import org.mozilla.javascript.ImporterTopLevel; + +public class TopLevelScope extends ImporterTopLevel { +} diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java index 4d0ea4c1..d00cedad 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptBridges.java @@ -19,8 +19,6 @@ public class ScriptBridges { Object toArray(Iterable o); - Object asArray(Object o); - Object toString(Object obj); } @@ -47,12 +45,6 @@ public class ScriptBridges { return mBridges.toArray(c); } - public Object asArray(Object o) { - checkBridges(); - return mBridges.asArray(o); - } - - public Object toString(Object obj) { checkBridges(); return mBridges.toString(obj); diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Engines.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Engines.java index 0e5f6972..78fbaeab 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Engines.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Engines.java @@ -1,20 +1,14 @@ package com.stardust.autojs.runtime.api; -import android.widget.RadioGroup; - import com.stardust.autojs.ScriptEngineService; -import com.stardust.autojs.engine.ScriptEngine; +import com.stardust.autojs.engine.JavaScriptEngine; import com.stardust.autojs.execution.ExecutionConfig; import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.script.AutoFileSource; import com.stardust.autojs.script.JavaScriptFileSource; -import com.stardust.autojs.script.JavaScriptSource; import com.stardust.autojs.script.StringScriptSource; -import java.util.ArrayList; -import java.util.List; - /** * Created by Stardust on 2017/8/4. */ @@ -22,7 +16,7 @@ import java.util.List; public class Engines { private ScriptEngineService mEngineService; - private ScriptEngine mScriptEngine; + private JavaScriptEngine mScriptEngine; private ScriptRuntime mScriptRuntime; public Engines(ScriptEngineService engineService, ScriptRuntime scriptRuntime) { @@ -55,13 +49,13 @@ public class Engines { } - public void setCurrentEngine(ScriptEngine engine) { + public void setCurrentEngine(JavaScriptEngine engine) { if (mScriptEngine != null) throw new IllegalStateException(); mScriptEngine = engine; } - public ScriptEngine myEngine() { + public JavaScriptEngine myEngine() { return mScriptEngine; } } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Files.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Files.java index 25ba3fbf..c69fafb8 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Files.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Files.java @@ -1,6 +1,5 @@ package com.stardust.autojs.runtime.api; -import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.pio.PFileInterface; import com.stardust.pio.PFiles; @@ -22,6 +21,7 @@ public class Files { mRuntime = runtime; } + // FIXME: 2018/10/16 is not correct in sub-directory? public String path(String relativePath) { String cwd = cwd(); if (cwd == null || relativePath == null || relativePath.startsWith("/")) diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Threads.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Threads.java index d1a1428c..b05df963 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Threads.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Threads.java @@ -4,7 +4,6 @@ import android.support.annotation.NonNull; import com.stardust.autojs.core.looper.MainThreadProxy; import com.stardust.autojs.core.looper.TimerThread; -import com.stardust.autojs.engine.RhinoJavaScriptEngine; import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.concurrent.VolatileDispose; @@ -56,10 +55,7 @@ public class Threads { @NonNull private TimerThread createThread(Runnable runnable) { return new TimerThread(mRuntime, mRuntime.timers.getMaxCallbackUptimeMillisForAllThreads(), - () -> { - ((RhinoJavaScriptEngine) mRuntime.engines.myEngine()).createContext(); - runnable.run(); - } + runnable ) { @Override protected void onExit() { diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java index 65679930..53e3b4ee 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java @@ -63,21 +63,6 @@ public class UI extends ProxyObject { return mResourceParser; } - @SuppressWarnings("unchecked") - public static V unwrapJsViewObject(@Nullable NativeObject object, Class c) { - if (object == null) - return null; - if (!object.containsKey("__javaObject__")) { - throw new ClassCastException("object " + object + " cannot be cast to " + c.getName()); - } - Object view = object.get("__javaObject__"); - if (!c.isInstance(view)) { - throw new ClassCastException("object " + object + " cannot be cast to " + c.getName()); - } - return (V) view; - - } - public Object getBindingContext() { return mProperties.get("bindingContext"); } diff --git a/autojs/src/main/java/org/mozilla/javascript/ContextWrapper.java b/autojs/src/main/java/org/mozilla/javascript/ContextWrapper.java new file mode 100644 index 00000000..3f7b60a8 --- /dev/null +++ b/autojs/src/main/java/org/mozilla/javascript/ContextWrapper.java @@ -0,0 +1,238 @@ +package org.mozilla.javascript; + +import org.mozilla.javascript.debug.DebuggableScript; +import org.mozilla.javascript.xml.XMLLib; + +public class ContextWrapper extends Context { + private final Context mContext; + + public ContextWrapper(Context context) { + mContext = context; + } + + public static Context getCurrentContext() { + return Context.getCurrentContext(); + } + + public static Context enter() { + return Context.enter(); + } + + @Deprecated + public static Context enter(Context cx) { + return Context.enter(cx); + } + + public static void exit() { + Context.exit(); + } + + @Deprecated + public static Object call(ContextAction action) { + return Context.call(action); + } + + public static Object call(ContextFactory factory, Callable callable, Scriptable scope, Scriptable thisObj, Object[] args) { + return Context.call(factory, callable, scope, thisObj, args); + } + + @Deprecated + public static void addContextListener(ContextListener listener) { + Context.addContextListener(listener); + } + + @Deprecated + public static void removeContextListener(ContextListener listener) { + Context.removeContextListener(listener); + } + + @Override + public void setLanguageVersion(int version) { + mContext.setLanguageVersion(version); + } + + public static boolean isValidLanguageVersion(int version) { + return Context.isValidLanguageVersion(version); + } + + public static void checkLanguageVersion(int version) { + Context.checkLanguageVersion(version); + } + + public static void reportWarning(String message, String sourceName, int lineno, String lineSource, int lineOffset) { + Context.reportWarning(message, sourceName, lineno, lineSource, lineOffset); + } + + public static void reportWarning(String message) { + Context.reportWarning(message); + } + + public static void reportWarning(String message, Throwable t) { + Context.reportWarning(message, t); + } + + public static void reportError(String message, String sourceName, int lineno, String lineSource, int lineOffset) { + Context.reportError(message, sourceName, lineno, lineSource, lineOffset); + } + + public static void reportError(String message) { + Context.reportError(message); + } + + public static EvaluatorException reportRuntimeError(String message, String sourceName, int lineno, String lineSource, int lineOffset) { + return Context.reportRuntimeError(message, sourceName, lineno, lineSource, lineOffset); + } + + public static EvaluatorException reportRuntimeError(String message) { + return Context.reportRuntimeError(message); + } + + @Override + public ScriptableObject initStandardObjects(ScriptableObject scope, boolean sealed) { + return mContext.initStandardObjects(scope, sealed); + } + + @Override + public ScriptableObject initSafeStandardObjects(ScriptableObject scope, boolean sealed) { + return mContext.initSafeStandardObjects(scope, sealed); + } + + public static Object getUndefinedValue() { + return Context.getUndefinedValue(); + } + + @Override + public Object executeScriptWithContinuations(Script script, Scriptable scope) throws ContinuationPending { + return mContext.executeScriptWithContinuations(script, scope); + } + + @Override + public Object callFunctionWithContinuations(Callable function, Scriptable scope, Object[] args) throws ContinuationPending { + return mContext.callFunctionWithContinuations(function, scope, args); + } + + @Override + public ContinuationPending captureContinuation() { + return mContext.captureContinuation(); + } + + @Override + public Object resumeContinuation(Object continuation, Scriptable scope, Object functionResult) throws ContinuationPending { + return mContext.resumeContinuation(continuation, scope, functionResult); + } + + @Override + public Scriptable newObject(Scriptable scope) { + return mContext.newObject(scope); + } + + @Override + public Scriptable newObject(Scriptable scope, String constructorName) { + return mContext.newObject(scope, constructorName); + } + + @Override + public Scriptable newObject(Scriptable scope, String constructorName, Object[] args) { + return mContext.newObject(scope, constructorName, args); + } + + @Override + public Scriptable newArray(Scriptable scope, int length) { + return mContext.newArray(scope, length); + } + + @Override + public Scriptable newArray(Scriptable scope, Object[] elements) { + return mContext.newArray(scope, elements); + } + + public static boolean toBoolean(Object value) { + return Context.toBoolean(value); + } + + public static double toNumber(Object value) { + return Context.toNumber(value); + } + + public static String toString(Object value) { + return Context.toString(value); + } + + public static Scriptable toObject(Object value, Scriptable scope) { + return Context.toObject(value, scope); + } + + @Deprecated + public static Scriptable toObject(Object value, Scriptable scope, Class staticType) { + return Context.toObject(value, scope, staticType); + } + + public static Object javaToJS(Object value, Scriptable scope) { + return Context.javaToJS(value, scope); + } + + public static Object jsToJava(Object value, Class desiredType) throws EvaluatorException { + return Context.jsToJava(value, desiredType); + } + + @Deprecated + public static Object toType(Object value, Class desiredType) throws IllegalArgumentException { + return Context.toType(value, desiredType); + } + + public static RuntimeException throwAsScriptRuntimeEx(Throwable e) { + return Context.throwAsScriptRuntimeEx(e); + } + + public static boolean isValidOptimizationLevel(int optimizationLevel) { + return Context.isValidOptimizationLevel(optimizationLevel); + } + + public static void checkOptimizationLevel(int optimizationLevel) { + Context.checkOptimizationLevel(optimizationLevel); + } + + @Deprecated + public static void setCachingEnabled(boolean cachingEnabled) { + Context.setCachingEnabled(cachingEnabled); + } + + public static DebuggableScript getDebuggableView(Script script) { + return Context.getDebuggableView(script); + } + + @Override + public boolean hasFeature(int featureIndex) { + return mContext.hasFeature(featureIndex); + } + + @Override + public XMLLib.Factory getE4xImplementationFactory() { + return mContext.getE4xImplementationFactory(); + } + + @Override + public void setGenerateObserverCount(boolean generateObserverCount) { + mContext.setGenerateObserverCount(generateObserverCount); + } + + @Override + public void observeInstructionCount(int instructionCount) { + mContext.observeInstructionCount(instructionCount); + } + + @Override + public GeneratedClassLoader createClassLoader(ClassLoader parent) { + return mContext.createClassLoader(parent); + } + + @Override + public void addActivationName(String name) { + mContext.addActivationName(name); + } + + @Override + public void removeActivationName(String name) { + mContext.removeActivationName(name); + } +} diff --git a/autojs/src/main/java/org/mozilla/javascript/VMBridge_custom.java b/autojs/src/main/java/org/mozilla/javascript/VMBridge_custom.java index 521b1084..bcd69bc0 100644 --- a/autojs/src/main/java/org/mozilla/javascript/VMBridge_custom.java +++ b/autojs/src/main/java/org/mozilla/javascript/VMBridge_custom.java @@ -3,6 +3,8 @@ package org.mozilla.javascript; import android.os.Looper; import android.util.Log; +import com.stardust.autojs.engine.RhinoJavaScriptEngine; + import org.mozilla.javascript.jdk15.VMBridge_jdk15; import java.lang.reflect.Constructor; @@ -19,6 +21,9 @@ public class VMBridge_custom extends VMBridge_jdk15 { @Override protected Object newInterfaceProxy(Object proxyHelper, ContextFactory cf, InterfaceAdapter adapter, Object target, Scriptable topScope) { + Context context = Context.getCurrentContext(); + InterfaceAdapterWrapper adapterWrapper = new InterfaceAdapterWrapper(adapter, context); + RhinoJavaScriptEngine engine = RhinoJavaScriptEngine.getEngineOfContext(context); // --- The following code is copied from super class -- Constructor c = (Constructor) proxyHelper; InvocationHandler handler = (proxy, method, args) -> { @@ -43,25 +48,19 @@ public class VMBridge_custom extends VMBridge_jdk15 { // If so, catch any exception of invoking // Because an exception on ui thread will cause the whole app to crash try { - Object result = adapter.invoke(cf, target, topScope, proxy, method, args); + Object result = adapterWrapper.invoke(cf, target, topScope, proxy, method, args); return castReturnValue(method, result); } catch (Exception e) { e.printStackTrace(); // notify the script thread to exit - Object jsRuntime = topScope.get("runtime", null); - Log.d(LOG_TAG, "jsRuntime = " + jsRuntime); - if (jsRuntime instanceof NativeJavaObject) { - Object runtime = ((NativeJavaObject) jsRuntime).unwrap(); - Log.d(LOG_TAG, "runtime = " + runtime); - if(runtime instanceof com.stardust.autojs.runtime.ScriptRuntime){ - ((com.stardust.autojs.runtime.ScriptRuntime) runtime).exit(e); - } - } + com.stardust.autojs.runtime.ScriptRuntime runtime = engine.getRuntime(); + Log.d(LOG_TAG, "runtime = " + runtime); + runtime.exit(e); // even if we caught the exception, we must return a value to for the method call. return defaultValue(method.getReturnType()); } } else { - return castReturnValue(method, adapter.invoke(cf, target, topScope, proxy, method, args)); + return castReturnValue(method, adapterWrapper.invoke(cf, target, topScope, proxy, method, args)); } }; @@ -115,4 +114,36 @@ public class VMBridge_custom extends VMBridge_jdk15 { } return null; } + + private class InterfaceAdapterWrapper { + + private final InterfaceAdapter mInterfaceAdapter; + private final Context mCallerContext; + + private InterfaceAdapterWrapper(InterfaceAdapter interfaceAdapter, Context callerContext) { + mInterfaceAdapter = interfaceAdapter; + mCallerContext = callerContext; + } + + public Object invoke(ContextFactory cf, Object target, Scriptable topScope, Object thisObject, Method method, Object[] args) { + ContextAction action = cx -> invokeImpl(cx, target, topScope, thisObject, method, args); + return call(cf, action); + } + + private Object call(ContextFactory cf, ContextAction action) { + Context cx = Context.enter(null, cf); + //TODO null check + cx.setWrapFactory(mCallerContext.getWrapFactory()); + try { + return action.run(cx); + } finally { + Context.exit(); + } + } + + + public Object invokeImpl(Context cx, Object target, Scriptable topScope, Object thisObject, Method method, Object[] args) { + return mInterfaceAdapter.invokeImpl(cx, target, topScope, thisObject, method, args); + } + } } diff --git a/automator/src/main/java/com/stardust/automator/UiGlobalSelector.java b/automator/src/main/java/com/stardust/automator/UiGlobalSelector.java index f05508ca..59668277 100644 --- a/automator/src/main/java/com/stardust/automator/UiGlobalSelector.java +++ b/automator/src/main/java/com/stardust/automator/UiGlobalSelector.java @@ -446,7 +446,9 @@ public class UiGlobalSelector { for (ListFilter filter : mFilters) { str.append(filter.toString()).append("."); } - str.deleteCharAt(str.length() - 1); + if(str.length() > 0){ + str.deleteCharAt(str.length() - 1); + } return str.toString(); } } diff --git a/automator/src/main/java/com/stardust/automator/UiObjectCollection.java b/automator/src/main/java/com/stardust/automator/UiObjectCollection.java index 1435a356..5b7b60f3 100644 --- a/automator/src/main/java/com/stardust/automator/UiObjectCollection.java +++ b/automator/src/main/java/com/stardust/automator/UiObjectCollection.java @@ -42,7 +42,7 @@ public class UiObjectCollection { } public UiObject[] toArray(){ - return mNodes.toArray(new UiObject[mNodes.size()]); + return mNodes.toArray(new UiObject[0]); } public boolean performAction(int action) { diff --git a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityInfoProvider.java b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityInfoProvider.java index 8858cfda..4851ee3b 100644 --- a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityInfoProvider.java +++ b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityInfoProvider.java @@ -60,7 +60,7 @@ public class AccessibilityInfoProvider implements AccessibilityDelegate { return; try { ComponentName componentName = new ComponentName(latestPackageStr, latestClassStr); - mLatestActivity = mPackageManager.getActivityInfo(componentName, 0).name; + mLatestActivity = mPackageManager.getActivityInfo(componentName, PackageManager.MATCH_DEFAULT_ONLY).name; } catch (PackageManager.NameNotFoundException ignored) { return; } diff --git a/common/release/output.json b/common/release/output.json index 558cdd3f..9ad8b669 100644 --- a/common/release/output.json +++ b/common/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":430,"versionName":"4.0.4 Alpha","enabled":true,"outputFile":"commonRelease-4.0.4 Alpha.apk","fullName":"commonRelease","baseName":"common-release"},"path":"commonRelease-4.0.4 Alpha.apk","properties":{}}] \ No newline at end of file +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":431,"versionName":"4.0.4 Alpha2","enabled":true,"outputFile":"commonRelease-4.0.4 Alpha2.apk","fullName":"commonRelease","baseName":"common-release"},"path":"commonRelease-4.0.4 Alpha2.apk","properties":{}}] \ No newline at end of file diff --git a/project-versions.json b/project-versions.json index 25349cea..e21a0e93 100644 --- a/project-versions.json +++ b/project-versions.json @@ -1,6 +1,6 @@ { - "appVersionCode": 430, - "appVersionName": "4.0.4 Alpha", + "appVersionCode": 431, + "appVersionName": "4.0.4 Alpha2", "target": 28, "mini": 17, "compile": 28,