Index: runtime/observatory/lib/src/elements/debugger.dart |
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart |
index 8b91efffe5b35548afe24bb75b7924feafcf80b1..3cf1be997a4ba9a1196c407cd924b54bc677d22b 100644 |
--- a/runtime/observatory/lib/src/elements/debugger.dart |
+++ b/runtime/observatory/lib/src/elements/debugger.dart |
@@ -209,7 +209,8 @@ class DownCommand extends DebuggerCommand { |
debugger.downFrame(count); |
debugger.console.print('frame = ${debugger.currentFrame}'); |
} catch (e) { |
- debugger.console.print('frame must be in range [${e.start},${e.end-1}]'); |
+ debugger.console.print( |
+ 'frame must be in range [${e.start}..${e.end-1}]'); |
} |
return new Future.value(null); |
} |
@@ -243,7 +244,8 @@ class UpCommand extends DebuggerCommand { |
debugger.upFrame(count); |
debugger.console.print('frame = ${debugger.currentFrame}'); |
} on RangeError catch (e) { |
- debugger.console.print('frame must be in range [${e.start},${e.end-1}]'); |
+ debugger.console.print( |
+ 'frame must be in range [${e.start}..${e.end-1}]'); |
} |
return new Future.value(null); |
} |
@@ -279,7 +281,8 @@ class FrameCommand extends DebuggerCommand { |
debugger.currentFrame = frame; |
debugger.console.print('frame = ${debugger.currentFrame}'); |
} on RangeError catch (e) { |
- debugger.console.print('frame must be in range [${e.start},${e.end-1}]'); |
+ debugger.console.print( |
+ 'frame must be in range [${e.start}..${e.end-1}]'); |
} |
return new Future.value(null); |
} |
@@ -403,6 +406,74 @@ class StepCommand extends DebuggerCommand { |
'Syntax: step\n'; |
} |
+class RewindCommand extends DebuggerCommand { |
+ RewindCommand(Debugger debugger) : super(debugger, 'rewind', []); |
+ |
+ Future run(List<String> args) async { |
+ try { |
+ int count = 1; |
+ if (args.length == 1) { |
+ count = int.parse(args[0]); |
+ } else if (args.length > 1) { |
+ debugger.console.print('rewind expects 0 or 1 argument'); |
+ return; |
+ } else if (count < 1 || count > debugger.stackDepth) { |
+ debugger.console.print( |
+ 'frame must be in range [1..${debugger.stackDepth - 1}]'); |
+ return; |
+ } |
+ await debugger.rewind(count); |
+ } on S.ServerRpcException catch(e) { |
+ if (e.code == S.ServerRpcException.kCannotResume) { |
+ debugger.console.printRed(e.data['details']); |
+ } else { |
+ rethrow; |
+ } |
+ } |
+ } |
+ |
+ String helpShort = 'Rewind the stack to a previous frame'; |
+ |
+ String helpLong = |
+ 'Rewind the stack to a previous frame.\n' |
+ '\n' |
+ 'Syntax: rewind\n' |
+ ' rewind <count>\n'; |
+} |
+ |
+class ReloadCommand extends DebuggerCommand { |
+ ReloadCommand(Debugger debugger) : super(debugger, 'reload', []); |
+ |
+ Future run(List<String> args) async { |
+ try { |
+ int count = 1; |
+ if (args.length > 0) { |
+ debugger.console.print('reload expects no arguments'); |
+ return; |
+ } |
+ await debugger.isolate.reloadSources(); |
+ // debugger.clearStack(); |
+ debugger.console.print('reload complete'); |
+ await debugger.refreshStack(); |
+ } on S.ServerRpcException catch(e) { |
+ if (e.code == S.ServerRpcException.kIsolateReloadBarred || |
+ e.code == S.ServerRpcException.kIsolateReloadFailed || |
+ e.code == S.ServerRpcException.kIsolateIsReloading) { |
+ debugger.console.printRed(e.data['details']); |
+ } else { |
+ rethrow; |
+ } |
+ } |
+ } |
+ |
+ String helpShort = 'Reload the sources for the current isolate'; |
+ |
+ String helpLong = |
+ 'Reload the sources for the current isolate.\n' |
+ '\n' |
+ 'Syntax: reload\n'; |
+} |
+ |
class ClsCommand extends DebuggerCommand { |
ClsCommand(Debugger debugger) : super(debugger, 'cls', []) {} |
@@ -663,8 +734,8 @@ class BreakCommand extends DebuggerCommand { |
var script = loc.script; |
await script.load(); |
if (loc.line < 1 || loc.line > script.lines.length) { |
- debugger.console |
- .print('line number must be in range [1,${script.lines.length}]'); |
+ debugger.console.print( |
+ 'line number must be in range [1..${script.lines.length}]'); |
return; |
} |
try { |
@@ -744,7 +815,7 @@ class ClearCommand extends DebuggerCommand { |
var script = loc.script; |
if (loc.line < 1 || loc.line > script.lines.length) { |
debugger.console |
- .print('line number must be in range [1,${script.lines.length}]'); |
+ .print('line number must be in range [1..${script.lines.length}]'); |
return; |
} |
var lineInfo = script.getLine(loc.line); |
@@ -899,7 +970,6 @@ class IsolateCommand extends DebuggerCommand { |
: super(debugger, 'isolate', [ |
new IsolateListCommand(debugger), |
new IsolateNameCommand(debugger), |
- new IsolateReloadCommand(debugger), |
]) { |
alias = 'i'; |
} |
@@ -1042,27 +1112,6 @@ class IsolateNameCommand extends DebuggerCommand { |
'Syntax: isolate name <name>\n'; |
} |
-class IsolateReloadCommand extends DebuggerCommand { |
- IsolateReloadCommand(Debugger debugger) : super(debugger, 'reload', []); |
- |
- Future run(List<String> args) async { |
- if (debugger.isolate == null) { |
- debugger.console.print('There is no current vm'); |
- return; |
- } |
- |
- await debugger.isolate.reloadSources(); |
- |
- debugger.console.print('Isolate reloading....'); |
- } |
- |
- String helpShort = 'Reload the sources for the current isolate.'; |
- |
- String helpLong = 'Reload the sources for the current isolate.\n' |
- '\n' |
- 'Syntax: reload\n'; |
-} |
- |
class InfoCommand extends DebuggerCommand { |
InfoCommand(Debugger debugger) |
: super(debugger, 'info', [ |
@@ -1371,7 +1420,9 @@ class ObservatoryDebugger extends Debugger { |
new LogCommand(this), |
new PauseCommand(this), |
new PrintCommand(this), |
+ new ReloadCommand(this), |
new RefreshCommand(this), |
+ new RewindCommand(this), |
new SetCommand(this), |
new SmartNextCommand(this), |
new StepCommand(this), |
@@ -1456,6 +1507,10 @@ class ObservatoryDebugger extends Debugger { |
}); |
} |
+ void clearStack() { |
+ stackElement.clearStack(); |
+ } |
+ |
Future<S.ServiceMap> _refreshStack(M.DebugEvent pauseEvent) { |
return isolate.getStack().then((result) { |
if (result.isSentinel) { |
@@ -1879,6 +1934,20 @@ class ObservatoryDebugger extends Debugger { |
return new Future.value(null); |
} |
} |
+ |
+ Future rewind(int count) { |
+ if (isolatePaused()) { |
+ var event = isolate.pauseEvent; |
+ if (event is M.PauseExitEvent) { |
+ console.print("Type 'continue' [F7] to exit the isolate"); |
+ return new Future.value(null); |
+ } |
+ return isolate.rewind(count); |
+ } else { |
+ console.print('The program must be paused'); |
+ return new Future.value(null); |
+ } |
+ } |
} |
class DebuggerPageElement extends HtmlElement implements Renderable { |
@@ -2273,6 +2342,17 @@ class DebuggerStackElement extends HtmlElement implements Renderable { |
isSampled = pauseEvent == null; |
} |
+ void clearStack() { |
+ List frameElements = _frameList.children; |
Cutch
2016/11/22 22:27:50
can we not just call clear on the lists?
turnidge
2016/11/22 22:54:06
Turns out this code was dead. Removed.
|
+ for (int i = 0; i < frameElements.length; i++) { |
+ frameElements.removeAt(0); |
+ } |
+ List messageElements = _messageList.children; |
+ for (int i = 0; i < messageElements.length; i++) { |
+ messageElements.removeAt(0); |
+ } |
+ } |
+ |
void setCurrentFrame(int value) { |
currentFrame = value; |
List frameElements = _frameList.children; |
@@ -2513,7 +2593,9 @@ class DebuggerFrameElement extends HtmlElement implements Renderable { |
} |
bool matchFrame(S.Frame newFrame) { |
- return newFrame.function.id == _frame.function.id; |
+ return (newFrame.function.id == _frame.function.id && |
+ newFrame.location.script.id == |
+ frame.location.script.id); |
} |
void updateFrame(S.Frame newFrame) { |