OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 ]; |
OLD | NEW |