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

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

Issue 1584173003: Use getSourceReport for coverage/callsites in Observatory. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: cleanups Created 4 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 script_inset_element; 5 library script_inset_element;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:html'; 8 import 'dart:html';
9 import 'dart:math';
9 import 'observatory_element.dart'; 10 import 'observatory_element.dart';
10 import 'service_ref.dart'; 11 import 'service_ref.dart';
11 import 'package:observatory/service.dart'; 12 import 'package:observatory/service.dart';
12 import 'package:observatory/utils.dart'; 13 import 'package:observatory/utils.dart';
13 import 'package:polymer/polymer.dart'; 14 import 'package:polymer/polymer.dart';
14 import 'package:logging/logging.dart'; 15 import 'package:logging/logging.dart';
15 16
16 const nbsp = "\u00A0"; 17 const nbsp = "\u00A0";
17 18
18 void addInfoBox(Element content, Function infoBoxGenerator) { 19 void addInfoBox(Element content, Function infoBoxGenerator) {
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 details.append(row('Call of "${callSite.name}" did not execute')); 238 details.append(row('Call of "${callSite.name}" did not execute'));
238 } else { 239 } else {
239 var r = row(); 240 var r = row();
240 r.append(cell("Container")); 241 r.append(cell("Container"));
241 r.append(cell("Count")); 242 r.append(cell("Count"));
242 r.append(cell("Target")); 243 r.append(cell("Target"));
243 details.append(r); 244 details.append(r);
244 245
245 for (var entry in callSite.entries) { 246 for (var entry in callSite.entries) {
246 var r = row(); 247 var r = row();
247 r.append(cell(serviceRef(entry.receiverContainer))); 248 r.append(cell(serviceRef(entry.receiver)));
248 r.append(cell(entry.count.toString())); 249 r.append(cell(entry.count.toString()));
249 r.append(cell(serviceRef(entry.target))); 250 r.append(cell(serviceRef(entry.target)));
250 details.append(r); 251 details.append(r);
251 } 252 }
252 } 253 }
253 return details; 254 return details;
254 }); 255 });
255 } 256 }
256 } 257 }
257 258
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 @published int endPos; 368 @published int endPos;
368 369
369 /// Set the height to make the script inset scroll. Otherwise it 370 /// Set the height to make the script inset scroll. Otherwise it
370 /// will show from startPos to endPos. 371 /// will show from startPos to endPos.
371 @published String height = null; 372 @published String height = null;
372 373
373 @published int currentPos; 374 @published int currentPos;
374 @published bool inDebuggerContext = false; 375 @published bool inDebuggerContext = false;
375 @published ObservableList variables; 376 @published ObservableList variables;
376 377
378 @published Element scroller;
379 RefreshButtonElement _refreshButton;
380
377 int _currentLine; 381 int _currentLine;
378 int _currentCol; 382 int _currentCol;
379 int _startLine; 383 int _startLine;
380 int _endLine; 384 int _endLine;
381 385
386 Map<int, List<ServiceMap>> _rangeMap = {};
387 Set _callSites = new Set<CallSite>();
388
382 var annotations = []; 389 var annotations = [];
383 var annotationsCursor; 390 var annotationsCursor;
384 391
385 StreamSubscription _scriptChangeSubscription; 392 StreamSubscription _scriptChangeSubscription;
386 Future<StreamSubscription> _debugSubscriptionFuture; 393 Future<StreamSubscription> _debugSubscriptionFuture;
394 StreamSubscription _scrollSubscription;
387 395
388 bool hasLoadedLibraryDeclarations = false; 396 bool hasLoadedLibraryDeclarations = false;
389 397
390 String makeLineId(int line) { 398 String makeLineId(int line) {
391 return 'line-$line'; 399 return 'line-$line';
392 } 400 }
393 401
394 void _scrollToCurrentPos() { 402 void _scrollToCurrentPos() {
395 var line = shadowRoot.getElementById(makeLineId(_currentLine)); 403 var line = shadowRoot.getElementById(makeLineId(_currentLine));
396 if (line != null) { 404 if (line != null) {
397 line.scrollIntoView(); 405 line.scrollIntoView();
398 } 406 }
399 } 407 }
400 408
401 void attached() { 409 void attached() {
402 super.attached(); 410 super.attached();
403 _debugSubscriptionFuture = 411 _debugSubscriptionFuture =
404 app.vm.listenEventStream(VM.kDebugStream, _onDebugEvent); 412 app.vm.listenEventStream(VM.kDebugStream, _onDebugEvent);
413 if (scroller != null) {
414 _scrollSubscription = scroller.onScroll.listen(_onScroll);
415 } else {
416 _scrollSubscription = window.onScroll.listen(_onScroll);
417 }
405 } 418 }
406 419
407 void detached() { 420 void detached() {
408 cancelFutureSubscription(_debugSubscriptionFuture); 421 cancelFutureSubscription(_debugSubscriptionFuture);
409 _debugSubscriptionFuture = null; 422 _debugSubscriptionFuture = null;
423 if (_scrollSubscription != null) {
424 _scrollSubscription.cancel();
425 _scrollSubscription = null;
426 }
410 if (_scriptChangeSubscription != null) { 427 if (_scriptChangeSubscription != null) {
411 // Don't leak. If only Dart and Javascript exposed weak references... 428 // Don't leak. If only Dart and Javascript exposed weak references...
412 _scriptChangeSubscription.cancel(); 429 _scriptChangeSubscription.cancel();
413 _scriptChangeSubscription = null; 430 _scriptChangeSubscription = null;
414 } 431 }
415 super.detached(); 432 super.detached();
416 } 433 }
417 434
435 void _onScroll(event) {
436 var currentTop = _refreshButton.style.top;
437 var newTop = _refreshButtonTop();
438 if (currentTop != newTop) {
439 _refreshButton.style.top = '${newTop}px';
440 }
441 }
442
418 void _onDebugEvent(event) { 443 void _onDebugEvent(event) {
419 if (script == null) { 444 if (script == null) {
420 return; 445 return;
421 } 446 }
422 switch (event.kind) { 447 switch (event.kind) {
423 case ServiceEvent.kBreakpointAdded: 448 case ServiceEvent.kBreakpointAdded:
424 case ServiceEvent.kBreakpointResolved: 449 case ServiceEvent.kBreakpointResolved:
425 case ServiceEvent.kBreakpointRemoved: 450 case ServiceEvent.kBreakpointRemoved:
426 var loc = event.breakpoint.location; 451 var loc = event.breakpoint.location;
427 if (loc.script == script) { 452 if (loc.script == script) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 Element hitsNotExecuted(Element element) { 504 Element hitsNotExecuted(Element element) {
480 element.classes.add('hitsNotExecuted'); 505 element.classes.add('hitsNotExecuted');
481 element.title = "Line did not execute"; 506 element.title = "Line did not execute";
482 return element; 507 return element;
483 } 508 }
484 Element hitsExecuted(Element element) { 509 Element hitsExecuted(Element element) {
485 element.classes.add('hitsExecuted'); 510 element.classes.add('hitsExecuted');
486 element.title = "Line did execute"; 511 element.title = "Line did execute";
487 return element; 512 return element;
488 } 513 }
514 Element hitsCompiled(Element element) {
515 element.classes.add('hitsCompiled');
516 element.title = "Line in compiled function";
517 return element;
518 }
519 Element hitsNotCompiled(Element element) {
520 element.classes.add('hitsNotCompiled');
521 element.title = "Line in uncompiled function";
522 return element;
523 }
489 524
490 Element container; 525 Element container;
491 526
527 Future _refresh() async {
528 await update();
529 }
530
531 // Build _rangeMap and _callSites from a source report.
532 Future _refreshSourceReport() async {
533 var sourceReport = await script.isolate.getSourceReport(
534 [Isolate.kCallSitesReport], script, startPos, endPos);
535 _rangeMap.clear();
536 _callSites.clear();
537 for (var range in sourceReport['ranges']) {
538 int startLine = script.tokenToLine(range['startPos']);
539 int endLine = script.tokenToLine(range['endPos']);
540 for (var line = startLine; line <= endLine; line++) {
541 var rangeList = _rangeMap[line];
542 if (rangeList == null) {
543 _rangeMap[line] = [range];
544 } else {
545 rangeList.add(range);
546 }
547 }
548 var rangeCallSites = range['callSites'];
549 if (rangeCallSites != null) {
550 for (var callSiteMap in rangeCallSites) {
551 _callSites.add(new CallSite.fromMap(callSiteMap, script));
552 }
553 }
554 }
555 }
556
492 Task _updateTask; 557 Task _updateTask;
493 void update() { 558 Future update() async {
494 assert(_updateTask != null); 559 assert(_updateTask != null);
495 if (script == null) { 560 if (script == null) {
496 // We may have previously had a script. 561 // We may have previously had a script.
497 if (container != null) { 562 if (container != null) {
498 container.children.clear(); 563 container.children.clear();
499 } 564 }
500 return; 565 return;
501 } 566 }
502 if (!script.loaded) { 567 if (!script.loaded) {
503 script.load().then((_) => update()); 568 await script.load();
504 return;
505 } 569 }
506
507 if (_scriptChangeSubscription == null) { 570 if (_scriptChangeSubscription == null) {
508 _scriptChangeSubscription = script.changes.listen((_) => update()); 571 _scriptChangeSubscription = script.changes.listen((_) => update());
509 } 572 }
573 await _refreshSourceReport();
510 574
511 computeAnnotations(); 575 computeAnnotations();
512 576
513 var table = linesTable(); 577 var table = linesTable();
514 var firstBuild = false; 578 var firstBuild = false;
515 if (container == null) { 579 if (container == null) {
516 // Indirect to avoid deleting the style element. 580 // Indirect to avoid deleting the style element.
517 container = new DivElement(); 581 container = new DivElement();
518 shadowRoot.append(container); 582 shadowRoot.append(container);
519 firstBuild = true; 583 firstBuild = true;
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 // We annotate a field declaration with the field instead of the 860 // We annotate a field declaration with the field instead of the
797 // implicit getter or setter. 861 // implicit getter or setter.
798 var a = new FunctionDeclarationAnnotation(func, inspectLink(func)); 862 var a = new FunctionDeclarationAnnotation(func, inspectLink(func));
799 annotations.add(a); 863 annotations.add(a);
800 } 864 }
801 } 865 }
802 } 866 }
803 } 867 }
804 868
805 void addCallSiteAnnotations() { 869 void addCallSiteAnnotations() {
806 for (var callSite in script.callSites) { 870 for (var callSite in _callSites) {
807 annotations.add(new CallSiteAnnotation(callSite)); 871 annotations.add(new CallSiteAnnotation(callSite));
808 } 872 }
809 } 873 }
810 874
811 void addLocalVariableAnnotations() { 875 void addLocalVariableAnnotations() {
812 // We have local variable information. 876 // We have local variable information.
813 if (variables != null) { 877 if (variables != null) {
814 // For each variable. 878 // For each variable.
815 for (var variable in variables) { 879 for (var variable in variables) {
816 // Find variable usage locations. 880 // Find variable usage locations.
817 var locations = script.scanForLocalVariableLocations( 881 var locations = script.scanForLocalVariableLocations(
818 variable['name'], 882 variable['name'],
819 variable['_tokenPos'], 883 variable['_tokenPos'],
820 variable['_endTokenPos']); 884 variable['_endTokenPos']);
821 885
822 // Annotate locations. 886 // Annotate locations.
823 for (var location in locations) { 887 for (var location in locations) {
824 annotations.add(new LocalVariableAnnotation(location, 888 annotations.add(new LocalVariableAnnotation(location,
825 variable['value'])); 889 variable['value']));
826 } 890 }
827 } 891 }
828 } 892 }
829 } 893 }
830 894
895 int _refreshButtonTop() {
896 if (_refreshButton == null) {
897 return 5;
898 }
899 const padding = 5;
900 const navbarHeight = 40;
Cutch 2016/01/14 21:37:40 The navbarHeight constant is hardcoded in two plac
901 var rect = getBoundingClientRect();
902 var buttonHeight = _refreshButton.clientHeight;
903 return min(max(0, navbarHeight - rect.top) + padding,
904 rect.height - (buttonHeight + padding));
905 }
906
907 RefreshButtonElement _newRefreshButton() {
908 var button = new Element.tag('refresh-button');
909 button.style.position = 'absolute';
910 button.style.display = 'inline-block';
911 button.style.top = '${_refreshButtonTop()}px';
912 button.style.right = '5px';
913 button.callback = _refresh;
914 return button;
915 }
916
831 Element linesTable() { 917 Element linesTable() {
832 var table = new DivElement(); 918 var table = new DivElement();
833 table.classes.add("sourceTable"); 919 table.classes.add("sourceTable");
834 920
921 _refreshButton = _newRefreshButton();
922 table.append(_refreshButton);
923
835 if (_startLine == null || _endLine == null) { 924 if (_startLine == null || _endLine == null) {
836 return table; 925 return table;
837 } 926 }
838 927
839 var endLine = (endPos != null 928 var endLine = (endPos != null
840 ? script.tokenToLine(endPos) 929 ? script.tokenToLine(endPos)
841 : script.lines.length + script.lineOffset); 930 : script.lines.length + script.lineOffset);
842 var lineNumPad = endLine.toString().length; 931 var lineNumPad = endLine.toString().length;
843 932
844 annotationsCursor = 0; 933 annotationsCursor = 0;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 update(); 1055 update();
967 }); 1056 });
968 update(); 1057 update();
969 return e; 1058 return e;
970 } 1059 }
971 1060
972 Element lineNumberElement(ScriptLine line, int lineNumPad) { 1061 Element lineNumberElement(ScriptLine line, int lineNumPad) {
973 var lineNumber = line == null ? "..." : line.line; 1062 var lineNumber = line == null ? "..." : line.line;
974 var e = span("$nbsp${lineNumber.toString().padLeft(lineNumPad,nbsp)}$nbsp"); 1063 var e = span("$nbsp${lineNumber.toString().padLeft(lineNumPad,nbsp)}$nbsp");
975 e.classes.add('noCopy'); 1064 e.classes.add('noCopy');
976
977 if (lineNumber == _currentLine) { 1065 if (lineNumber == _currentLine) {
978 hitsCurrent(e); 1066 hitsCurrent(e);
979 } else if ((line == null) || (line.hits == null)) { 1067 return e;
1068 }
1069 var ranges = _rangeMap[lineNumber];
1070 if ((ranges == null) || ranges.isEmpty) {
1071 // This line is not code.
980 hitsUnknown(e); 1072 hitsUnknown(e);
981 } else if (line.hits == 0) { 1073 return e;
1074 }
1075 bool compiled = false;
1076 bool hasCallInfo = false;
1077 bool executed = false;
1078 for (var range in ranges) {
1079 if (range['compiled']) {
1080 compiled = true;
1081 for (var callSite in range['callSites']) {
1082 var callLine = line.script.tokenToLine(callSite['tokenPos']);
1083 if (lineNumber == callLine) {
1084 // The call site is on the current line.
1085 hasCallInfo = true;
1086 for (var cacheEntry in callSite['cacheEntries']) {
1087 if (cacheEntry['count'] > 0) {
1088 // If any call site on the line has been executed, we
1089 // mark the line as executed.
1090 executed = true;
1091 break;
1092 }
1093 }
1094 }
1095 }
1096 }
1097 }
1098 if (executed) {
1099 hitsExecuted(e);
1100 } else if (hasCallInfo) {
982 hitsNotExecuted(e); 1101 hitsNotExecuted(e);
1102 } else if (compiled) {
1103 hitsCompiled(e);
983 } else { 1104 } else {
984 hitsExecuted(e); 1105 hitsNotCompiled(e);
985 } 1106 }
986
987 return e; 1107 return e;
988 } 1108 }
989 1109
990 Element lineSourceElement(ScriptLine line) { 1110 Element lineSourceElement(ScriptLine line) {
991 var e = new DivElement(); 1111 var e = new DivElement();
992 e.classes.add("sourceItem"); 1112 e.classes.add("sourceItem");
993 1113
994 if (line != null) { 1114 if (line != null) {
995 if (line.line == _currentLine) { 1115 if (line.line == _currentLine) {
996 e.classes.add("currentLine"); 1116 e.classes.add("currentLine");
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 1149
1030 return e; 1150 return e;
1031 } 1151 }
1032 1152
1033 ScriptInsetElement.created() 1153 ScriptInsetElement.created()
1034 : super.created() { 1154 : super.created() {
1035 _updateTask = new Task(update); 1155 _updateTask = new Task(update);
1036 } 1156 }
1037 } 1157 }
1038 1158
1159 @CustomTag('refresh-button')
1160 class RefreshButtonElement extends PolymerElement {
1161 RefreshButtonElement.created() : super.created();
1162
1163 @published var callback = null;
1164 bool busy = false;
1165
1166 Future buttonClick(var event, var b, var c) async {
1167 if (busy) {
1168 return;
1169 }
1170 busy = true;
1171 if (callback != null) {
1172 await callback();
1173 }
1174 busy = false;
1175 }
1176 }
1177
1178
1039 @CustomTag('source-inset') 1179 @CustomTag('source-inset')
1040 class SourceInsetElement extends PolymerElement { 1180 class SourceInsetElement extends PolymerElement {
1041 SourceInsetElement.created() : super.created(); 1181 SourceInsetElement.created() : super.created();
1042 1182
1043 @published SourceLocation location; 1183 @published SourceLocation location;
1044 @published String height = null; 1184 @published String height = null;
1045 @published int currentPos; 1185 @published int currentPos;
1046 @published bool inDebuggerContext = false; 1186 @published bool inDebuggerContext = false;
1047 @published ObservableList variables; 1187 @published ObservableList variables;
1188 @published Element scroller;
1048 } 1189 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698