feat(ui): fix debug mode exception on orientation change

This commit is contained in:
hyb1996
2018-09-08 01:53:51 +08:00
parent 32805aad34
commit c56157d8da
13 changed files with 127 additions and 40 deletions

View File

@@ -73,6 +73,7 @@
<activity <activity
android:name=".ui.edit.EditActivity_" android:name=".ui.edit.EditActivity_"
android:configChanges="orientation|screenSize"
android:multiprocess="true" android:multiprocess="true"
android:theme="@style/EditorTheme"> android:theme="@style/EditorTheme">
</activity> </activity>
@@ -81,7 +82,10 @@
android:name=".ui.settings.SettingsActivity_" android:name=".ui.settings.SettingsActivity_"
android:theme="@style/AppTheme.Settings"/> android:theme="@style/AppTheme.Settings"/>
<activity android:name=".ui.error.ErrorReportActivity"/> <activity android:name=".ui.error.ErrorReportActivity"/>
<activity android:name=".external.tasker.TaskerScriptEditActivity_"/> <activity
android:name=".external.tasker.TaskerScriptEditActivity_"
android:configChanges="orientation|screenSize"
/>
<activity android:name=".ui.edit.ViewSampleActivity"/> <activity android:name=".ui.edit.ViewSampleActivity"/>
<activity <activity
android:name=".ui.user.LoginActivity_" android:name=".ui.user.LoginActivity_"

View File

@@ -273,7 +273,10 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
private void initNormalToolbar() { private void initNormalToolbar() {
mNormalToolbar.setOnMenuItemClickListener(this); mNormalToolbar.setOnMenuItemClickListener(this);
showNormalToolbar(); Fragment fragment = getActivity().getSupportFragmentManager().findFragmentById(R.id.toolbar_menu);
if(fragment == null){
showNormalToolbar();
}
} }
private void setUpFunctionsKeyboard() { private void setUpFunctionsKeyboard() {
@@ -427,7 +430,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
private void showNormalToolbar() { private void showNormalToolbar() {
getActivity().getSupportFragmentManager().beginTransaction() getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.toolbar_menu, mNormalToolbar) .replace(R.id.toolbar_menu, mNormalToolbar)
.commit(); .commitAllowingStateLoss();
} }
FragmentActivity getActivity() { FragmentActivity getActivity() {
@@ -618,6 +621,11 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
return mScriptExecutionId; return mScriptExecutionId;
} }
@Nullable
public ScriptExecution getScriptExecution(){
return AutoJs.getInstance().getScriptEngineService().getScriptExecution(mScriptExecutionId);
}
@Nullable @Nullable
@Override @Override
protected Parcelable onSaveInstanceState() { protected Parcelable onSaveInstanceState() {

View File

@@ -22,6 +22,8 @@ import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v7.widget.AppCompatEditText; import android.support.v7.widget.AppCompatEditText;
import android.text.Editable; import android.text.Editable;
import android.text.Layout; import android.text.Layout;
@@ -30,14 +32,17 @@ import android.util.Log;
import android.util.TimingLogger; import android.util.TimingLogger;
import android.view.Gravity; import android.view.Gravity;
import org.autojs.autojs.R;
import org.autojs.autojs.ui.edit.theme.Theme; import org.autojs.autojs.ui.edit.theme.Theme;
import org.autojs.autojs.ui.edit.theme.TokenMapping; import org.autojs.autojs.ui.edit.theme.TokenMapping;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.util.ClipboardUtil; import com.stardust.util.ClipboardUtil;
import com.stardust.util.TextUtils; import com.stardust.util.TextUtils;
import org.mozilla.javascript.Token; import org.mozilla.javascript.Token;
import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import static org.autojs.autojs.ui.edit.editor.BracketMatching.UNMATCHED_BRACKET; import static org.autojs.autojs.ui.edit.editor.BracketMatching.UNMATCHED_BRACKET;
@@ -137,12 +142,12 @@ public class CodeEditText extends AppCompatEditText {
private void drawLineHighlights(Canvas canvas) { private void drawLineHighlights(Canvas canvas) {
int currentLine = getCurrentLine(); int currentLine = getCurrentLine();
int debugHighlightLine = mDebuggingLine; int debugHighlightLine = mDebuggingLine;
if(debugHighlightLine != currentLine){ if (debugHighlightLine != currentLine) {
//绘制当前行高亮 //绘制当前行高亮
mLineHighlightPaint.setColor(mTheme.getLineHighlightBackgroundColor()); mLineHighlightPaint.setColor(mTheme.getLineHighlightBackgroundColor());
drawLineHighlight(canvas, mLineHighlightPaint, getCurrentLine()); drawLineHighlight(canvas, mLineHighlightPaint, getCurrentLine());
} }
if(debugHighlightLine != -1){ if (debugHighlightLine != -1) {
mLineHighlightPaint.setColor(mTheme.getDebuggingLineBackgroundColor()); mLineHighlightPaint.setColor(mTheme.getDebuggingLineBackgroundColor());
drawLineHighlight(canvas, mLineHighlightPaint, debugHighlightLine); drawLineHighlight(canvas, mLineHighlightPaint, debugHighlightLine);
} }
@@ -400,4 +405,34 @@ public class CodeEditText extends AppCompatEditText {
super.setSelection(index); super.setSelection(index);
} }
@Override
public Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
Parcelable superData = super.onSaveInstanceState();
bundle.putParcelable("super_data", superData);
bundle.putInt("debugging_line", mDebuggingLine);
int[] breakpoints = new int[mBreakpoints.size()];
int i = 0;
for (CodeEditor.Breakpoint breakpoint : mBreakpoints.values()) {
breakpoints[i++] = breakpoint.line;
}
bundle.putIntArray("breakpoints", breakpoints);
return bundle;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
Bundle bundle = (Bundle) state;
Parcelable superData = bundle.getParcelable("super_data");
mDebuggingLine = bundle.getInt("debugging_line", -1);
int[] breakpoints = bundle.getIntArray("breakpoints");
if(breakpoints != null){
for (int breakpoint : breakpoints) {
mBreakpoints.put(breakpoint, new CodeEditor.Breakpoint(breakpoint));
}
}
super.onRestoreInstanceState(superData);
}
} }

View File

@@ -3,6 +3,7 @@ package org.autojs.autojs.ui.edit.editor;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.text.Layout;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.Toast; import android.widget.Toast;
@@ -167,7 +168,8 @@ public class CodeEditor extends HVScrollView {
} }
public void jumpTo(int line, int col) { public void jumpTo(int line, int col) {
if (line >= mCodeEditText.getLayout().getLineCount() || line < 0) { Layout layout = mCodeEditText.getLayout();
if (line < 0 || (layout != null && line >= layout.getLineCount())) {
return; return;
} }
mCodeEditText.setSelection(mCodeEditText.getLayout().getLineStart(line) + col); mCodeEditText.setSelection(mCodeEditText.getLayout().getLineStart(line) + col);
@@ -334,13 +336,14 @@ public class CodeEditor extends HVScrollView {
return mCodeEditText.getBreakpoints(); return mCodeEditText.getBreakpoints();
} }
public void setDebuggingLine(int line){ public void setDebuggingLine(int line) {
jumpTo(line, 0);
mCodeEditText.setDebuggingLine(line); mCodeEditText.setDebuggingLine(line);
} }
public void addOrRemoveBreakpoint(int line) { public void addOrRemoveBreakpoint(int line) {
LinkedHashMap<Integer, Breakpoint> breakpoints = mCodeEditText.getBreakpoints(); LinkedHashMap<Integer, Breakpoint> breakpoints = mCodeEditText.getBreakpoints();
if(breakpoints.remove(line) == null){ if (breakpoints.remove(line) == null) {
breakpoints.put(line, new Breakpoint(line)); breakpoints.put(line, new Breakpoint(line));
} }
mCodeEditText.invalidate(); mCodeEditText.invalidate();

View File

@@ -1,6 +1,5 @@
package org.autojs.autojs.ui.edit.toolbar; package org.autojs.autojs.ui.edit.toolbar;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@@ -29,14 +28,11 @@ import java.util.List;
public class DebugToolbarFragment extends ToolbarFragment implements DebugCallback { public class DebugToolbarFragment extends ToolbarFragment implements DebugCallback {
private static final String LOG_TAG = "DebugToolbarFragment"; private static final String LOG_TAG = "DebugToolbarFragment";
private Dim mDim = new Dim(); private Dim mDim;
private EditorView mEditorView; private EditorView mEditorView;
private Handler mHandler; private Handler mHandler;
public DebugToolbarFragment() { public DebugToolbarFragment() {
mDim.setGuiCallback(this);
mDim.setBreak();
mDim.attachTo(AutoJs.getInstance().getScriptEngineService(), ContextFactory.getGlobal());
Log.d(LOG_TAG, "DebugToolbarFragment()"); Log.d(LOG_TAG, "DebugToolbarFragment()");
} }
@@ -50,29 +46,54 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
mEditorView = findEditorView(view); mEditorView = findEditorView(view);
mEditorView.run(); ScriptExecution scriptExecution = mEditorView.getScriptExecution();
if (scriptExecution != null) {
mDim = (Dim) scriptExecution.getEngine().getTag(Dim.TAG);
}
if (mDim == null) {
mDim = new Dim();
mDim.setBreak();
mDim.setBreakOnExceptions(true);
mDim.attachTo(AutoJs.getInstance().getScriptEngineService(), ContextFactory.getGlobal());
mDim.setGuiCallback(this);
setInterrupted(false);
mEditorView.run();
} else {
mDim.setGuiCallback(this);
}
Log.d(LOG_TAG, "onViewCreated"); Log.d(LOG_TAG, "onViewCreated");
} }
private void setInterrupted(boolean interrupted) {
setMenuItemStatus(R.id.step_into, interrupted);
setMenuItemStatus(R.id.step_over, interrupted);
setMenuItemStatus(R.id.step_out, interrupted);
setMenuItemStatus(R.id.resume_script, interrupted);
if (!interrupted) {
mEditorView.getEditor().setDebuggingLine(-1);
}
}
public void detachDebugger() { public void detachDebugger() {
mDim.detach(); mDim.detach();
mDim.setGuiCallback(null);
} }
@Click(R.id.step_over) @Click(R.id.step_over)
void stepOver() { void stepOver() {
mEditorView.getEditor().setDebuggingLine(-1); setInterrupted(false);
mDim.setReturnValue(Dim.STEP_OVER); mDim.setReturnValue(Dim.STEP_OVER);
} }
@Click(R.id.step_into) @Click(R.id.step_into)
void stepInto() { void stepInto() {
mEditorView.getEditor().setDebuggingLine(-1); setInterrupted(false);
mDim.setReturnValue(Dim.STEP_INTO); mDim.setReturnValue(Dim.STEP_INTO);
} }
@Click(R.id.stop_out) @Click(R.id.step_out)
void stepOut() { void stepOut() {
mEditorView.getEditor().setDebuggingLine(-1); setInterrupted(false);
mDim.setReturnValue(Dim.STEP_OUT); mDim.setReturnValue(Dim.STEP_OUT);
} }
@@ -83,13 +104,13 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
@Click(R.id.resume_script) @Click(R.id.resume_script)
void resumeScript() { void resumeScript() {
mEditorView.getEditor().setDebuggingLine(-1); setInterrupted(false);
mDim.setReturnValue(Dim.GO); mDim.setReturnValue(Dim.GO);
} }
@Override @Override
public void updateSourceText(Dim.SourceInfo sourceInfo) { public void updateSourceText(Dim.SourceInfo sourceInfo) {
Log.d(LOG_TAG, "updateSourceText: url = " + sourceInfo.url() + ", source = " + sourceInfo.source()); Log.d(LOG_TAG, "updateSourceText: url = " + sourceInfo.url());
if (!sourceInfo.url().equals(mEditorView.getFile().toString())) { if (!sourceInfo.url().equals(mEditorView.getFile().toString())) {
return; return;
} }
@@ -107,7 +128,12 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
public void enterInterrupt(Dim.StackFrame stackFrame, String threadName, String s1) { public void enterInterrupt(Dim.StackFrame stackFrame, String threadName, String s1) {
Log.d(LOG_TAG, "enterInterrupt: threadName = " + threadName + ", url = " + stackFrame.getUrl() + ", line = " + stackFrame.getLineNumber()); Log.d(LOG_TAG, "enterInterrupt: threadName = " + threadName + ", url = " + stackFrame.getUrl() + ", line = " + stackFrame.getLineNumber());
if (stackFrame.getUrl().equals(mEditorView.getFile().toString())) { if (stackFrame.getUrl().equals(mEditorView.getFile().toString())) {
mEditorView.getEditor().setDebuggingLine(stackFrame.getLineNumber() - 1); final int line = stackFrame.getLineNumber() - 1;
mHandler.post(() -> {
mEditorView.getEditor().setDebuggingLine(line);
setInterrupted(true);
});
} else { } else {
mHandler.post(this::resumeScript); mHandler.post(this::resumeScript);
} }
@@ -120,25 +146,18 @@ public class DebugToolbarFragment extends ToolbarFragment implements DebugCallba
@Override @Override
public void dispatchNextGuiEvent() { public void dispatchNextGuiEvent() {
Log.d(LOG_TAG, "dispatchNextGuiEvent");
} }
@Override @Override
public boolean shouldAttachDebugger(RhinoJavaScriptEngine engine) { public boolean shouldAttachDebugger(RhinoJavaScriptEngine engine) {
ScriptExecution execution = AutoJs.getInstance().getScriptEngineService().getScriptExecution(mEditorView.getScriptExecutionId()); ScriptExecution execution = mEditorView.getScriptExecution();
return execution != null && execution.getId() == engine.getId(); return execution != null && execution.getId() == engine.getId();
} }
@Override @Override
public List<Integer> getMenuItemIds() { public List<Integer> getMenuItemIds() {
return Arrays.asList(R.id.step_over, R.id.step_into, R.id.stop_out, R.id.resume_script, R.id.stop_script); return Arrays.asList(R.id.step_over, R.id.step_into, R.id.step_out, R.id.resume_script, R.id.stop_script);
} }
@Override
public void onDestroy() {
super.onDestroy();
mDim.detach();
}
} }

View File

@@ -5,6 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:scrollHorizontally="true" android:scrollHorizontally="true"
android:imeOptions="flagNoExtractUi"
android:textColor="@android:color/transparent" android:textColor="@android:color/transparent"
android:textCursorDrawable="@drawable/code_edit_text_cursor" android:textCursorDrawable="@drawable/code_edit_text_cursor"
android:textSize="15sp"/> android:textSize="15sp"/>

View File

@@ -21,7 +21,7 @@
app:text="@string/text_debug_step_into"/> app:text="@string/text_debug_step_into"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem <org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/stop_out" android:id="@+id/step_out"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="match_parent" android:layout_height="match_parent"
app:icon="@drawable/ic_debug_step_out" app:icon="@drawable/ic_debug_step_out"

View File

@@ -1,6 +1,7 @@
package com.stardust.autojs; package com.stardust.autojs;
import android.content.Context; import android.content.Context;
import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.stardust.autojs.engine.JavaScriptEngine; import com.stardust.autojs.engine.JavaScriptEngine;
@@ -25,6 +26,9 @@ import com.stardust.util.UiHandler;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
import org.mozilla.javascript.RhinoException;
import org.mozilla.javascript.ScriptStackElement;
import org.mozilla.javascript.WrappedException;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@@ -209,7 +213,7 @@ public class ScriptEngineService {
@Nullable @Nullable
public ScriptExecution getScriptExecution(int id) { public ScriptExecution getScriptExecution(int id) {
if(id == ScriptExecution.NO_ID){ if (id == ScriptExecution.NO_ID) {
return null; return null;
} }
return mScriptExecutions.get(id); return mScriptExecutions.get(id);
@@ -275,7 +279,17 @@ public class ScriptEngineService {
} }
} }
private static String getScriptTrace(Exception e) { public static String getScriptTrace(Exception e) {
StringBuilder scriptTrace = new StringBuilder();
if (e instanceof RhinoException) {
RhinoException rhinoException = (RhinoException) e;
scriptTrace.append(rhinoException.details()).append("\n");
for (ScriptStackElement element : rhinoException.getScriptStack()) {
element.renderV8Style(scriptTrace);
scriptTrace.append("\n");
}
scriptTrace.append("- - - - - - - - - - -\n");
}
try { try {
PipedReader reader = new PipedReader(8192); PipedReader reader = new PipedReader(8192);
PrintWriter writer = new PrintWriter(new PipedWriter(reader)); PrintWriter writer = new PrintWriter(new PipedWriter(reader));
@@ -283,10 +297,9 @@ public class ScriptEngineService {
writer.close(); writer.close();
BufferedReader bufferedReader = new BufferedReader(reader); BufferedReader bufferedReader = new BufferedReader(reader);
String line; String line;
StringBuilder scriptTrace = new StringBuilder(TextUtils.toEmptyIfNull(e.getMessage())); //scriptTrace.append(TextUtils.toEmptyIfNull(e.getMessage()));
while ((line = bufferedReader.readLine()) != null) { while ((line = bufferedReader.readLine()) != null) {
if (line.trim().startsWith("at script")) scriptTrace.append("\n").append(line);
scriptTrace.append("\n").append(line);
} }
return scriptTrace.toString(); return scriptTrace.toString();
} catch (IOException e1) { } catch (IOException e1) {

View File

@@ -4,6 +4,7 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.support.annotation.CallSuper; import android.support.annotation.CallSuper;
import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.engine.RhinoJavaScriptEngine; import com.stardust.autojs.engine.RhinoJavaScriptEngine;
import com.stardust.autojs.runtime.ScriptBridges; import com.stardust.autojs.runtime.ScriptBridges;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
@@ -48,7 +49,7 @@ public class TimerThread extends ThreadCompat {
Looper.loop(); Looper.loop();
} catch (Exception e) { } catch (Exception e) {
if (!ScriptInterruptedException.causedByInterrupted(e)) { if (!ScriptInterruptedException.causedByInterrupted(e)) {
mRuntime.console.error(Thread.currentThread().toString() + ": " + e); mRuntime.console.error(Thread.currentThread().toString() + ": " + ScriptEngineService.getScriptTrace(e));
} }
} finally { } finally {
onExit(); onExit();

View File

@@ -32,6 +32,7 @@ public class Dim {
public static final int GO = 3; public static final int GO = 3;
public static final int BREAK = 4; public static final int BREAK = 4;
public static final int EXIT = 5; public static final int EXIT = 5;
public static final String TAG = Dim.class.getName();
// Constants for the DimIProxy interface implementation class. // Constants for the DimIProxy interface implementation class.
private static final int IPROXY_DEBUG = 0; private static final int IPROXY_DEBUG = 0;
@@ -1027,6 +1028,7 @@ public class Dim {
cx.setDebugger(debugger, contextData); cx.setDebugger(debugger, contextData);
cx.setGeneratingDebug(true); cx.setGeneratingDebug(true);
cx.setOptimizationLevel(-1); cx.setOptimizationLevel(-1);
engine.setTag(TAG, Dim.this);
} }
@Override @Override

View File

@@ -372,7 +372,7 @@ public class ScriptRuntime {
try { try {
events.emit("exit"); events.emit("exit");
} catch (Exception ignored) { } catch (Exception ignored) {
console.error("exception on exit: " + ignored); console.error("exception on exit: " + ScriptEngineService.getScriptTrace(ignored));
} }
ignoresException(threads::shutDownAll); ignoresException(threads::shutDownAll);
ignoresException(events::recycle); ignoresException(events::recycle);

View File

@@ -1 +1 @@
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":401},"path":"commonRelease-4.0.0 Alpha1.apk","properties":{"packageId":"org.autojs.autojs","split":"","minSdkVersion":"17"}}] [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":408},"path":"commonRelease-4.0.2 Alpha3.apk","properties":{"packageId":"org.autojs.autojs","split":"","minSdkVersion":"17"}}]

View File

@@ -10,6 +10,7 @@ import com.stardust.auojs.inrt.BuildConfig;
import com.stardust.auojs.inrt.LogActivity; import com.stardust.auojs.inrt.LogActivity;
import com.stardust.auojs.inrt.Pref; import com.stardust.auojs.inrt.Pref;
import com.stardust.auojs.inrt.autojs.AutoJs; import com.stardust.auojs.inrt.autojs.AutoJs;
import com.stardust.autojs.ScriptEngineService;
import com.stardust.autojs.execution.ExecutionConfig; import com.stardust.autojs.execution.ExecutionConfig;
import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.project.ProjectConfig; import com.stardust.autojs.project.ProjectConfig;
@@ -73,7 +74,7 @@ public class AssetsProjectLauncher {
mScriptExecution = AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig() mScriptExecution = AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig()
.executePath(mProjectDir)); .executePath(mProjectDir));
} catch (Exception e) { } catch (Exception e) {
AutoJs.getInstance().getGlobalConsole().error(e); AutoJs.getInstance().getGlobalConsole().error(ScriptEngineService.getScriptTrace(e));
} }
} }