Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Side by Side Diff: runtime/observatory/lib/src/elements/debugger.dart

Issue 2603383004: Sane asynchronous debugging and stack traces (Closed)
Patch Set: rebase Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/lib/stacktrace.cc ('k') | runtime/observatory/lib/src/models/objects/frame.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library debugger_page_element; 5 library debugger_page_element;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:svg'; 8 import 'dart:svg';
9 import 'dart:html'; 9 import 'dart:html';
10 import 'dart:math'; 10 import 'dart:math';
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 'break-on-exception': [ 597 'break-on-exception': [
598 _boeValues, 598 _boeValues,
599 _setBreakOnException, 599 _setBreakOnException,
600 (debugger, _) => debugger.breakOnException 600 (debugger, _) => debugger.breakOnException
601 ], 601 ],
602 'up-is-down': [ 602 'up-is-down': [
603 _boolValues, 603 _boolValues,
604 _setUpIsDown, 604 _setUpIsDown,
605 (debugger, _) => debugger.upIsDown 605 (debugger, _) => debugger.upIsDown
606 ], 606 ],
607 'sane-async-stacks': [
608 _boolValues,
609 _setSaneAsyncStacks,
610 (debugger, _) => debugger.saneAsyncStacks
611 ]
607 }; 612 };
608 613
609 static Future _setBreakOnException(debugger, name, value) async { 614 static Future _setBreakOnException(debugger, name, value) async {
610 var result = await debugger.isolate.setExceptionPauseMode(value); 615 var result = await debugger.isolate.setExceptionPauseMode(value);
611 if (result.isError) { 616 if (result.isError) {
612 debugger.console.print(result.toString()); 617 debugger.console.print(result.toString());
613 } else { 618 } else {
614 // Printing will occur elsewhere. 619 // Printing will occur elsewhere.
615 debugger.breakOnException = value; 620 debugger.breakOnException = value;
616 } 621 }
617 } 622 }
618 623
619 static Future _setUpIsDown(debugger, name, value) async { 624 static Future _setUpIsDown(debugger, name, value) async {
620 if (value == 'true') { 625 if (value == 'true') {
621 debugger.upIsDown = true; 626 debugger.upIsDown = true;
622 } else { 627 } else {
623 debugger.upIsDown = false; 628 debugger.upIsDown = false;
624 } 629 }
625 debugger.console.print('${name} = ${value}'); 630 debugger.console.print('${name} = ${value}');
626 } 631 }
627 632
633 static Future _setSaneAsyncStacks(debugger, name, value) async {
634 if (value == 'true') {
635 debugger.saneAsyncStacks = true;
636 } else {
637 debugger.saneAsyncStacks = false;
638 }
639 debugger.refreshStack();
640 debugger.console.print('${name} = ${value}');
641 }
642
628 Future run(List<String> args) async { 643 Future run(List<String> args) async {
629 if (args.length == 0) { 644 if (args.length == 0) {
630 for (var name in _options.keys) { 645 for (var name in _options.keys) {
631 var getHandler = _options[name][2]; 646 var getHandler = _options[name][2];
632 var value = await getHandler(debugger, name); 647 var value = await getHandler(debugger, name);
633 debugger.console.print("${name} = ${value}"); 648 debugger.console.print("${name} = ${value}");
634 } 649 }
635 } else if (args.length == 1) { 650 } else if (args.length == 1) {
636 var name = args[0].trim(); 651 var name = args[0].trim();
637 var optionInfo = _options[name]; 652 var optionInfo = _options[name];
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after
1374 int _currentFrame = null; 1389 int _currentFrame = null;
1375 1390
1376 bool get upIsDown => _upIsDown; 1391 bool get upIsDown => _upIsDown;
1377 void set upIsDown(bool value) { 1392 void set upIsDown(bool value) {
1378 settings.set('up-is-down', value); 1393 settings.set('up-is-down', value);
1379 _upIsDown = value; 1394 _upIsDown = value;
1380 } 1395 }
1381 1396
1382 bool _upIsDown; 1397 bool _upIsDown;
1383 1398
1399 bool get saneAsyncStacks => _saneAsyncStacks;
1400 void set saneAsyncStacks(bool value) {
1401 settings.set('sane-async-stacks', value);
1402 _saneAsyncStacks = value;
1403 }
1404
1405 bool _saneAsyncStacks;
1406
1407 static const String kAsyncStackFrames = 'asyncFrames';
1408 static const String kStackFrames = 'frames';
1409
1384 void upFrame(int count) { 1410 void upFrame(int count) {
1385 if (_upIsDown) { 1411 if (_upIsDown) {
1386 currentFrame += count; 1412 currentFrame += count;
1387 } else { 1413 } else {
1388 currentFrame -= count; 1414 currentFrame -= count;
1389 } 1415 }
1390 } 1416 }
1391 1417
1392 void downFrame(int count) { 1418 void downFrame(int count) {
1393 if (_upIsDown) { 1419 if (_upIsDown) {
1394 currentFrame -= count; 1420 currentFrame -= count;
1395 } else { 1421 } else {
1396 currentFrame += count; 1422 currentFrame += count;
1397 } 1423 }
1398 } 1424 }
1399 1425
1400 int get stackDepth => stack['frames'].length; 1426 int get stackDepth {
1427 if (saneAsyncStacks) {
1428 return stack[kAsyncStackFrames].length;
1429 } else {
1430 return stack[kStackFrames].length;
1431 }
1432 }
1433
1434 List get stackFrames {
1435 if (saneAsyncStacks) {
1436 return stack[kAsyncStackFrames] ?? [];
1437 } else {
1438 return stack[kStackFrames] ?? [];
1439 }
1440 }
1401 1441
1402 static final _history = ['']; 1442 static final _history = [''];
1403 1443
1404 ObservatoryDebugger(this.isolate) { 1444 ObservatoryDebugger(this.isolate) {
1405 _loadSettings(); 1445 _loadSettings();
1406 cmd = new RootCommand([ 1446 cmd = new RootCommand([
1407 new AsyncNextCommand(this), 1447 new AsyncNextCommand(this),
1408 new BreakCommand(this), 1448 new BreakCommand(this),
1409 new ClearCommand(this), 1449 new ClearCommand(this),
1410 new ClsCommand(this), 1450 new ClsCommand(this),
(...skipping 16 matching lines...) Expand all
1427 new StepCommand(this), 1467 new StepCommand(this),
1428 new SyncNextCommand(this), 1468 new SyncNextCommand(this),
1429 new UpCommand(this), 1469 new UpCommand(this),
1430 new VmCommand(this), 1470 new VmCommand(this),
1431 ], _history); 1471 ], _history);
1432 _consolePrinter = new _ConsoleStreamPrinter(this); 1472 _consolePrinter = new _ConsoleStreamPrinter(this);
1433 } 1473 }
1434 1474
1435 void _loadSettings() { 1475 void _loadSettings() {
1436 _upIsDown = settings.get('up-is-down'); 1476 _upIsDown = settings.get('up-is-down');
1477 _saneAsyncStacks = settings.get('sane-async-stacks') ?? true;
1478 print('saneAsyncStacks -> $_saneAsyncStacks');
1437 } 1479 }
1438 1480
1439 S.VM get vm => page.app.vm; 1481 S.VM get vm => page.app.vm;
1440 1482
1441 void init() { 1483 void init() {
1442 console.printBold('Debugging isolate isolate ${isolate.number} ' 1484 console.printBold('Debugging isolate isolate ${isolate.number} '
1443 '\'${isolate.name}\' '); 1485 '\'${isolate.name}\' ');
1444 console.printBold('Type \'h\' for help'); 1486 console.printBold('Type \'h\' for help');
1445 // Wait a bit and if polymer still hasn't set up the isolate, 1487 // Wait a bit and if polymer still hasn't set up the isolate,
1446 // report this to the user. 1488 // report this to the user.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1508 1550
1509 Future<S.ServiceMap> _refreshStack(M.DebugEvent pauseEvent) { 1551 Future<S.ServiceMap> _refreshStack(M.DebugEvent pauseEvent) {
1510 return isolate.getStack().then((result) { 1552 return isolate.getStack().then((result) {
1511 if (result.isSentinel) { 1553 if (result.isSentinel) {
1512 // The isolate has gone away. The IsolateExit event will 1554 // The isolate has gone away. The IsolateExit event will
1513 // clear the isolate for the debugger page. 1555 // clear the isolate for the debugger page.
1514 return; 1556 return;
1515 } 1557 }
1516 stack = result; 1558 stack = result;
1517 stackElement.updateStack(stack, pauseEvent); 1559 stackElement.updateStack(stack, pauseEvent);
1518 if (stack['frames'].length > 0) { 1560 List frames =
1561 saneAsyncStacks ? stack[kAsyncStackFrames] : stack[kStackFrames];
1562 if (frames.length > 0) {
1519 currentFrame = 0; 1563 currentFrame = 0;
1520 } else { 1564 } else {
1521 currentFrame = null; 1565 currentFrame = null;
1522 } 1566 }
1523 input.focus(); 1567 input.focus();
1524 }); 1568 });
1525 } 1569 }
1526 1570
1527 void reportStatus() { 1571 void reportStatus() {
1528 flushStdio(); 1572 flushStdio();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 console.print("Paused at isolate start " 1622 console.print("Paused at isolate start "
1579 "(type 'continue' [F7] or 'step' [F10] to start the isolate')"); 1623 "(type 'continue' [F7] or 'step' [F10] to start the isolate')");
1580 } else if (event is M.PauseExitEvent) { 1624 } else if (event is M.PauseExitEvent) {
1581 console.print("Paused at isolate exit " 1625 console.print("Paused at isolate exit "
1582 "(type 'continue' or [F7] to exit the isolate')"); 1626 "(type 'continue' or [F7] to exit the isolate')");
1583 _reportIsolateError(isolate, event); 1627 _reportIsolateError(isolate, event);
1584 } else if (event is M.PauseExceptionEvent) { 1628 } else if (event is M.PauseExceptionEvent) {
1585 console.print("Paused at an unhandled exception " 1629 console.print("Paused at an unhandled exception "
1586 "(type 'continue' or [F7] to exit the isolate')"); 1630 "(type 'continue' or [F7] to exit the isolate')");
1587 _reportIsolateError(isolate, event); 1631 _reportIsolateError(isolate, event);
1588 } else if (stack['frames'].length > 0) { 1632 } else if (stackFrames.length > 0) {
1589 S.Frame frame = stack['frames'][0]; 1633 S.Frame frame = stackFrames[0];
1590 var script = frame.location.script; 1634 var script = frame.location.script;
1591 script.load().then((_) { 1635 script.load().then((_) {
1592 var line = script.tokenToLine(frame.location.tokenPos); 1636 var line = script.tokenToLine(frame.location.tokenPos);
1593 var col = script.tokenToCol(frame.location.tokenPos); 1637 var col = script.tokenToCol(frame.location.tokenPos);
1594 if ((event is M.PauseBreakpointEvent) && (event.breakpoint != null)) { 1638 if ((event is M.PauseBreakpointEvent) && (event.breakpoint != null)) {
1595 var bpId = event.breakpoint.number; 1639 var bpId = event.breakpoint.number;
1596 console.print('Paused at breakpoint ${bpId} at ' 1640 console.print('Paused at breakpoint ${bpId} at '
1597 '${script.name}:${line}:${col}'); 1641 '${script.name}:${line}:${col}');
1598 } else if ((event is M.PauseExceptionEvent) && 1642 } else if ((event is M.PauseExceptionEvent) &&
1599 (event.exception != null)) { 1643 (event.exception != null)) {
(...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after
2244 li.classes.add('list-group-item'); 2288 li.classes.add('list-group-item');
2245 li.children.insert(0, messageElement); 2289 li.children.insert(0, messageElement);
2246 2290
2247 messageList.add(li); 2291 messageList.add(li);
2248 } 2292 }
2249 2293
2250 ObservatoryApplication get app => ObservatoryApplication.app; 2294 ObservatoryApplication get app => ObservatoryApplication.app;
2251 2295
2252 void updateStackFrames(S.ServiceMap newStack) { 2296 void updateStackFrames(S.ServiceMap newStack) {
2253 List frameElements = _frameList.children; 2297 List frameElements = _frameList.children;
2254 List newFrames = newStack['frames']; 2298 List newFrames = _debugger.saneAsyncStacks ?
2299 newStack[ObservatoryDebugger.kAsyncStackFrames] :
2300 newStack[ObservatoryDebugger.kStackFrames];
2255 2301
2256 // Remove any frames whose functions don't match, starting from 2302 // Remove any frames whose functions don't match, starting from
2257 // bottom of stack. 2303 // bottom of stack.
2258 int oldPos = frameElements.length - 1; 2304 int oldPos = frameElements.length - 1;
2259 int newPos = newFrames.length - 1; 2305 int newPos = newFrames.length - 1;
2260 while (oldPos >= 0 && newPos >= 0) { 2306 while (oldPos >= 0 && newPos >= 0) {
2261 if (!frameElements[oldPos].children[0].matchFrame(newFrames[newPos])) { 2307 if (!frameElements[oldPos].children[0].matchFrame(newFrames[newPos])) {
2262 // The rest of the frame elements no longer match. Remove them. 2308 // The rest of the frame elements no longer match. Remove them.
2263 for (int i = 0; i <= oldPos; i++) { 2309 for (int i = 0; i <= oldPos; i++) {
2264 // NOTE(turnidge): removeRange is missing, sadly. 2310 // NOTE(turnidge): removeRange is missing, sadly.
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
2372 2418
2373 // Is this the current frame? 2419 // Is this the current frame?
2374 bool _current = false; 2420 bool _current = false;
2375 2421
2376 // Has this frame been pinned open? 2422 // Has this frame been pinned open?
2377 bool _pinned = false; 2423 bool _pinned = false;
2378 2424
2379 bool _expanded = false; 2425 bool _expanded = false;
2380 2426
2381 void setCurrent(bool value) { 2427 void setCurrent(bool value) {
2382 _frame.function.load().then((func) { 2428 Future load =
2429 (_frame.function != null) ?
2430 _frame.function.load() :
2431 new Future.value(null);
2432 load.then((func) {
2383 _current = value; 2433 _current = value;
2384 if (_current) { 2434 if (_current) {
2385 _expand(); 2435 _expand();
2386 scrollIntoView(); 2436 scrollIntoView();
2387 } else { 2437 } else {
2388 if (_pinned) { 2438 if (_pinned) {
2389 _expand(); 2439 _expand();
2390 } else { 2440 } else {
2391 _unexpand(); 2441 _unexpand();
2392 } 2442 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2425 if (_pinned) { 2475 if (_pinned) {
2426 classes.add('shadow'); 2476 classes.add('shadow');
2427 } else { 2477 } else {
2428 classes.remove('shadow'); 2478 classes.remove('shadow');
2429 } 2479 }
2430 if (_current) { 2480 if (_current) {
2431 classes.add('current'); 2481 classes.add('current');
2432 } else { 2482 } else {
2433 classes.remove('current'); 2483 classes.remove('current');
2434 } 2484 }
2485 if (_frame.kind == M.FrameKind.marker) {
2486 final content = <Element>[
2487 new SpanElement()..children = _createMarkerHeader(_frame.marker)
2488 ];
2489 children = content;
2490 return;
2491 }
2435 ButtonElement expandButton; 2492 ButtonElement expandButton;
2436 final content = <Element>[ 2493 final content = <Element>[
2437 expandButton = new ButtonElement() 2494 expandButton = new ButtonElement()
2438 ..children = _createHeader() 2495 ..children = _createHeader()
2439 ..onClick.listen((e) async { 2496 ..onClick.listen((e) async {
2440 if (e.target is AnchorElement) { 2497 if (e.target is AnchorElement) {
2441 return; 2498 return;
2442 } 2499 }
2443 expandButton.disabled = true; 2500 expandButton.disabled = true;
2444 await _toggleExpand(); 2501 await _toggleExpand();
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2527 collapseButton.disabled = false; 2584 collapseButton.disabled = false;
2528 }) 2585 })
2529 ..children = [iconExpandLess.clone(true)] 2586 ..children = [iconExpandLess.clone(true)]
2530 ] 2587 ]
2531 ] 2588 ]
2532 ]); 2589 ]);
2533 } 2590 }
2534 children = content; 2591 children = content;
2535 } 2592 }
2536 2593
2594 List<Element> _createMarkerHeader(String marker) {
2595 final content = [
2596 new DivElement()
2597 ..classes = ['frameSummaryText']
2598 ..children = [
2599 new DivElement()
2600 ..classes = ['frameId']
2601 ..text = 'Frame ${_frame.index}',
2602 new SpanElement()..text = '$marker',
2603 ]
2604 ];
2605 return [
2606 new DivElement()
2607 ..classes = ['frameSummary']
2608 ..children = content
2609 ];
2610 }
2611
2537 List<Element> _createHeader() { 2612 List<Element> _createHeader() {
2538 final content = [ 2613 final content = [
2539 new DivElement() 2614 new DivElement()
2540 ..classes = ['frameSummaryText'] 2615 ..classes = ['frameSummaryText']
2541 ..children = [ 2616 ..children = [
2542 new DivElement() 2617 new DivElement()
2543 ..classes = ['frameId'] 2618 ..classes = ['frameId']
2544 ..text = 'Frame ${_frame.index}', 2619 ..text = 'Frame ${_frame.index}',
2545 new SpanElement() 2620 new SpanElement()
2546 ..children = _frame.function == null 2621 ..children = _frame.function == null
(...skipping 24 matching lines...) Expand all
2571 ..classes = ['frameSummary'] 2646 ..classes = ['frameSummary']
2572 ..children = content 2647 ..children = content
2573 ]; 2648 ];
2574 } 2649 }
2575 2650
2576 String makeExpandKey(String key) { 2651 String makeExpandKey(String key) {
2577 return '${_frame.function.qualifiedName}/${key}'; 2652 return '${_frame.function.qualifiedName}/${key}';
2578 } 2653 }
2579 2654
2580 bool matchFrame(S.Frame newFrame) { 2655 bool matchFrame(S.Frame newFrame) {
2656 if (newFrame.function == null) {
2657 return frame.function == null;
2658 }
2581 return (newFrame.function.id == _frame.function.id && 2659 return (newFrame.function.id == _frame.function.id &&
2582 newFrame.location.script.id == 2660 newFrame.location.script.id ==
2583 frame.location.script.id); 2661 frame.location.script.id);
2584 } 2662 }
2585 2663
2586 void updateFrame(S.Frame newFrame) { 2664 void updateFrame(S.Frame newFrame) {
2587 assert(matchFrame(newFrame)); 2665 assert(matchFrame(newFrame));
2588 _frame = newFrame; 2666 _frame = newFrame;
2589 } 2667 }
2590 2668
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after
3257 ..setAttribute('height', '24') 3335 ..setAttribute('height', '24')
3258 ..children = [ 3336 ..children = [
3259 new PathElement() 3337 new PathElement()
3260 ..setAttribute( 3338 ..setAttribute(
3261 'd', 3339 'd',
3262 'M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 ' 3340 'M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 '
3263 '10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 ' 3341 '10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 '
3264 '0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 ' 3342 '0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 '
3265 '9h2V7h-2v2z') 3343 '9h2V7h-2v2z')
3266 ]; 3344 ];
OLDNEW
« no previous file with comments | « runtime/lib/stacktrace.cc ('k') | runtime/observatory/lib/src/models/objects/frame.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698