Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 persitent_handles_page; | 5 library persitent_handles_page; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:html'; | 8 import 'dart:html'; |
| 9 import 'observatory_element.dart'; | 9 import 'package:observatory/models.dart' as M; |
| 10 import 'package:observatory/app.dart'; | 10 import 'package:observatory/src/elements/containers/virtual_collection.dart'; |
| 11 import 'package:observatory/elements.dart'; | 11 import 'package:observatory/src/elements/helpers/any_ref.dart'; |
| 12 import 'package:observatory/service.dart'; | 12 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
| 13 import 'package:polymer/polymer.dart'; | 13 import 'package:observatory/src/elements/helpers/tag.dart'; |
| 14 | 14 import 'package:observatory/src/elements/helpers/uris.dart'; |
| 15 class WeakPersistentHandlesSortedTable extends SortedTable { | 15 import 'package:observatory/src/elements/instance_ref.dart'; |
| 16 factory WeakPersistentHandlesSortedTable() { | 16 import 'package:observatory/src/elements/nav/bar.dart'; |
| 17 var columns = [ | 17 import 'package:observatory/src/elements/nav/isolate_menu.dart'; |
| 18 new SortedTableColumn.withFormatter('External Size', | 18 import 'package:observatory/src/elements/nav/menu.dart'; |
| 19 Utils.formatSize), | 19 import 'package:observatory/src/elements/nav/notify.dart'; |
| 20 new SortedTableColumn('Peer'), | 20 import 'package:observatory/src/elements/nav/refresh.dart'; |
| 21 new SortedTableColumn('Finalizer Callback'), | 21 import 'package:observatory/src/elements/nav/top_menu.dart'; |
| 22 new SortedTableColumn(''), // Spacer column. | 22 import 'package:observatory/src/elements/nav/vm_menu.dart'; |
| 23 new SortedTableColumn('Object'), | 23 import 'package:observatory/utils.dart'; |
| 24 | |
| 25 enum _SortingField { | |
| 26 externalSize, | |
| 27 peer, | |
| 28 finalizerCallback | |
| 29 } | |
| 30 | |
| 31 enum _SortingDirection { | |
| 32 ascending, | |
| 33 descending | |
| 34 } | |
| 35 | |
| 36 class PersistentHandlesPageElement extends HtmlElement implements Renderable { | |
| 37 static const tag = | |
| 38 const Tag<PersistentHandlesPageElement>('persistent-handles-page', | |
| 39 dependencies: const [ | |
| 40 InstanceRefElement.tag, | |
| 41 NavBarElement.tag, | |
| 42 NavTopMenuElement.tag, | |
| 43 NavVMMenuElement.tag, | |
| 44 NavIsolateMenuElement.tag, | |
| 45 NavMenuElement.tag, | |
| 46 NavRefreshElement.tag, | |
| 47 NavNotifyElement.tag, | |
| 48 VirtualCollectionElement.tag | |
| 49 ]); | |
| 50 | |
| 51 RenderingScheduler<PersistentHandlesPageElement> _r; | |
| 52 | |
| 53 Stream<RenderedEvent<PersistentHandlesPageElement>> get onRendered => | |
| 54 _r.onRendered; | |
| 55 | |
| 56 M.VM _vm; | |
| 57 M.IsolateRef _isolate; | |
| 58 M.EventRepository _events; | |
| 59 M.NotificationRepository _notifications; | |
| 60 M.PersistentHandlesRepository _repository; | |
| 61 M.InstanceRepository _instances; | |
| 62 M.PersistentHandles _handles; | |
| 63 _SortingField _sortingField = | |
| 64 _SortingField.externalSize; | |
| 65 _SortingDirection _sortingDirection = | |
| 66 _SortingDirection.descending; | |
| 67 | |
| 68 M.VMRef get vm => _vm; | |
| 69 M.IsolateRef get isolate => _isolate; | |
| 70 M.NotificationRepository get notifications => _notifications; | |
| 71 | |
| 72 factory PersistentHandlesPageElement(M.VM vm, M.IsolateRef isolate, | |
| 73 M.EventRepository events, | |
| 74 M.NotificationRepository notifications, | |
| 75 M.PersistentHandlesRepository repository, | |
| 76 M.InstanceRepository instances, | |
| 77 {RenderingQueue queue}) { | |
| 78 assert(vm != null); | |
| 79 assert(isolate != null); | |
| 80 assert(events != null); | |
| 81 assert(notifications != null); | |
| 82 assert(repository != null); | |
| 83 assert(instances != null); | |
| 84 PersistentHandlesPageElement e = document.createElement(tag.name); | |
| 85 e._r = new RenderingScheduler(e, queue: queue); | |
| 86 e._vm = vm; | |
| 87 e._isolate = isolate; | |
| 88 e._events = events; | |
| 89 e._notifications = notifications; | |
| 90 e._repository = repository; | |
| 91 e._instances = instances; | |
| 92 return e; | |
| 93 } | |
| 94 | |
| 95 PersistentHandlesPageElement.created() : super.created(); | |
| 96 | |
| 97 @override | |
| 98 attached() { | |
| 99 super.attached(); | |
| 100 _r.enable(); | |
| 101 _refresh(); | |
| 102 } | |
| 103 | |
| 104 @override | |
| 105 detached() { | |
| 106 super.detached(); | |
| 107 _r.disable(notify: true); | |
| 108 children = []; | |
| 109 } | |
| 110 | |
| 111 void render() { | |
| 112 children = ([ | |
| 113 new NavBarElement(queue: _r.queue) | |
| 114 ..children = [ | |
| 115 new NavTopMenuElement(queue: _r.queue), | |
| 116 new NavVMMenuElement(_vm, _events, queue: _r.queue), | |
| 117 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue), | |
| 118 new NavMenuElement('persistent handles', last: true, | |
| 119 link: Uris.persistentHandles(_isolate), queue: _r.queue), | |
| 120 new NavRefreshElement(queue: _r.queue) | |
| 121 ..onRefresh.listen((_) => _refresh()), | |
| 122 new NavNotifyElement(_notifications, queue: _r.queue) | |
| 123 ] | |
| 124 ]..addAll(_createPersistendHandlers()) | |
| 125 ..add(new BRElement()) | |
| 126 ..addAll(_createWeakPersistendHandlers())); | |
| 127 } | |
| 128 | |
| 129 List<Element> _createPersistendHandlers() { | |
|
Cutch
2016/08/25 22:27:28
It seems like it should be easy to merge _createPe
cbernaschina
2016/08/25 22:43:39
Done.
| |
| 130 return [ | |
| 131 new DivElement()..classes = const ['content-centered-big'] | |
| 132 ..children = [ | |
| 133 new HeadingElement.h1()..text = 'Persistent Handles', | |
| 134 new HRElement(), | |
| 135 ], | |
| 136 new DivElement()..classes = const ['persistent-handles'] | |
| 137 ..children = [ | |
| 138 _handles == null | |
| 139 ? (new HeadingElement.h2()..classes = const ['content-centered-big'] | |
| 140 ..text = 'Loading...') | |
| 141 : new VirtualCollectionElement( | |
| 142 _createLine, | |
| 143 _updateLine, | |
| 144 items: _handles.elements, | |
| 145 queue: _r.queue) | |
| 146 ] | |
| 24 ]; | 147 ]; |
| 25 WeakPersistentHandlesSortedTable result = | 148 } |
| 26 new WeakPersistentHandlesSortedTable._(columns); | 149 |
| 27 // Sort by external size. | 150 List<Element> _createWeakPersistendHandlers() { |
| 28 result.sortColumnIndex = 0; | 151 return [ |
| 29 return result; | 152 new DivElement()..classes = const ['content-centered-big'] |
| 30 } | 153 ..children = [ |
| 31 | 154 new HeadingElement.h1()..text = 'Weak Persistent Handles', |
| 32 WeakPersistentHandlesSortedTable._(columns) : super(columns); | 155 new HRElement(), |
| 33 | 156 ], |
| 34 @override | 157 new DivElement()..classes = const ['weak-persistent-handles'] |
| 35 dynamic getSortKeyFor(int row, int col) { | 158 ..children = [ |
| 36 return super.getSortKeyFor(row, col); | 159 _handles == null |
| 37 } | 160 ? (new HeadingElement.h2()..classes = const ['content-centered-big'] |
| 38 | 161 ..text = 'Loading...') |
| 39 void update(List<ServiceMap> handles, HtmlElement tableBody) { | 162 : new VirtualCollectionElement( |
| 40 clearRows(); | 163 _createWeakLine, |
| 41 for (ServiceMap handle in handles) { | 164 _updateWeakLine, |
| 42 var row = [int.parse(handle['externalSize'], onError: (_) => 0), | 165 createHeader: _createWeakHeader, |
| 43 handle['peer'], | 166 items: _handles.weakElements.toList()..sort(_createSorter()), |
| 44 handle['callbackSymbolName'] + | 167 queue: _r.queue) |
| 45 '( ${handle['callbackAddress']} )', | 168 ] |
| 46 '', // Spacer column. | 169 ]; |
| 47 handle['object']]; | 170 } |
| 48 addRow(new SortedTableRow(row)); | 171 |
| 49 print(row); | 172 _createSorter() { |
| 173 var getter; | |
| 174 switch (_sortingField) { | |
| 175 case _SortingField.externalSize: | |
| 176 getter = _getExternalSize; | |
| 177 break; | |
| 178 case _SortingField.peer: | |
| 179 getter = _getPeer; | |
| 180 break; | |
| 181 case _SortingField.finalizerCallback: | |
| 182 getter = _getFinalizerCallback; | |
| 183 break; | |
| 50 } | 184 } |
| 51 sort(); | 185 switch (_sortingDirection) { |
| 52 _updateTableInDom(tableBody); | 186 case _SortingDirection.ascending: |
| 53 } | 187 return (a, b) => getter(a).compareTo(getter(b)); |
| 54 | 188 case _SortingDirection.descending: |
| 55 void sortAndDisplay(HtmlElement tableBody) { | 189 return (a, b) => getter(b).compareTo(getter(a)); |
| 56 sort(); | 190 } |
| 57 _updateTableInDom(tableBody); | 191 } |
| 58 } | 192 |
| 59 | 193 static Element _createLine() => |
| 60 | 194 new DivElement()..classes = const ['collection-item'] |
| 61 void _updateTableInDom(HtmlElement tableBody) { | 195 ..text = 'object'; |
| 62 assert(tableBody != null); | 196 |
| 63 // Resize DOM table. | 197 static Element _createWeakLine() => |
| 64 if (tableBody.children.length > sortedRows.length) { | 198 new DivElement() |
| 65 // Shrink the table. | 199 ..classes = const ['weak-item'] |
| 66 var deadRows = | 200 ..children = [ |
| 67 tableBody.children.length - sortedRows.length; | 201 new SpanElement()..classes = const ['external-size'] |
| 68 for (var i = 0; i < deadRows; i++) { | 202 ..text = '0B', |
| 69 tableBody.children.removeLast(); | 203 new SpanElement()..classes = const ['peer'] |
| 204 ..text = '0x00000', | |
| 205 new SpanElement()..classes = const ['object'], | |
| 206 new SpanElement()..classes = const ['finalizer'] | |
| 207 ..text = 'dart::Class::Method()' | |
| 208 ]; | |
| 209 | |
| 210 Element _createWeakHeader() => | |
| 211 new DivElement() | |
| 212 ..classes = const ['weak-item'] | |
| 213 ..children = [ | |
| 214 _createHeaderButton(const ['external-size'], 'External Size', | |
| 215 _SortingField.externalSize, | |
| 216 _SortingDirection.descending), | |
| 217 _createHeaderButton(const ['peer'], 'Peer', | |
| 218 _SortingField.peer, | |
| 219 _SortingDirection.descending), | |
| 220 new SpanElement()..classes = const ['object'] | |
| 221 ..text = 'Object', | |
| 222 _createHeaderButton(const ['finalizer'], 'Finalizer Callback', | |
| 223 _SortingField.finalizerCallback, | |
| 224 _SortingDirection.ascending) | |
| 225 ]; | |
| 226 | |
| 227 ButtonElement _createHeaderButton(List<String> classes, | |
| 228 String text, | |
| 229 _SortingField field, | |
| 230 _SortingDirection direction) => | |
| 231 new ButtonElement()..classes = classes | |
| 232 ..text = _sortingField != field ? text : | |
| 233 _sortingDirection == _SortingDirection.ascending | |
| 234 ? '$textâ–¼' : '$textâ–²' | |
| 235 ..onClick.listen((_) => _setSorting(field, direction)); | |
| 236 | |
| 237 | |
| 238 void _setSorting(_SortingField field, | |
| 239 _SortingDirection defaultDirection) { | |
| 240 if (_sortingField == field) { | |
| 241 switch (_sortingDirection) { | |
| 242 case _SortingDirection.descending: | |
| 243 _sortingDirection = _SortingDirection.ascending; | |
| 244 break; | |
| 245 case _SortingDirection.ascending: | |
| 246 _sortingDirection = _SortingDirection.descending; | |
| 247 break; | |
| 70 } | 248 } |
| 71 } else if (tableBody.children.length < sortedRows.length) { | 249 } else { |
| 72 // Grow table. | 250 _sortingDirection = defaultDirection; |
| 73 var newRows = sortedRows.length - tableBody.children.length; | 251 _sortingField = field; |
| 74 for (var i = 0; i < newRows; i++) { | |
| 75 _addDomRow(tableBody); | |
| 76 } | |
| 77 } | 252 } |
| 78 assert(tableBody.children.length == sortedRows.length); | 253 _r.dirty(); |
| 79 // Fill table. | 254 } |
| 80 for (var i = 0; i < sortedRows.length; i++) { | 255 |
| 81 var rowIndex = sortedRows[i]; | 256 void _updateWeakLine(Element e, M.WeakPersistentHandle item, |
| 82 var tr = tableBody.children[i]; | 257 index) { |
| 83 _fillDomRow(tr, rowIndex); | 258 e.children[0].text = Utils.formatSize(_getExternalSize(item)); |
| 84 } | 259 e.children[1].text = '${_getPeer(item)}'; |
| 85 } | 260 e.children[2] = anyRef(_isolate, item.object, _instances, queue: _r.queue) |
| 86 | 261 ..classes = const ['object']; |
| 87 void _addDomRow(HtmlElement tableBody) { | 262 e.children[3]..text = '${_getFinalizerCallback(item)}' |
| 88 // Add empty dom row. | 263 ..title = '${_getFinalizerCallback(item)}'; |
| 89 var tr = new TableRowElement(); | 264 } |
| 90 | 265 |
| 91 var cell; | 266 void _updateLine(Element e, M.PersistentHandle item, |
| 92 | 267 index) { |
| 93 cell = tr.insertCell(-1); | 268 e.children = [ |
| 94 cell = tr.insertCell(-1); | 269 anyRef(_isolate, item.object, _instances, queue: _r.queue) |
| 95 cell = tr.insertCell(-1); | 270 ..classes = const ['object'] |
| 96 | 271 ]; |
| 97 // Add spacer. | 272 } |
| 98 cell = tr.insertCell(-1); | 273 |
| 99 cell.classes.add('left-border-spacer'); | 274 Future _refresh({bool gc: false, bool reset: false}) async { |
| 100 | 275 _handles = null; |
| 101 // Add class ref. | 276 _r.dirty(); |
| 102 cell = tr.insertCell(-1); | 277 _handles = await _repository.get(_isolate); |
| 103 AnyServiceRefElement objectRef = new Element.tag('any-service-ref'); | 278 _r.dirty(); |
| 104 cell.children.add(objectRef); | 279 } |
| 105 | 280 |
| 106 // Add row to table. | 281 static int _getExternalSize(M.WeakPersistentHandle h) => h.externalSize; |
| 107 tableBody.children.add(tr); | 282 static String _getPeer(M.WeakPersistentHandle h) => h.peer; |
| 108 } | 283 static String _getFinalizerCallback(M.WeakPersistentHandle h) => |
| 109 | 284 '${h.callbackSymbolName} (${h.callbackAddress})'; |
| 110 void _fillDomRow(TableRowElement tr, int rowIndex) { | |
| 111 var row = rows[rowIndex]; | |
| 112 | |
| 113 for (var i = 0; i < row.values.length - 2; i++) { | |
| 114 var cell = tr.children[i]; | |
| 115 cell.title = row.values[i].toString(); | |
| 116 cell.text = getFormattedValue(rowIndex, i); | |
| 117 cell.style.paddingLeft = '1em'; | |
| 118 cell.style.paddingRight = '1em'; | |
| 119 } | |
| 120 | |
| 121 final int objectIndex = row.values.length - 1; | |
| 122 AnyServiceRefElement objectRef = tr.children[objectIndex].children[0]; | |
| 123 objectRef.ref = row.values[objectIndex]; | |
| 124 } | |
| 125 } | 285 } |
| 126 | |
| 127 | |
| 128 @CustomTag('persistent-handles-page') | |
| 129 class PersistentHandlesPageElement extends ObservatoryElement { | |
| 130 PersistentHandlesPageElement.created() : super.created(); | |
| 131 | |
| 132 @observable Isolate isolate; | |
| 133 @observable var /*ObservableList | ServiceObject*/ persistentHandles; | |
| 134 @observable var /*ObservableList | ServiceObject*/ weakPersistentHandles; | |
| 135 @observable WeakPersistentHandlesSortedTable weakPersistentHandlesTable; | |
| 136 var _weakPersistentHandlesTableBody; | |
| 137 | |
| 138 void isolateChanged(oldValue) { | |
| 139 if (isolate != null) { | |
| 140 refresh(); | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 @override | |
| 145 void attached() { | |
| 146 super.attached(); | |
| 147 _weakPersistentHandlesTableBody = | |
| 148 shadowRoot.querySelector('#weakPersistentHandlesTableBody'); | |
| 149 weakPersistentHandlesTable = | |
| 150 new WeakPersistentHandlesSortedTable(); | |
| 151 } | |
| 152 | |
| 153 Future refresh() { | |
| 154 return isolate.getPersistentHandles().then(_refreshView); | |
| 155 } | |
| 156 | |
| 157 _refreshView(/*ObservableList | ServiceObject*/ object) { | |
| 158 persistentHandles = object['persistentHandles']; | |
| 159 weakPersistentHandles = object['weakPersistentHandles']; | |
| 160 weakPersistentHandlesTable.update( | |
| 161 weakPersistentHandles, | |
| 162 _weakPersistentHandlesTableBody); | |
| 163 } | |
| 164 | |
| 165 @observable void changeSort(Event e, var detail, Element target) { | |
| 166 if (target is TableCellElement) { | |
| 167 if (weakPersistentHandlesTable.sortColumnIndex != target.cellIndex) { | |
| 168 weakPersistentHandlesTable.sortColumnIndex = target.cellIndex; | |
| 169 weakPersistentHandlesTable.sortDescending = true; | |
| 170 } else { | |
| 171 weakPersistentHandlesTable.sortDescending = | |
| 172 !weakPersistentHandlesTable.sortDescending; | |
| 173 } | |
| 174 weakPersistentHandlesTable.sortAndDisplay( | |
| 175 _weakPersistentHandlesTableBody); | |
| 176 } | |
| 177 } | |
| 178 } | |
| OLD | NEW |