| 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 b3ca5693fd3b00e7b831eb127e6e7b95524bbda6..18594b42dd4210ae95990f6066f966648eacc112 100644
|
| --- a/runtime/observatory/lib/src/elements/debugger.dart
|
| +++ b/runtime/observatory/lib/src/elements/debugger.dart
|
| @@ -604,6 +604,11 @@ class SetCommand extends DebuggerCommand {
|
| _setUpIsDown,
|
| (debugger, _) => debugger.upIsDown
|
| ],
|
| + 'sane-async-stacks': [
|
| + _boolValues,
|
| + _setSaneAsyncStacks,
|
| + (debugger, _) => debugger.saneAsyncStacks
|
| + ]
|
| };
|
|
|
| static Future _setBreakOnException(debugger, name, value) async {
|
| @@ -625,6 +630,16 @@ class SetCommand extends DebuggerCommand {
|
| debugger.console.print('${name} = ${value}');
|
| }
|
|
|
| + static Future _setSaneAsyncStacks(debugger, name, value) async {
|
| + if (value == 'true') {
|
| + debugger.saneAsyncStacks = true;
|
| + } else {
|
| + debugger.saneAsyncStacks = false;
|
| + }
|
| + debugger.refreshStack();
|
| + debugger.console.print('${name} = ${value}');
|
| + }
|
| +
|
| Future run(List<String> args) async {
|
| if (args.length == 0) {
|
| for (var name in _options.keys) {
|
| @@ -1381,6 +1396,17 @@ class ObservatoryDebugger extends Debugger {
|
|
|
| bool _upIsDown;
|
|
|
| + bool get saneAsyncStacks => _saneAsyncStacks;
|
| + void set saneAsyncStacks(bool value) {
|
| + settings.set('sane-async-stacks', value);
|
| + _saneAsyncStacks = value;
|
| + }
|
| +
|
| + bool _saneAsyncStacks;
|
| +
|
| + static const String kAsyncStackFrames = 'asyncFrames';
|
| + static const String kStackFrames = 'frames';
|
| +
|
| void upFrame(int count) {
|
| if (_upIsDown) {
|
| currentFrame += count;
|
| @@ -1397,7 +1423,21 @@ class ObservatoryDebugger extends Debugger {
|
| }
|
| }
|
|
|
| - int get stackDepth => stack['frames'].length;
|
| + int get stackDepth {
|
| + if (saneAsyncStacks) {
|
| + return stack[kAsyncStackFrames].length;
|
| + } else {
|
| + return stack[kStackFrames].length;
|
| + }
|
| + }
|
| +
|
| + List get stackFrames {
|
| + if (saneAsyncStacks) {
|
| + return stack[kAsyncStackFrames] ?? [];
|
| + } else {
|
| + return stack[kStackFrames] ?? [];
|
| + }
|
| + }
|
|
|
| static final _history = [''];
|
|
|
| @@ -1434,6 +1474,8 @@ class ObservatoryDebugger extends Debugger {
|
|
|
| void _loadSettings() {
|
| _upIsDown = settings.get('up-is-down');
|
| + _saneAsyncStacks = settings.get('sane-async-stacks') ?? true;
|
| + print('saneAsyncStacks -> $_saneAsyncStacks');
|
| }
|
|
|
| S.VM get vm => page.app.vm;
|
| @@ -1515,7 +1557,9 @@ class ObservatoryDebugger extends Debugger {
|
| }
|
| stack = result;
|
| stackElement.updateStack(stack, pauseEvent);
|
| - if (stack['frames'].length > 0) {
|
| + List frames =
|
| + saneAsyncStacks ? stack[kAsyncStackFrames] : stack[kStackFrames];
|
| + if (frames.length > 0) {
|
| currentFrame = 0;
|
| } else {
|
| currentFrame = null;
|
| @@ -1585,8 +1629,8 @@ class ObservatoryDebugger extends Debugger {
|
| console.print("Paused at an unhandled exception "
|
| "(type 'continue' or [F7] to exit the isolate')");
|
| _reportIsolateError(isolate, event);
|
| - } else if (stack['frames'].length > 0) {
|
| - S.Frame frame = stack['frames'][0];
|
| + } else if (stackFrames.length > 0) {
|
| + S.Frame frame = stackFrames[0];
|
| var script = frame.location.script;
|
| script.load().then((_) {
|
| var line = script.tokenToLine(frame.location.tokenPos);
|
| @@ -2251,7 +2295,9 @@ class DebuggerStackElement extends HtmlElement implements Renderable {
|
|
|
| void updateStackFrames(S.ServiceMap newStack) {
|
| List frameElements = _frameList.children;
|
| - List newFrames = newStack['frames'];
|
| + List newFrames = _debugger.saneAsyncStacks ?
|
| + newStack[ObservatoryDebugger.kAsyncStackFrames] :
|
| + newStack[ObservatoryDebugger.kStackFrames];
|
|
|
| // Remove any frames whose functions don't match, starting from
|
| // bottom of stack.
|
| @@ -2379,7 +2425,11 @@ class DebuggerFrameElement extends HtmlElement implements Renderable {
|
| bool _expanded = false;
|
|
|
| void setCurrent(bool value) {
|
| - _frame.function.load().then((func) {
|
| + Future load =
|
| + (_frame.function != null) ?
|
| + _frame.function.load() :
|
| + new Future.value(null);
|
| + load.then((func) {
|
| _current = value;
|
| if (_current) {
|
| _expand();
|
| @@ -2432,6 +2482,13 @@ class DebuggerFrameElement extends HtmlElement implements Renderable {
|
| } else {
|
| classes.remove('current');
|
| }
|
| + if (_frame.kind == M.FrameKind.marker) {
|
| + final content = <Element>[
|
| + new SpanElement()..children = _createMarkerHeader(_frame.marker)
|
| + ];
|
| + children = content;
|
| + return;
|
| + }
|
| ButtonElement expandButton;
|
| final content = <Element>[
|
| expandButton = new ButtonElement()
|
| @@ -2534,6 +2591,24 @@ class DebuggerFrameElement extends HtmlElement implements Renderable {
|
| children = content;
|
| }
|
|
|
| + List<Element> _createMarkerHeader(String marker) {
|
| + final content = [
|
| + new DivElement()
|
| + ..classes = ['frameSummaryText']
|
| + ..children = [
|
| + new DivElement()
|
| + ..classes = ['frameId']
|
| + ..text = 'Frame ${_frame.index}',
|
| + new SpanElement()..text = '$marker',
|
| + ]
|
| + ];
|
| + return [
|
| + new DivElement()
|
| + ..classes = ['frameSummary']
|
| + ..children = content
|
| + ];
|
| + }
|
| +
|
| List<Element> _createHeader() {
|
| final content = [
|
| new DivElement()
|
| @@ -2578,6 +2653,9 @@ class DebuggerFrameElement extends HtmlElement implements Renderable {
|
| }
|
|
|
| bool matchFrame(S.Frame newFrame) {
|
| + if (newFrame.function == null) {
|
| + return frame.function == null;
|
| + }
|
| return (newFrame.function.id == _frame.function.id &&
|
| newFrame.location.script.id ==
|
| frame.location.script.id);
|
|
|