feat(ui): supports debugging
This commit is contained in:
@@ -101,6 +101,7 @@ public abstract class AutoJs {
|
||||
engine.setRuntime(createRuntime());
|
||||
return engine;
|
||||
});
|
||||
LoopBasedJavaScriptEngine.initEngine();
|
||||
mScriptEngineManager.registerEngine(AutoFileSource.ENGINE, () -> new RootAutomatorEngine(mContext));
|
||||
|
||||
}
|
||||
|
||||
@@ -86,5 +86,9 @@ public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine {
|
||||
super.init();
|
||||
}
|
||||
|
||||
public static void initEngine(){
|
||||
RhinoJavaScriptEngine.initEngine();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
1558
autojs/src/main/java/com/stardust/autojs/rhino/debug/Dim.java
Normal file
1558
autojs/src/main/java/com/stardust/autojs/rhino/debug/Dim.java
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user