feat(ui): supports debugging

This commit is contained in:
hyb1996
2018-09-07 22:26:03 +08:00
parent e5e1b567e7
commit 32805aad34
28 changed files with 2027 additions and 57 deletions

View File

@@ -101,6 +101,7 @@ public abstract class AutoJs {
engine.setRuntime(createRuntime());
return engine;
});
LoopBasedJavaScriptEngine.initEngine();
mScriptEngineManager.registerEngine(AutoFileSource.ENGINE, () -> new RootAutomatorEngine(mContext));
}

View File

@@ -86,5 +86,9 @@ public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine {
super.init();
}
public static void initEngine(){
RhinoJavaScriptEngine.initEngine();
}
}

View File

@@ -3,6 +3,7 @@ package com.stardust.autojs.engine;
import android.os.Looper;
import android.util.Log;
import com.stardust.app.GlobalAppContext;
import com.stardust.autojs.BuildConfig;
import com.stardust.autojs.rhino.AndroidContextFactory;
import com.stardust.autojs.rhino.NativeJavaClassWithPrototype;
@@ -33,6 +34,7 @@ import java.io.Reader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
@@ -43,10 +45,13 @@ import java.util.concurrent.ConcurrentHashMap;
public class RhinoJavaScriptEngine extends JavaScriptEngine {
public static final String SOURCE_NAME_INIT = "<init>";
private static final String LOG_TAG = "RhinoJavaScriptEngine";
private static int contextCount = 0;
private static StringScriptSource sInitScript;
private static final ConcurrentHashMap<Context, RhinoJavaScriptEngine> sContextEngineMap = new ConcurrentHashMap<>();
private Context mContext;
private Scriptable mScriptable;
@@ -69,7 +74,7 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
Reader reader = source.getNonNullScriptReader();
try {
reader = preprocess(reader);
return mContext.evaluateReader(mScriptable, reader, "<" + source.getName() + ">", 1, null);
return mContext.evaluateReader(mScriptable, reader, source.toString(), 1, null);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
@@ -90,6 +95,7 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
public synchronized void destroy() {
super.destroy();
Log.d(LOG_TAG, "on destroy");
sContextEngineMap.remove(getContext());
Context.exit();
contextCount--;
Log.d(LOG_TAG, "contextCount = " + contextCount);
@@ -105,7 +111,7 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
mThread = Thread.currentThread();
ScriptableObject.putProperty(mScriptable, "__engine__", this);
initRequireBuilder(mContext, mScriptable);
mContext.evaluateString(mScriptable, getInitScript().getScript(), "<init>", 1, null);
mContext.evaluateString(mScriptable, getInitScript().getScript(), SOURCE_NAME_INIT, 1, null);
}
private JavaScriptSource getInitScript() {
@@ -148,12 +154,10 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
}
public Context createContext() {
if (!ContextFactory.hasExplicitGlobal()) {
ContextFactory.initGlobal(new InterruptibleAndroidContextFactory(new File(mAndroidContext.getCacheDir(), "classes")));
}
Context context = new RhinoAndroidHelper(mAndroidContext).enterContext();
contextCount++;
setupContext(context);
sContextEngineMap.put(context, this);
return context;
}
@@ -164,6 +168,17 @@ 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);
}
private class WrapFactory extends org.mozilla.javascript.WrapFactory {

View File

@@ -3,7 +3,6 @@ package com.stardust.autojs.engine;
import android.support.annotation.CallSuper;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.runtime.exception.ScriptException;
import com.stardust.autojs.script.ScriptSource;
import java.util.Map;
@@ -14,7 +13,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* Created by Stardust on 2017/4/2.
* <p>
* <p>
* A ScriptEngine is created by {@link ScriptEngineManager#createEngine(String)} ()}, and then can be
* A ScriptEngine is created by {@link ScriptEngineManager#createEngine(String, int)} ()}, and then can be
* used to execute script with {@link ScriptEngine#execute(ScriptSource)} in the **same** thread.
* When the execution finish successfully, the engine should be destroy in the thread that created it.
* <p>

View File

@@ -4,6 +4,7 @@ import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.util.Supplier;
@@ -96,37 +97,34 @@ public class ScriptEngineManager {
@Nullable
public ScriptEngine createEngine(String name) {
public ScriptEngine createEngine(String name, int id) {
Supplier<ScriptEngine> s = mEngineSuppliers.get(name);
if (s == null) {
return null;
}
ScriptEngine engine = s.get();
engine.setId(id);
putProperties(engine);
addEngine(engine);
return engine;
}
@Nullable
public ScriptEngine createEngineOfSource(ScriptSource source) {
return createEngine(source.getEngineName());
public ScriptEngine createEngineOfSource(ScriptSource source, int id) {
return createEngine(source.getEngineName(), id);
}
@NonNull
public ScriptEngine createEngineByNameOrThrow(String name) {
ScriptEngine engine = createEngine(name);
public ScriptEngine createEngineOfSourceOrThrow(ScriptSource source, int id) {
ScriptEngine engine = createEngineOfSource(source, id);
if (engine == null)
throw new ScriptEngineFactory.EngineNotFoundException("name: " + name);
throw new ScriptEngineFactory.EngineNotFoundException("source: " + source.toString());
return engine;
}
@NonNull
public ScriptEngine createEngineOfSourceOrThrow(ScriptSource source) {
ScriptEngine engine = createEngineOfSource(source);
if (engine == null)
throw new ScriptEngineFactory.EngineNotFoundException("source: " + source.toString());
return engine;
return createEngineOfSourceOrThrow(source, ScriptExecution.NO_ID);
}
public void registerEngine(String name, Supplier<ScriptEngine> supplier) {

View File

@@ -28,8 +28,7 @@ public class RunnableScriptExecution extends ScriptExecution.AbstractScriptExecu
}
public Object execute() {
mScriptEngine = mScriptEngineManager.createEngineOfSourceOrThrow(getSource());
mScriptEngine.setId(getId());
mScriptEngine = mScriptEngineManager.createEngineOfSourceOrThrow(getSource(), getId());
return execute(mScriptEngine);
}

View File

@@ -0,0 +1,50 @@
package com.stardust.autojs.rhino.debug;
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import com.stardust.autojs.engine.RhinoJavaScriptEngine;
import com.stardust.autojs.engine.ScriptEngine;
import org.mozilla.javascript.Context;
/**
* Interface for communication between the debugger and its GUI. This
* should be implemented by the GUI.
*/
public interface DebugCallback {
/**
* Called when the source text of some script has been changed.
*/
void updateSourceText(Dim.SourceInfo sourceInfo);
/**
* Called when the interrupt loop has been entered.
*/
void enterInterrupt(Dim.StackFrame lastFrame,
String threadTitle,
String alertMessage);
/**
* Returns whether the current thread is the GUI's event thread.
* This information is required to avoid blocking the event thread
* from the debugger.
*/
boolean isGuiEventThread();
/**
* Processes the next GUI event. This manual pumping of GUI events
* is necessary when the GUI event thread itself has been stopped.
*/
void dispatchNextGuiEvent() throws InterruptedException;
/**
*
* Returns whether the debugger should attach to this engine or not.
*/
boolean shouldAttachDebugger(RhinoJavaScriptEngine engine);
}

File diff suppressed because it is too large Load Diff