| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| 11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
| 13 * distribution. | 13 * distribution. |
| 14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
| 15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
| 16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
| 17 * | 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | |
| 31 /** | 30 /** |
| 32 * @constructor | 31 * @unrestricted |
| 33 * @extends {WebInspector.DataGridNode} | |
| 34 * @param {!WebInspector.HeapSnapshotSortableDataGrid} tree | |
| 35 * @param {boolean} hasChildren | |
| 36 */ | 32 */ |
| 37 WebInspector.HeapSnapshotGridNode = function(tree, hasChildren) | 33 WebInspector.HeapSnapshotGridNode = class extends WebInspector.DataGridNode { |
| 38 { | 34 /** |
| 39 WebInspector.DataGridNode.call(this, null, hasChildren); | 35 * @param {!WebInspector.HeapSnapshotSortableDataGrid} tree |
| 36 * @param {boolean} hasChildren |
| 37 */ |
| 38 constructor(tree, hasChildren) { |
| 39 super(null, hasChildren); |
| 40 this._dataGrid = tree; | 40 this._dataGrid = tree; |
| 41 this._instanceCount = 0; | 41 this._instanceCount = 0; |
| 42 | 42 |
| 43 this._savedChildren = null; | 43 this._savedChildren = null; |
| 44 /** | 44 /** |
| 45 * List of position ranges for all visible nodes: [startPos1, endPos1),...,[
startPosN, endPosN) | 45 * List of position ranges for all visible nodes: [startPos1, endPos1),...,[
startPosN, endPosN) |
| 46 * Position is an item position in the provider. | 46 * Position is an item position in the provider. |
| 47 */ | 47 */ |
| 48 this._retrievedChildrenRanges = []; | 48 this._retrievedChildrenRanges = []; |
| 49 | 49 |
| 50 /** | 50 /** |
| 51 * @type {?WebInspector.HeapSnapshotGridNode.ChildrenProvider} | 51 * @type {?WebInspector.HeapSnapshotGridNode.ChildrenProvider} |
| 52 */ | 52 */ |
| 53 this._providerObject = null; | 53 this._providerObject = null; |
| 54 this._reachableFromWindow = false; |
| 55 } |
| 56 |
| 57 /** |
| 58 * @param {!Array.<string>} fieldNames |
| 59 * @return {!WebInspector.HeapSnapshotCommon.ComparatorConfig} |
| 60 */ |
| 61 static createComparator(fieldNames) { |
| 62 return /** @type {!WebInspector.HeapSnapshotCommon.ComparatorConfig} */ ( |
| 63 {fieldName1: fieldNames[0], ascending1: fieldNames[1], fieldName2: field
Names[2], ascending2: fieldNames[3]}); |
| 64 } |
| 65 |
| 66 /** |
| 67 * @return {!WebInspector.HeapSnapshotSortableDataGrid} |
| 68 */ |
| 69 heapSnapshotDataGrid() { |
| 70 return this._dataGrid; |
| 71 } |
| 72 |
| 73 /** |
| 74 * @return {!WebInspector.HeapSnapshotGridNode.ChildrenProvider} |
| 75 */ |
| 76 createProvider() { |
| 77 throw new Error('Not implemented.'); |
| 78 } |
| 79 |
| 80 /** |
| 81 * @return {?{snapshot:!WebInspector.HeapSnapshotProxy, snapshotNodeIndex:numb
er}} |
| 82 */ |
| 83 retainersDataSource() { |
| 84 return null; |
| 85 } |
| 86 |
| 87 /** |
| 88 * @return {!WebInspector.HeapSnapshotGridNode.ChildrenProvider} |
| 89 */ |
| 90 _provider() { |
| 91 if (!this._providerObject) |
| 92 this._providerObject = this.createProvider(); |
| 93 return this._providerObject; |
| 94 } |
| 95 |
| 96 /** |
| 97 * @override |
| 98 * @param {string} columnId |
| 99 * @return {!Element} |
| 100 */ |
| 101 createCell(columnId) { |
| 102 var cell = super.createCell(columnId); |
| 103 if (this._searchMatched) |
| 104 cell.classList.add('highlight'); |
| 105 return cell; |
| 106 } |
| 107 |
| 108 /** |
| 109 * @override |
| 110 */ |
| 111 collapse() { |
| 112 super.collapse(); |
| 113 this._dataGrid.updateVisibleNodes(true); |
| 114 } |
| 115 |
| 116 /** |
| 117 * @override |
| 118 */ |
| 119 expand() { |
| 120 super.expand(); |
| 121 this._dataGrid.updateVisibleNodes(true); |
| 122 } |
| 123 |
| 124 dispose() { |
| 125 if (this._providerObject) |
| 126 this._providerObject.dispose(); |
| 127 for (var node = this.children[0]; node; node = node.traverseNextNode(true, t
his, true)) |
| 128 if (node.dispose) |
| 129 node.dispose(); |
| 130 } |
| 131 |
| 132 /** |
| 133 * @param {!WebInspector.Target} target |
| 134 * @param {function(!WebInspector.RemoteObject)} callback |
| 135 * @param {string} objectGroupName |
| 136 */ |
| 137 queryObjectContent(target, callback, objectGroupName) { |
| 138 } |
| 139 |
| 140 /** |
| 141 * @override |
| 142 */ |
| 143 wasDetached() { |
| 144 this._dataGrid.nodeWasDetached(this); |
| 145 } |
| 146 |
| 147 /** |
| 148 * @param {number} num |
| 149 * @return {string} |
| 150 */ |
| 151 _toPercentString(num) { |
| 152 return num.toFixed(0) + '\u2009%'; // \u2009 is a thin space. |
| 153 } |
| 154 |
| 155 /** |
| 156 * @param {number} distance |
| 157 * @return {string} |
| 158 */ |
| 159 _toUIDistance(distance) { |
| 160 var baseSystemDistance = WebInspector.HeapSnapshotCommon.baseSystemDistance; |
| 161 return distance >= 0 && distance < baseSystemDistance ? WebInspector.UIStrin
g('%d', distance) : |
| 162 WebInspector.UIStrin
g('\u2212'); |
| 163 } |
| 164 |
| 165 /** |
| 166 * @return {!Array.<!WebInspector.DataGridNode>} |
| 167 */ |
| 168 allChildren() { |
| 169 return this._dataGrid.allChildren(this); |
| 170 } |
| 171 |
| 172 /** |
| 173 * @param {number} index |
| 174 */ |
| 175 removeChildByIndex(index) { |
| 176 this._dataGrid.removeChildByIndex(this, index); |
| 177 } |
| 178 |
| 179 /** |
| 180 * @param {number} nodePosition |
| 181 * @return {?WebInspector.DataGridNode} |
| 182 */ |
| 183 childForPosition(nodePosition) { |
| 184 var indexOfFirstChildInRange = 0; |
| 185 for (var i = 0; i < this._retrievedChildrenRanges.length; i++) { |
| 186 var range = this._retrievedChildrenRanges[i]; |
| 187 if (range.from <= nodePosition && nodePosition < range.to) { |
| 188 var childIndex = indexOfFirstChildInRange + nodePosition - range.from; |
| 189 return this.allChildren()[childIndex]; |
| 190 } |
| 191 indexOfFirstChildInRange += range.to - range.from + 1; |
| 192 } |
| 193 return null; |
| 194 } |
| 195 |
| 196 /** |
| 197 * @param {string} columnId |
| 198 * @return {!Element} |
| 199 */ |
| 200 _createValueCell(columnId) { |
| 201 var cell = createElement('td'); |
| 202 cell.className = 'numeric-column'; |
| 203 if (this.dataGrid.snapshot.totalSize !== 0) { |
| 204 var div = createElement('div'); |
| 205 var valueSpan = createElement('span'); |
| 206 valueSpan.textContent = this.data[columnId]; |
| 207 div.appendChild(valueSpan); |
| 208 var percentColumn = columnId + '-percent'; |
| 209 if (percentColumn in this.data) { |
| 210 var percentSpan = createElement('span'); |
| 211 percentSpan.className = 'percent-column'; |
| 212 percentSpan.textContent = this.data[percentColumn]; |
| 213 div.appendChild(percentSpan); |
| 214 div.classList.add('profile-multiple-values'); |
| 215 } |
| 216 cell.appendChild(div); |
| 217 } |
| 218 return cell; |
| 219 } |
| 220 |
| 221 /** |
| 222 * @override |
| 223 */ |
| 224 populate() { |
| 225 if (this._populated) |
| 226 return; |
| 227 this._populated = true; |
| 228 this._provider().sortAndRewind(this.comparator()).then(this._populateChildre
n.bind(this)); |
| 229 } |
| 230 |
| 231 /** |
| 232 * @return {!Promise<?>} |
| 233 */ |
| 234 expandWithoutPopulate() { |
| 235 // Make sure default populate won't take action. |
| 236 this._populated = true; |
| 237 this.expand(); |
| 238 return this._provider().sortAndRewind(this.comparator()); |
| 239 } |
| 240 |
| 241 /** |
| 242 * @param {?number=} fromPosition |
| 243 * @param {?number=} toPosition |
| 244 * @param {function()=} afterPopulate |
| 245 */ |
| 246 _populateChildren(fromPosition, toPosition, afterPopulate) { |
| 247 fromPosition = fromPosition || 0; |
| 248 toPosition = toPosition || fromPosition + this._dataGrid.defaultPopulateCoun
t(); |
| 249 var firstNotSerializedPosition = fromPosition; |
| 250 |
| 251 /** |
| 252 * @this {WebInspector.HeapSnapshotGridNode} |
| 253 */ |
| 254 function serializeNextChunk() { |
| 255 if (firstNotSerializedPosition >= toPosition) |
| 256 return; |
| 257 var end = Math.min(firstNotSerializedPosition + this._dataGrid.defaultPopu
lateCount(), toPosition); |
| 258 this._provider().serializeItemsRange(firstNotSerializedPosition, end, chil
drenRetrieved.bind(this)); |
| 259 firstNotSerializedPosition = end; |
| 260 } |
| 261 |
| 262 /** |
| 263 * @this {WebInspector.HeapSnapshotGridNode} |
| 264 */ |
| 265 function insertRetrievedChild(item, insertionIndex) { |
| 266 if (this._savedChildren) { |
| 267 var hash = this._childHashForEntity(item); |
| 268 if (hash in this._savedChildren) { |
| 269 this._dataGrid.insertChild(this, this._savedChildren[hash], insertionI
ndex); |
| 270 return; |
| 271 } |
| 272 } |
| 273 this._dataGrid.insertChild(this, this._createChildNode(item), insertionInd
ex); |
| 274 } |
| 275 |
| 276 /** |
| 277 * @this {WebInspector.HeapSnapshotGridNode} |
| 278 */ |
| 279 function insertShowMoreButton(from, to, insertionIndex) { |
| 280 var button = new WebInspector.ShowMoreDataGridNode( |
| 281 this._populateChildren.bind(this), from, to, this._dataGrid.defaultPop
ulateCount()); |
| 282 this._dataGrid.insertChild(this, button, insertionIndex); |
| 283 } |
| 284 |
| 285 /** |
| 286 * @param {!WebInspector.HeapSnapshotCommon.ItemsRange} itemsRange |
| 287 * @this {WebInspector.HeapSnapshotGridNode} |
| 288 */ |
| 289 function childrenRetrieved(itemsRange) { |
| 290 var itemIndex = 0; |
| 291 var itemPosition = itemsRange.startPosition; |
| 292 var items = itemsRange.items; |
| 293 var insertionIndex = 0; |
| 294 |
| 295 if (!this._retrievedChildrenRanges.length) { |
| 296 if (itemsRange.startPosition > 0) { |
| 297 this._retrievedChildrenRanges.push({from: 0, to: 0}); |
| 298 insertShowMoreButton.call(this, 0, itemsRange.startPosition, insertion
Index++); |
| 299 } |
| 300 this._retrievedChildrenRanges.push({from: itemsRange.startPosition, to:
itemsRange.endPosition}); |
| 301 for (var i = 0, l = items.length; i < l; ++i) |
| 302 insertRetrievedChild.call(this, items[i], insertionIndex++); |
| 303 if (itemsRange.endPosition < itemsRange.totalLength) |
| 304 insertShowMoreButton.call(this, itemsRange.endPosition, itemsRange.tot
alLength, insertionIndex++); |
| 305 } else { |
| 306 var rangeIndex = 0; |
| 307 var found = false; |
| 308 var range; |
| 309 while (rangeIndex < this._retrievedChildrenRanges.length) { |
| 310 range = this._retrievedChildrenRanges[rangeIndex]; |
| 311 if (range.to >= itemPosition) { |
| 312 found = true; |
| 313 break; |
| 314 } |
| 315 insertionIndex += range.to - range.from; |
| 316 // Skip the button if there is one. |
| 317 if (range.to < itemsRange.totalLength) |
| 318 insertionIndex += 1; |
| 319 ++rangeIndex; |
| 320 } |
| 321 |
| 322 if (!found || itemsRange.startPosition < range.from) { |
| 323 // Update previous button. |
| 324 this.allChildren()[insertionIndex - 1].setEndPosition(itemsRange.start
Position); |
| 325 insertShowMoreButton.call( |
| 326 this, itemsRange.startPosition, found ? range.from : itemsRange.to
talLength, insertionIndex); |
| 327 range = {from: itemsRange.startPosition, to: itemsRange.startPosition}
; |
| 328 if (!found) |
| 329 rangeIndex = this._retrievedChildrenRanges.length; |
| 330 this._retrievedChildrenRanges.splice(rangeIndex, 0, range); |
| 331 } else { |
| 332 insertionIndex += itemPosition - range.from; |
| 333 } |
| 334 // At this point insertionIndex is always an index before button or betw
een nodes. |
| 335 // Also it is always true here that range.from <= itemPosition <= range.
to |
| 336 |
| 337 // Stretch the range right bound to include all new items. |
| 338 while (range.to < itemsRange.endPosition) { |
| 339 // Skip already added nodes. |
| 340 var skipCount = range.to - itemPosition; |
| 341 insertionIndex += skipCount; |
| 342 itemIndex += skipCount; |
| 343 itemPosition = range.to; |
| 344 |
| 345 // We're at the position before button: ...<?node>x<button> |
| 346 var nextRange = this._retrievedChildrenRanges[rangeIndex + 1]; |
| 347 var newEndOfRange = nextRange ? nextRange.from : itemsRange.totalLengt
h; |
| 348 if (newEndOfRange > itemsRange.endPosition) |
| 349 newEndOfRange = itemsRange.endPosition; |
| 350 while (itemPosition < newEndOfRange) { |
| 351 insertRetrievedChild.call(this, items[itemIndex++], insertionIndex++
); |
| 352 ++itemPosition; |
| 353 } |
| 354 |
| 355 // Merge with the next range. |
| 356 if (nextRange && newEndOfRange === nextRange.from) { |
| 357 range.to = nextRange.to; |
| 358 // Remove "show next" button if there is one. |
| 359 this.removeChildByIndex(insertionIndex); |
| 360 this._retrievedChildrenRanges.splice(rangeIndex + 1, 1); |
| 361 } else { |
| 362 range.to = newEndOfRange; |
| 363 // Remove or update next button. |
| 364 if (newEndOfRange === itemsRange.totalLength) |
| 365 this.removeChildByIndex(insertionIndex); |
| 366 else |
| 367 this.allChildren()[insertionIndex].setStartPosition(itemsRange.end
Position); |
| 368 } |
| 369 } |
| 370 } |
| 371 |
| 372 // TODO: fix this. |
| 373 this._instanceCount += items.length; |
| 374 if (firstNotSerializedPosition < toPosition) { |
| 375 serializeNextChunk.call(this); |
| 376 return; |
| 377 } |
| 378 |
| 379 if (this.expanded) |
| 380 this._dataGrid.updateVisibleNodes(true); |
| 381 if (afterPopulate) |
| 382 afterPopulate(); |
| 383 this.dispatchEventToListeners(WebInspector.HeapSnapshotGridNode.Events.Pop
ulateComplete); |
| 384 } |
| 385 serializeNextChunk.call(this); |
| 386 } |
| 387 |
| 388 _saveChildren() { |
| 389 this._savedChildren = null; |
| 390 var children = this.allChildren(); |
| 391 for (var i = 0, l = children.length; i < l; ++i) { |
| 392 var child = children[i]; |
| 393 if (!child.expanded) |
| 394 continue; |
| 395 if (!this._savedChildren) |
| 396 this._savedChildren = {}; |
| 397 this._savedChildren[this._childHashForNode(child)] = child; |
| 398 } |
| 399 } |
| 400 |
| 401 sort() { |
| 402 this._dataGrid.recursiveSortingEnter(); |
| 403 |
| 404 /** |
| 405 * @this {WebInspector.HeapSnapshotGridNode} |
| 406 */ |
| 407 function afterSort() { |
| 408 this._saveChildren(); |
| 409 this._dataGrid.removeAllChildren(this); |
| 410 this._retrievedChildrenRanges = []; |
| 411 |
| 412 /** |
| 413 * @this {WebInspector.HeapSnapshotGridNode} |
| 414 */ |
| 415 function afterPopulate() { |
| 416 var children = this.allChildren(); |
| 417 for (var i = 0, l = children.length; i < l; ++i) { |
| 418 var child = children[i]; |
| 419 if (child.expanded) |
| 420 child.sort(); |
| 421 } |
| 422 this._dataGrid.recursiveSortingLeave(); |
| 423 } |
| 424 var instanceCount = this._instanceCount; |
| 425 this._instanceCount = 0; |
| 426 this._populateChildren(0, instanceCount, afterPopulate.bind(this)); |
| 427 } |
| 428 |
| 429 this._provider().sortAndRewind(this.comparator()).then(afterSort.bind(this))
; |
| 430 } |
| 54 }; | 431 }; |
| 55 | 432 |
| 56 /** @enum {symbol} */ | 433 /** @enum {symbol} */ |
| 57 WebInspector.HeapSnapshotGridNode.Events = { | 434 WebInspector.HeapSnapshotGridNode.Events = { |
| 58 PopulateComplete: Symbol("PopulateComplete") | 435 PopulateComplete: Symbol('PopulateComplete') |
| 59 }; | |
| 60 | |
| 61 /** | |
| 62 * @param {!Array.<string>} fieldNames | |
| 63 * @return {!WebInspector.HeapSnapshotCommon.ComparatorConfig} | |
| 64 */ | |
| 65 WebInspector.HeapSnapshotGridNode.createComparator = function(fieldNames) | |
| 66 { | |
| 67 return /** @type {!WebInspector.HeapSnapshotCommon.ComparatorConfig} */ ({fi
eldName1: fieldNames[0], ascending1: fieldNames[1], fieldName2: fieldNames[2], a
scending2: fieldNames[3]}); | |
| 68 }; | 436 }; |
| 69 | 437 |
| 70 | 438 |
| 71 /** | 439 /** |
| 72 * @interface | 440 * @interface |
| 73 */ | 441 */ |
| 74 WebInspector.HeapSnapshotGridNode.ChildrenProvider = function() { }; | 442 WebInspector.HeapSnapshotGridNode.ChildrenProvider = function() {}; |
| 75 | 443 |
| 76 WebInspector.HeapSnapshotGridNode.ChildrenProvider.prototype = { | 444 WebInspector.HeapSnapshotGridNode.ChildrenProvider.prototype = { |
| 77 dispose: function() { }, | 445 dispose: function() {}, |
| 78 | 446 |
| 79 /** | 447 /** |
| 80 * @param {number} snapshotObjectId | 448 * @param {number} snapshotObjectId |
| 81 * @return {!Promise<number>} | 449 * @return {!Promise<number>} |
| 82 */ | 450 */ |
| 83 nodePosition: function(snapshotObjectId) { }, | 451 nodePosition: function(snapshotObjectId) {}, |
| 84 | 452 |
| 85 /** | 453 /** |
| 86 * @param {function(boolean)} callback | 454 * @param {function(boolean)} callback |
| 87 */ | 455 */ |
| 88 isEmpty: function(callback) { }, | 456 isEmpty: function(callback) {}, |
| 89 | 457 |
| 90 /** | 458 /** |
| 91 * @param {number} startPosition | 459 * @param {number} startPosition |
| 92 * @param {number} endPosition | 460 * @param {number} endPosition |
| 93 * @param {function(!WebInspector.HeapSnapshotCommon.ItemsRange)} callback | 461 * @param {function(!WebInspector.HeapSnapshotCommon.ItemsRange)} callback |
| 94 */ | 462 */ |
| 95 serializeItemsRange: function(startPosition, endPosition, callback) { }, | 463 serializeItemsRange: function(startPosition, endPosition, callback) {}, |
| 96 | 464 |
| 97 /** | 465 /** |
| 98 * @param {!WebInspector.HeapSnapshotCommon.ComparatorConfig} comparator | 466 * @param {!WebInspector.HeapSnapshotCommon.ComparatorConfig} comparator |
| 99 * @return {!Promise<?>} | 467 * @return {!Promise<?>} |
| 100 */ | 468 */ |
| 101 sortAndRewind: function(comparator) { } | 469 sortAndRewind: function(comparator) {} |
| 102 }; | 470 }; |
| 103 | 471 |
| 104 | |
| 105 WebInspector.HeapSnapshotGridNode.prototype = { | |
| 106 /** | |
| 107 * @return {!WebInspector.HeapSnapshotSortableDataGrid} | |
| 108 */ | |
| 109 heapSnapshotDataGrid: function() | |
| 110 { | |
| 111 return this._dataGrid; | |
| 112 }, | |
| 113 | |
| 114 /** | |
| 115 * @return {!WebInspector.HeapSnapshotGridNode.ChildrenProvider} | |
| 116 */ | |
| 117 createProvider: function() | |
| 118 { | |
| 119 throw new Error("Not implemented."); | |
| 120 }, | |
| 121 | |
| 122 /** | |
| 123 * @return {?{snapshot:!WebInspector.HeapSnapshotProxy, snapshotNodeIndex:nu
mber}} | |
| 124 */ | |
| 125 retainersDataSource: function() | |
| 126 { | |
| 127 return null; | |
| 128 }, | |
| 129 | |
| 130 /** | |
| 131 * @return {!WebInspector.HeapSnapshotGridNode.ChildrenProvider} | |
| 132 */ | |
| 133 _provider: function() | |
| 134 { | |
| 135 if (!this._providerObject) | |
| 136 this._providerObject = this.createProvider(); | |
| 137 return this._providerObject; | |
| 138 }, | |
| 139 | |
| 140 /** | |
| 141 * @override | |
| 142 * @param {string} columnId | |
| 143 * @return {!Element} | |
| 144 */ | |
| 145 createCell: function(columnId) | |
| 146 { | |
| 147 var cell = WebInspector.DataGridNode.prototype.createCell.call(this, col
umnId); | |
| 148 if (this._searchMatched) | |
| 149 cell.classList.add("highlight"); | |
| 150 return cell; | |
| 151 }, | |
| 152 | |
| 153 /** | |
| 154 * @override | |
| 155 */ | |
| 156 collapse: function() | |
| 157 { | |
| 158 WebInspector.DataGridNode.prototype.collapse.call(this); | |
| 159 this._dataGrid.updateVisibleNodes(true); | |
| 160 }, | |
| 161 | |
| 162 /** | |
| 163 * @override | |
| 164 */ | |
| 165 expand: function() | |
| 166 { | |
| 167 WebInspector.DataGridNode.prototype.expand.call(this); | |
| 168 this._dataGrid.updateVisibleNodes(true); | |
| 169 }, | |
| 170 | |
| 171 dispose: function() | |
| 172 { | |
| 173 if (this._providerObject) | |
| 174 this._providerObject.dispose(); | |
| 175 for (var node = this.children[0]; node; node = node.traverseNextNode(tru
e, this, true)) | |
| 176 if (node.dispose) | |
| 177 node.dispose(); | |
| 178 }, | |
| 179 | |
| 180 _reachableFromWindow: false, | |
| 181 | |
| 182 queryObjectContent: function(callback) | |
| 183 { | |
| 184 }, | |
| 185 | |
| 186 /** | |
| 187 * @override | |
| 188 */ | |
| 189 wasDetached: function() | |
| 190 { | |
| 191 this._dataGrid.nodeWasDetached(this); | |
| 192 }, | |
| 193 | |
| 194 /** | |
| 195 * @param {number} num | |
| 196 * @return {string} | |
| 197 */ | |
| 198 _toPercentString: function(num) | |
| 199 { | |
| 200 return num.toFixed(0) + "\u2009%"; // \u2009 is a thin space. | |
| 201 }, | |
| 202 | |
| 203 /** | |
| 204 * @param {number} distance | |
| 205 * @return {string} | |
| 206 */ | |
| 207 _toUIDistance: function(distance) | |
| 208 { | |
| 209 var baseSystemDistance = WebInspector.HeapSnapshotCommon.baseSystemDista
nce; | |
| 210 return distance >= 0 && distance < baseSystemDistance ? WebInspector.UIS
tring("%d", distance) : WebInspector.UIString("\u2212"); | |
| 211 }, | |
| 212 | |
| 213 /** | |
| 214 * @return {!Array.<!WebInspector.DataGridNode>} | |
| 215 */ | |
| 216 allChildren: function() | |
| 217 { | |
| 218 return this._dataGrid.allChildren(this); | |
| 219 }, | |
| 220 | |
| 221 /** | |
| 222 * @param {number} index | |
| 223 */ | |
| 224 removeChildByIndex: function(index) | |
| 225 { | |
| 226 this._dataGrid.removeChildByIndex(this, index); | |
| 227 }, | |
| 228 | |
| 229 /** | |
| 230 * @param {number} nodePosition | |
| 231 * @return {?WebInspector.DataGridNode} | |
| 232 */ | |
| 233 childForPosition: function(nodePosition) | |
| 234 { | |
| 235 var indexOfFirstChildInRange = 0; | |
| 236 for (var i = 0; i < this._retrievedChildrenRanges.length; i++) { | |
| 237 var range = this._retrievedChildrenRanges[i]; | |
| 238 if (range.from <= nodePosition && nodePosition < range.to) { | |
| 239 var childIndex = indexOfFirstChildInRange + nodePosition - range
.from; | |
| 240 return this.allChildren()[childIndex]; | |
| 241 } | |
| 242 indexOfFirstChildInRange += range.to - range.from + 1; | |
| 243 } | |
| 244 return null; | |
| 245 }, | |
| 246 | |
| 247 /** | |
| 248 * @param {string} columnId | |
| 249 * @return {!Element} | |
| 250 */ | |
| 251 _createValueCell: function(columnId) | |
| 252 { | |
| 253 var cell = createElement("td"); | |
| 254 cell.className = "numeric-column"; | |
| 255 if (this.dataGrid.snapshot.totalSize !== 0) { | |
| 256 var div = createElement("div"); | |
| 257 var valueSpan = createElement("span"); | |
| 258 valueSpan.textContent = this.data[columnId]; | |
| 259 div.appendChild(valueSpan); | |
| 260 var percentColumn = columnId + "-percent"; | |
| 261 if (percentColumn in this.data) { | |
| 262 var percentSpan = createElement("span"); | |
| 263 percentSpan.className = "percent-column"; | |
| 264 percentSpan.textContent = this.data[percentColumn]; | |
| 265 div.appendChild(percentSpan); | |
| 266 div.classList.add("profile-multiple-values"); | |
| 267 } | |
| 268 cell.appendChild(div); | |
| 269 } | |
| 270 return cell; | |
| 271 }, | |
| 272 | |
| 273 populate: function(event) | |
| 274 { | |
| 275 if (this._populated) | |
| 276 return; | |
| 277 this._populated = true; | |
| 278 this._provider().sortAndRewind(this.comparator()).then(this._populateChi
ldren.bind(this)); | |
| 279 }, | |
| 280 | |
| 281 /** | |
| 282 * @return {!Promise<?>} | |
| 283 */ | |
| 284 expandWithoutPopulate: function() | |
| 285 { | |
| 286 // Make sure default populate won't take action. | |
| 287 this._populated = true; | |
| 288 this.expand(); | |
| 289 return this._provider().sortAndRewind(this.comparator()); | |
| 290 }, | |
| 291 | |
| 292 /** | |
| 293 * @param {?number=} fromPosition | |
| 294 * @param {?number=} toPosition | |
| 295 * @param {function()=} afterPopulate | |
| 296 */ | |
| 297 _populateChildren: function(fromPosition, toPosition, afterPopulate) | |
| 298 { | |
| 299 fromPosition = fromPosition || 0; | |
| 300 toPosition = toPosition || fromPosition + this._dataGrid.defaultPopulate
Count(); | |
| 301 var firstNotSerializedPosition = fromPosition; | |
| 302 | |
| 303 /** | |
| 304 * @this {WebInspector.HeapSnapshotGridNode} | |
| 305 */ | |
| 306 function serializeNextChunk() | |
| 307 { | |
| 308 if (firstNotSerializedPosition >= toPosition) | |
| 309 return; | |
| 310 var end = Math.min(firstNotSerializedPosition + this._dataGrid.defau
ltPopulateCount(), toPosition); | |
| 311 this._provider().serializeItemsRange(firstNotSerializedPosition, end
, childrenRetrieved.bind(this)); | |
| 312 firstNotSerializedPosition = end; | |
| 313 } | |
| 314 | |
| 315 /** | |
| 316 * @this {WebInspector.HeapSnapshotGridNode} | |
| 317 */ | |
| 318 function insertRetrievedChild(item, insertionIndex) | |
| 319 { | |
| 320 if (this._savedChildren) { | |
| 321 var hash = this._childHashForEntity(item); | |
| 322 if (hash in this._savedChildren) { | |
| 323 this._dataGrid.insertChild(this, this._savedChildren[hash],
insertionIndex); | |
| 324 return; | |
| 325 } | |
| 326 } | |
| 327 this._dataGrid.insertChild(this, this._createChildNode(item), insert
ionIndex); | |
| 328 } | |
| 329 | |
| 330 /** | |
| 331 * @this {WebInspector.HeapSnapshotGridNode} | |
| 332 */ | |
| 333 function insertShowMoreButton(from, to, insertionIndex) | |
| 334 { | |
| 335 var button = new WebInspector.ShowMoreDataGridNode(this._populateChi
ldren.bind(this), from, to, this._dataGrid.defaultPopulateCount()); | |
| 336 this._dataGrid.insertChild(this, button, insertionIndex); | |
| 337 } | |
| 338 | |
| 339 /** | |
| 340 * @param {!WebInspector.HeapSnapshotCommon.ItemsRange} itemsRange | |
| 341 * @this {WebInspector.HeapSnapshotGridNode} | |
| 342 */ | |
| 343 function childrenRetrieved(itemsRange) | |
| 344 { | |
| 345 var itemIndex = 0; | |
| 346 var itemPosition = itemsRange.startPosition; | |
| 347 var items = itemsRange.items; | |
| 348 var insertionIndex = 0; | |
| 349 | |
| 350 if (!this._retrievedChildrenRanges.length) { | |
| 351 if (itemsRange.startPosition > 0) { | |
| 352 this._retrievedChildrenRanges.push({from: 0, to: 0}); | |
| 353 insertShowMoreButton.call(this, 0, itemsRange.startPosition,
insertionIndex++); | |
| 354 } | |
| 355 this._retrievedChildrenRanges.push({from: itemsRange.startPositi
on, to: itemsRange.endPosition}); | |
| 356 for (var i = 0, l = items.length; i < l; ++i) | |
| 357 insertRetrievedChild.call(this, items[i], insertionIndex++); | |
| 358 if (itemsRange.endPosition < itemsRange.totalLength) | |
| 359 insertShowMoreButton.call(this, itemsRange.endPosition, item
sRange.totalLength, insertionIndex++); | |
| 360 } else { | |
| 361 var rangeIndex = 0; | |
| 362 var found = false; | |
| 363 var range; | |
| 364 while (rangeIndex < this._retrievedChildrenRanges.length) { | |
| 365 range = this._retrievedChildrenRanges[rangeIndex]; | |
| 366 if (range.to >= itemPosition) { | |
| 367 found = true; | |
| 368 break; | |
| 369 } | |
| 370 insertionIndex += range.to - range.from; | |
| 371 // Skip the button if there is one. | |
| 372 if (range.to < itemsRange.totalLength) | |
| 373 insertionIndex += 1; | |
| 374 ++rangeIndex; | |
| 375 } | |
| 376 | |
| 377 if (!found || itemsRange.startPosition < range.from) { | |
| 378 // Update previous button. | |
| 379 this.allChildren()[insertionIndex - 1].setEndPosition(itemsR
ange.startPosition); | |
| 380 insertShowMoreButton.call(this, itemsRange.startPosition, fo
und ? range.from : itemsRange.totalLength, insertionIndex); | |
| 381 range = {from: itemsRange.startPosition, to: itemsRange.star
tPosition}; | |
| 382 if (!found) | |
| 383 rangeIndex = this._retrievedChildrenRanges.length; | |
| 384 this._retrievedChildrenRanges.splice(rangeIndex, 0, range); | |
| 385 } else { | |
| 386 insertionIndex += itemPosition - range.from; | |
| 387 } | |
| 388 // At this point insertionIndex is always an index before button
or between nodes. | |
| 389 // Also it is always true here that range.from <= itemPosition <
= range.to | |
| 390 | |
| 391 // Stretch the range right bound to include all new items. | |
| 392 while (range.to < itemsRange.endPosition) { | |
| 393 // Skip already added nodes. | |
| 394 var skipCount = range.to - itemPosition; | |
| 395 insertionIndex += skipCount; | |
| 396 itemIndex += skipCount; | |
| 397 itemPosition = range.to; | |
| 398 | |
| 399 // We're at the position before button: ...<?node>x<button> | |
| 400 var nextRange = this._retrievedChildrenRanges[rangeIndex + 1
]; | |
| 401 var newEndOfRange = nextRange ? nextRange.from : itemsRange.
totalLength; | |
| 402 if (newEndOfRange > itemsRange.endPosition) | |
| 403 newEndOfRange = itemsRange.endPosition; | |
| 404 while (itemPosition < newEndOfRange) { | |
| 405 insertRetrievedChild.call(this, items[itemIndex++], inse
rtionIndex++); | |
| 406 ++itemPosition; | |
| 407 } | |
| 408 | |
| 409 // Merge with the next range. | |
| 410 if (nextRange && newEndOfRange === nextRange.from) { | |
| 411 range.to = nextRange.to; | |
| 412 // Remove "show next" button if there is one. | |
| 413 this.removeChildByIndex(insertionIndex); | |
| 414 this._retrievedChildrenRanges.splice(rangeIndex + 1, 1); | |
| 415 } else { | |
| 416 range.to = newEndOfRange; | |
| 417 // Remove or update next button. | |
| 418 if (newEndOfRange === itemsRange.totalLength) | |
| 419 this.removeChildByIndex(insertionIndex); | |
| 420 else | |
| 421 this.allChildren()[insertionIndex].setStartPosition(
itemsRange.endPosition); | |
| 422 } | |
| 423 } | |
| 424 } | |
| 425 | |
| 426 // TODO: fix this. | |
| 427 this._instanceCount += items.length; | |
| 428 if (firstNotSerializedPosition < toPosition) { | |
| 429 serializeNextChunk.call(this); | |
| 430 return; | |
| 431 } | |
| 432 | |
| 433 if (this.expanded) | |
| 434 this._dataGrid.updateVisibleNodes(true); | |
| 435 if (afterPopulate) | |
| 436 afterPopulate(); | |
| 437 this.dispatchEventToListeners(WebInspector.HeapSnapshotGridNode.Even
ts.PopulateComplete); | |
| 438 } | |
| 439 serializeNextChunk.call(this); | |
| 440 }, | |
| 441 | |
| 442 _saveChildren: function() | |
| 443 { | |
| 444 this._savedChildren = null; | |
| 445 var children = this.allChildren(); | |
| 446 for (var i = 0, l = children.length; i < l; ++i) { | |
| 447 var child = children[i]; | |
| 448 if (!child.expanded) | |
| 449 continue; | |
| 450 if (!this._savedChildren) | |
| 451 this._savedChildren = {}; | |
| 452 this._savedChildren[this._childHashForNode(child)] = child; | |
| 453 } | |
| 454 }, | |
| 455 | |
| 456 sort: function() | |
| 457 { | |
| 458 this._dataGrid.recursiveSortingEnter(); | |
| 459 | |
| 460 /** | |
| 461 * @this {WebInspector.HeapSnapshotGridNode} | |
| 462 */ | |
| 463 function afterSort() | |
| 464 { | |
| 465 this._saveChildren(); | |
| 466 this._dataGrid.removeAllChildren(this); | |
| 467 this._retrievedChildrenRanges = []; | |
| 468 | |
| 469 /** | |
| 470 * @this {WebInspector.HeapSnapshotGridNode} | |
| 471 */ | |
| 472 function afterPopulate() | |
| 473 { | |
| 474 var children = this.allChildren(); | |
| 475 for (var i = 0, l = children.length; i < l; ++i) { | |
| 476 var child = children[i]; | |
| 477 if (child.expanded) | |
| 478 child.sort(); | |
| 479 } | |
| 480 this._dataGrid.recursiveSortingLeave(); | |
| 481 } | |
| 482 var instanceCount = this._instanceCount; | |
| 483 this._instanceCount = 0; | |
| 484 this._populateChildren(0, instanceCount, afterPopulate.bind(this)); | |
| 485 } | |
| 486 | |
| 487 this._provider().sortAndRewind(this.comparator()).then(afterSort.bind(th
is)); | |
| 488 }, | |
| 489 | |
| 490 __proto__: WebInspector.DataGridNode.prototype | |
| 491 }; | |
| 492 | |
| 493 | |
| 494 /** | 472 /** |
| 495 * @constructor | 473 * @unrestricted |
| 496 * @extends {WebInspector.HeapSnapshotGridNode} | |
| 497 * @param {!WebInspector.HeapSnapshotSortableDataGrid} dataGrid | |
| 498 * @param {!WebInspector.HeapSnapshotCommon.Node} node | |
| 499 */ | 474 */ |
| 500 WebInspector.HeapSnapshotGenericObjectNode = function(dataGrid, node) | 475 WebInspector.HeapSnapshotGenericObjectNode = class extends WebInspector.HeapSnap
shotGridNode { |
| 501 { | 476 /** |
| 502 WebInspector.HeapSnapshotGridNode.call(this, dataGrid, false); | 477 * @param {!WebInspector.HeapSnapshotSortableDataGrid} dataGrid |
| 478 * @param {!WebInspector.HeapSnapshotCommon.Node} node |
| 479 */ |
| 480 constructor(dataGrid, node) { |
| 481 super(dataGrid, false); |
| 503 // node is null for DataGrid root nodes. | 482 // node is null for DataGrid root nodes. |
| 504 if (!node) | 483 if (!node) |
| 505 return; | 484 return; |
| 506 this._name = node.name; | 485 this._name = node.name; |
| 507 this._type = node.type; | 486 this._type = node.type; |
| 508 this._distance = node.distance; | 487 this._distance = node.distance; |
| 509 this._shallowSize = node.selfSize; | 488 this._shallowSize = node.selfSize; |
| 510 this._retainedSize = node.retainedSize; | 489 this._retainedSize = node.retainedSize; |
| 511 this.snapshotNodeId = node.id; | 490 this.snapshotNodeId = node.id; |
| 512 this.snapshotNodeIndex = node.nodeIndex; | 491 this.snapshotNodeIndex = node.nodeIndex; |
| 513 if (this._type === "string") | 492 if (this._type === 'string') |
| 514 this._reachableFromWindow = true; | 493 this._reachableFromWindow = true; |
| 515 else if (this._type === "object" && this._name.startsWith("Window")) { | 494 else if (this._type === 'object' && this._name.startsWith('Window')) { |
| 516 this._name = this.shortenWindowURL(this._name, false); | 495 this._name = this.shortenWindowURL(this._name, false); |
| 517 this._reachableFromWindow = true; | 496 this._reachableFromWindow = true; |
| 518 } else if (node.canBeQueried) | 497 } else if (node.canBeQueried) |
| 519 this._reachableFromWindow = true; | 498 this._reachableFromWindow = true; |
| 520 if (node.detachedDOMTreeNode) | 499 if (node.detachedDOMTreeNode) |
| 521 this.detachedDOMTreeNode = true; | 500 this.detachedDOMTreeNode = true; |
| 522 | 501 |
| 523 var snapshot = dataGrid.snapshot; | 502 var snapshot = dataGrid.snapshot; |
| 524 var shallowSizePercent = this._shallowSize / snapshot.totalSize * 100.0; | 503 var shallowSizePercent = this._shallowSize / snapshot.totalSize * 100.0; |
| 525 var retainedSizePercent = this._retainedSize / snapshot.totalSize * 100.0; | 504 var retainedSizePercent = this._retainedSize / snapshot.totalSize * 100.0; |
| 526 this.data = { | 505 this.data = { |
| 527 "distance": this._toUIDistance(this._distance), | 506 'distance': this._toUIDistance(this._distance), |
| 528 "shallowSize": Number.withThousandsSeparator(this._shallowSize), | 507 'shallowSize': Number.withThousandsSeparator(this._shallowSize), |
| 529 "retainedSize": Number.withThousandsSeparator(this._retainedSize), | 508 'retainedSize': Number.withThousandsSeparator(this._retainedSize), |
| 530 "shallowSize-percent": this._toPercentString(shallowSizePercent), | 509 'shallowSize-percent': this._toPercentString(shallowSizePercent), |
| 531 "retainedSize-percent": this._toPercentString(retainedSizePercent) | 510 'retainedSize-percent': this._toPercentString(retainedSizePercent) |
| 532 }; | 511 }; |
| 533 }; | 512 } |
| 534 | 513 |
| 535 WebInspector.HeapSnapshotGenericObjectNode.prototype = { | 514 /** |
| 515 * @override |
| 516 * @return {?{snapshot:!WebInspector.HeapSnapshotProxy, snapshotNodeIndex:numb
er}} |
| 517 */ |
| 518 retainersDataSource() { |
| 519 return {snapshot: this._dataGrid.snapshot, snapshotNodeIndex: this.snapshotN
odeIndex}; |
| 520 } |
| 521 |
| 522 /** |
| 523 * @override |
| 524 * @param {string} columnId |
| 525 * @return {!Element} |
| 526 */ |
| 527 createCell(columnId) { |
| 528 var cell = columnId !== 'object' ? this._createValueCell(columnId) : this._c
reateObjectCell(); |
| 529 if (this._searchMatched) |
| 530 cell.classList.add('highlight'); |
| 531 return cell; |
| 532 } |
| 533 |
| 534 /** |
| 535 * @return {!Element} |
| 536 */ |
| 537 _createObjectCell() { |
| 538 var value = this._name; |
| 539 var valueStyle = 'object'; |
| 540 switch (this._type) { |
| 541 case 'concatenated string': |
| 542 case 'string': |
| 543 value = '"' + value + '"'; |
| 544 valueStyle = 'string'; |
| 545 break; |
| 546 case 'regexp': |
| 547 value = '/' + value + '/'; |
| 548 valueStyle = 'string'; |
| 549 break; |
| 550 case 'closure': |
| 551 value = value + '()'; |
| 552 valueStyle = 'function'; |
| 553 break; |
| 554 case 'number': |
| 555 valueStyle = 'number'; |
| 556 break; |
| 557 case 'hidden': |
| 558 valueStyle = 'null'; |
| 559 break; |
| 560 case 'array': |
| 561 value = (value || '') + '[]'; |
| 562 break; |
| 563 } |
| 564 if (this._reachableFromWindow) |
| 565 valueStyle += ' highlight'; |
| 566 if (value === 'Object') |
| 567 value = ''; |
| 568 if (this.detachedDOMTreeNode) |
| 569 valueStyle += ' detached-dom-tree-node'; |
| 570 return this._createObjectCellWithValue(valueStyle, value); |
| 571 } |
| 572 |
| 573 _createObjectCellWithValue(valueStyle, value) { |
| 574 var cell = createElement('td'); |
| 575 cell.className = 'object-column'; |
| 576 var div = createElement('div'); |
| 577 div.className = 'source-code event-properties'; |
| 578 div.style.overflow = 'visible'; |
| 579 |
| 580 this._prefixObjectCell(div); |
| 581 |
| 582 var valueSpan = createElement('span'); |
| 583 valueSpan.className = 'value object-value-' + valueStyle; |
| 584 valueSpan.textContent = value; |
| 585 div.appendChild(valueSpan); |
| 586 |
| 587 var idSpan = createElement('span'); |
| 588 idSpan.className = 'object-value-id'; |
| 589 idSpan.textContent = ' @' + this.snapshotNodeId; |
| 590 div.appendChild(idSpan); |
| 591 |
| 592 cell.appendChild(div); |
| 593 cell.classList.add('disclosure'); |
| 594 if (this.depth) |
| 595 cell.style.setProperty('padding-left', (this.depth * this.dataGrid.indentW
idth) + 'px'); |
| 596 cell.heapSnapshotNode = this; |
| 597 return cell; |
| 598 } |
| 599 |
| 600 _prefixObjectCell(div) { |
| 601 } |
| 602 |
| 603 /** |
| 604 * @override |
| 605 * @param {!WebInspector.Target} target |
| 606 * @param {function(!WebInspector.RemoteObject)} callback |
| 607 * @param {string} objectGroupName |
| 608 */ |
| 609 queryObjectContent(target, callback, objectGroupName) { |
| 536 /** | 610 /** |
| 537 * @override | 611 * @param {?Protocol.Error} error |
| 538 * @return {?{snapshot:!WebInspector.HeapSnapshotProxy, snapshotNodeIndex:nu
mber}} | 612 * @param {!RuntimeAgent.RemoteObject} object |
| 539 */ | 613 */ |
| 540 retainersDataSource: function() | 614 function formatResult(error, object) { |
| 541 { | 615 if (!error && object.type) |
| 542 return {snapshot: this._dataGrid.snapshot, snapshotNodeIndex: this.snaps
hotNodeIndex}; | 616 callback(target.runtimeModel.createRemoteObject(object)); |
| 543 }, | 617 else |
| 618 callback(target.runtimeModel.createRemoteObjectFromPrimitiveValue( |
| 619 WebInspector.UIString('Preview is not available'))); |
| 620 } |
| 544 | 621 |
| 622 if (this._type === 'string') |
| 623 callback(target.runtimeModel.createRemoteObjectFromPrimitiveValue(this._na
me)); |
| 624 else |
| 625 target.heapProfilerAgent().getObjectByHeapObjectId(String(this.snapshotNod
eId), objectGroupName, formatResult); |
| 626 } |
| 627 |
| 628 updateHasChildren() { |
| 545 /** | 629 /** |
| 546 * @override | 630 * @this {WebInspector.HeapSnapshotGenericObjectNode} |
| 547 * @param {string} columnId | |
| 548 * @return {!Element} | |
| 549 */ | 631 */ |
| 550 createCell: function(columnId) | 632 function isEmptyCallback(isEmpty) { |
| 551 { | 633 this.hasChildren = !isEmpty; |
| 552 var cell = columnId !== "object" ? this._createValueCell(columnId) : thi
s._createObjectCell(); | 634 } |
| 553 if (this._searchMatched) | 635 this._provider().isEmpty(isEmptyCallback.bind(this)); |
| 554 cell.classList.add("highlight"); | 636 } |
| 555 return cell; | |
| 556 }, | |
| 557 | 637 |
| 558 /** | 638 /** |
| 559 * @return {!Element} | 639 * @param {string} fullName |
| 560 */ | 640 * @param {boolean} hasObjectId |
| 561 _createObjectCell: function() | 641 * @return {string} |
| 562 { | 642 */ |
| 563 var value = this._name; | 643 shortenWindowURL(fullName, hasObjectId) { |
| 564 var valueStyle = "object"; | 644 var startPos = fullName.indexOf('/'); |
| 565 switch (this._type) { | 645 var endPos = hasObjectId ? fullName.indexOf('@') : fullName.length; |
| 566 case "concatenated string": | 646 if (startPos !== -1 && endPos !== -1) { |
| 567 case "string": | 647 var fullURL = fullName.substring(startPos + 1, endPos).trimLeft(); |
| 568 value = "\"" + value + "\""; | 648 var url = fullURL.trimURL(); |
| 569 valueStyle = "string"; | 649 if (url.length > 40) |
| 570 break; | 650 url = url.trimMiddle(40); |
| 571 case "regexp": | 651 return fullName.substr(0, startPos + 2) + url + fullName.substr(endPos); |
| 572 value = "/" + value + "/"; | 652 } else |
| 573 valueStyle = "string"; | 653 return fullName; |
| 574 break; | 654 } |
| 575 case "closure": | |
| 576 value = value + "()"; | |
| 577 valueStyle = "function"; | |
| 578 break; | |
| 579 case "number": | |
| 580 valueStyle = "number"; | |
| 581 break; | |
| 582 case "hidden": | |
| 583 valueStyle = "null"; | |
| 584 break; | |
| 585 case "array": | |
| 586 value = (value || "") + "[]"; | |
| 587 break; | |
| 588 } | |
| 589 if (this._reachableFromWindow) | |
| 590 valueStyle += " highlight"; | |
| 591 if (value === "Object") | |
| 592 value = ""; | |
| 593 if (this.detachedDOMTreeNode) | |
| 594 valueStyle += " detached-dom-tree-node"; | |
| 595 return this._createObjectCellWithValue(valueStyle, value); | |
| 596 }, | |
| 597 | |
| 598 _createObjectCellWithValue: function(valueStyle, value) | |
| 599 { | |
| 600 var cell = createElement("td"); | |
| 601 cell.className = "object-column"; | |
| 602 var div = createElement("div"); | |
| 603 div.className = "source-code event-properties"; | |
| 604 div.style.overflow = "visible"; | |
| 605 | |
| 606 this._prefixObjectCell(div); | |
| 607 | |
| 608 var valueSpan = createElement("span"); | |
| 609 valueSpan.className = "value object-value-" + valueStyle; | |
| 610 valueSpan.textContent = value; | |
| 611 div.appendChild(valueSpan); | |
| 612 | |
| 613 var idSpan = createElement("span"); | |
| 614 idSpan.className = "object-value-id"; | |
| 615 idSpan.textContent = " @" + this.snapshotNodeId; | |
| 616 div.appendChild(idSpan); | |
| 617 | |
| 618 cell.appendChild(div); | |
| 619 cell.classList.add("disclosure"); | |
| 620 if (this.depth) | |
| 621 cell.style.setProperty("padding-left", (this.depth * this.dataGrid.i
ndentWidth) + "px"); | |
| 622 cell.heapSnapshotNode = this; | |
| 623 return cell; | |
| 624 }, | |
| 625 | |
| 626 _prefixObjectCell: function(div) | |
| 627 { | |
| 628 }, | |
| 629 | |
| 630 /** | |
| 631 * @param {!WebInspector.Target} target | |
| 632 * @param {function(!WebInspector.RemoteObject)} callback | |
| 633 * @param {string} objectGroupName | |
| 634 */ | |
| 635 queryObjectContent: function(target, callback, objectGroupName) | |
| 636 { | |
| 637 /** | |
| 638 * @param {?Protocol.Error} error | |
| 639 * @param {!RuntimeAgent.RemoteObject} object | |
| 640 */ | |
| 641 function formatResult(error, object) | |
| 642 { | |
| 643 if (!error && object.type) | |
| 644 callback(target.runtimeModel.createRemoteObject(object)); | |
| 645 else | |
| 646 callback(target.runtimeModel.createRemoteObjectFromPrimitiveValu
e(WebInspector.UIString("Preview is not available"))); | |
| 647 } | |
| 648 | |
| 649 if (this._type === "string") | |
| 650 callback(target.runtimeModel.createRemoteObjectFromPrimitiveValue(th
is._name)); | |
| 651 else | |
| 652 target.heapProfilerAgent().getObjectByHeapObjectId(String(this.snaps
hotNodeId), objectGroupName, formatResult); | |
| 653 }, | |
| 654 | |
| 655 updateHasChildren: function() | |
| 656 { | |
| 657 /** | |
| 658 * @this {WebInspector.HeapSnapshotGenericObjectNode} | |
| 659 */ | |
| 660 function isEmptyCallback(isEmpty) | |
| 661 { | |
| 662 this.hasChildren = !isEmpty; | |
| 663 } | |
| 664 this._provider().isEmpty(isEmptyCallback.bind(this)); | |
| 665 }, | |
| 666 | |
| 667 /** | |
| 668 * @param {string} fullName | |
| 669 * @param {boolean} hasObjectId | |
| 670 * @return {string} | |
| 671 */ | |
| 672 shortenWindowURL: function(fullName, hasObjectId) | |
| 673 { | |
| 674 var startPos = fullName.indexOf("/"); | |
| 675 var endPos = hasObjectId ? fullName.indexOf("@") : fullName.length; | |
| 676 if (startPos !== -1 && endPos !== -1) { | |
| 677 var fullURL = fullName.substring(startPos + 1, endPos).trimLeft(); | |
| 678 var url = fullURL.trimURL(); | |
| 679 if (url.length > 40) | |
| 680 url = url.trimMiddle(40); | |
| 681 return fullName.substr(0, startPos + 2) + url + fullName.substr(endP
os); | |
| 682 } else | |
| 683 return fullName; | |
| 684 }, | |
| 685 | |
| 686 __proto__: WebInspector.HeapSnapshotGridNode.prototype | |
| 687 }; | 655 }; |
| 688 | 656 |
| 689 /** | 657 /** |
| 690 * @constructor | 658 * @unrestricted |
| 691 * @extends {WebInspector.HeapSnapshotGenericObjectNode} | |
| 692 * @param {!WebInspector.HeapSnapshotSortableDataGrid} dataGrid | |
| 693 * @param {!WebInspector.HeapSnapshotProxy} snapshot | |
| 694 * @param {!WebInspector.HeapSnapshotCommon.Edge} edge | |
| 695 * @param {?WebInspector.HeapSnapshotObjectNode} parentObjectNode | |
| 696 */ | 659 */ |
| 697 WebInspector.HeapSnapshotObjectNode = function(dataGrid, snapshot, edge, parentO
bjectNode) | 660 WebInspector.HeapSnapshotObjectNode = class extends WebInspector.HeapSnapshotGen
ericObjectNode { |
| 698 { | 661 /** |
| 699 WebInspector.HeapSnapshotGenericObjectNode.call(this, dataGrid, edge.node); | 662 * @param {!WebInspector.HeapSnapshotSortableDataGrid} dataGrid |
| 663 * @param {!WebInspector.HeapSnapshotProxy} snapshot |
| 664 * @param {!WebInspector.HeapSnapshotCommon.Edge} edge |
| 665 * @param {?WebInspector.HeapSnapshotObjectNode} parentObjectNode |
| 666 */ |
| 667 constructor(dataGrid, snapshot, edge, parentObjectNode) { |
| 668 super(dataGrid, edge.node); |
| 700 this._referenceName = edge.name; | 669 this._referenceName = edge.name; |
| 701 this._referenceType = edge.type; | 670 this._referenceType = edge.type; |
| 702 this._edgeIndex = edge.edgeIndex; | 671 this._edgeIndex = edge.edgeIndex; |
| 703 this._snapshot = snapshot; | 672 this._snapshot = snapshot; |
| 704 | 673 |
| 705 this._parentObjectNode = parentObjectNode; | 674 this._parentObjectNode = parentObjectNode; |
| 706 this._cycledWithAncestorGridNode = this._findAncestorWithSameSnapshotNodeId(
); | 675 this._cycledWithAncestorGridNode = this._findAncestorWithSameSnapshotNodeId(
); |
| 707 if (!this._cycledWithAncestorGridNode) | 676 if (!this._cycledWithAncestorGridNode) |
| 708 this.updateHasChildren(); | 677 this.updateHasChildren(); |
| 709 | 678 |
| 710 var data = this.data; | 679 var data = this.data; |
| 711 data["count"] = ""; | 680 data['count'] = ''; |
| 712 data["addedCount"] = ""; | 681 data['addedCount'] = ''; |
| 713 data["removedCount"] = ""; | 682 data['removedCount'] = ''; |
| 714 data["countDelta"] = ""; | 683 data['countDelta'] = ''; |
| 715 data["addedSize"] = ""; | 684 data['addedSize'] = ''; |
| 716 data["removedSize"] = ""; | 685 data['removedSize'] = ''; |
| 717 data["sizeDelta"] = ""; | 686 data['sizeDelta'] = ''; |
| 687 } |
| 688 |
| 689 /** |
| 690 * @override |
| 691 * @return {?{snapshot:!WebInspector.HeapSnapshotProxy, snapshotNodeIndex:numb
er}} |
| 692 */ |
| 693 retainersDataSource() { |
| 694 return {snapshot: this._snapshot, snapshotNodeIndex: this.snapshotNodeIndex}
; |
| 695 } |
| 696 |
| 697 /** |
| 698 * @override |
| 699 * @return {!WebInspector.HeapSnapshotProviderProxy} |
| 700 */ |
| 701 createProvider() { |
| 702 return this._snapshot.createEdgesProvider(this.snapshotNodeIndex); |
| 703 } |
| 704 |
| 705 _findAncestorWithSameSnapshotNodeId() { |
| 706 var ancestor = this._parentObjectNode; |
| 707 while (ancestor) { |
| 708 if (ancestor.snapshotNodeId === this.snapshotNodeId) |
| 709 return ancestor; |
| 710 ancestor = ancestor._parentObjectNode; |
| 711 } |
| 712 return null; |
| 713 } |
| 714 |
| 715 /** |
| 716 * @param {!WebInspector.HeapSnapshotCommon.Edge} item |
| 717 * @return {!WebInspector.HeapSnapshotObjectNode} |
| 718 */ |
| 719 _createChildNode(item) { |
| 720 return new WebInspector.HeapSnapshotObjectNode(this._dataGrid, this._snapsho
t, item, this); |
| 721 } |
| 722 |
| 723 /** |
| 724 * @param {!WebInspector.HeapSnapshotCommon.Edge} edge |
| 725 * @return {number} |
| 726 */ |
| 727 _childHashForEntity(edge) { |
| 728 return edge.edgeIndex; |
| 729 } |
| 730 |
| 731 /** |
| 732 * @param {!WebInspector.HeapSnapshotObjectNode} childNode |
| 733 * @return {number} |
| 734 */ |
| 735 _childHashForNode(childNode) { |
| 736 return childNode._edgeIndex; |
| 737 } |
| 738 |
| 739 /** |
| 740 * @return {!WebInspector.HeapSnapshotCommon.ComparatorConfig} |
| 741 */ |
| 742 comparator() { |
| 743 var sortAscending = this._dataGrid.isSortOrderAscending(); |
| 744 var sortColumnId = this._dataGrid.sortColumnId(); |
| 745 var sortFields = { |
| 746 object: ['!edgeName', sortAscending, 'retainedSize', false], |
| 747 count: ['!edgeName', true, 'retainedSize', false], |
| 748 shallowSize: ['selfSize', sortAscending, '!edgeName', true], |
| 749 retainedSize: ['retainedSize', sortAscending, '!edgeName', true], |
| 750 distance: ['distance', sortAscending, '_name', true] |
| 751 }[sortColumnId] || |
| 752 ['!edgeName', true, 'retainedSize', false]; |
| 753 return WebInspector.HeapSnapshotGridNode.createComparator(sortFields); |
| 754 } |
| 755 |
| 756 /** |
| 757 * @override |
| 758 */ |
| 759 _prefixObjectCell(div) { |
| 760 var name = this._referenceName || '(empty)'; |
| 761 var nameClass = 'name'; |
| 762 switch (this._referenceType) { |
| 763 case 'context': |
| 764 nameClass = 'object-value-number'; |
| 765 break; |
| 766 case 'internal': |
| 767 case 'hidden': |
| 768 case 'weak': |
| 769 nameClass = 'object-value-null'; |
| 770 break; |
| 771 case 'element': |
| 772 name = '[' + name + ']'; |
| 773 break; |
| 774 } |
| 775 |
| 776 if (this._cycledWithAncestorGridNode) |
| 777 div.className += ' cycled-ancessor-node'; |
| 778 |
| 779 var nameSpan = createElement('span'); |
| 780 nameSpan.className = nameClass; |
| 781 nameSpan.textContent = name; |
| 782 div.appendChild(nameSpan); |
| 783 |
| 784 var separatorSpan = createElement('span'); |
| 785 separatorSpan.className = 'grayed'; |
| 786 separatorSpan.textContent = this._edgeNodeSeparator(); |
| 787 div.appendChild(separatorSpan); |
| 788 } |
| 789 |
| 790 /** |
| 791 * @return {string} |
| 792 */ |
| 793 _edgeNodeSeparator() { |
| 794 return ' :: '; |
| 795 } |
| 718 }; | 796 }; |
| 719 | 797 |
| 720 WebInspector.HeapSnapshotObjectNode.prototype = { | 798 /** |
| 799 * @unrestricted |
| 800 */ |
| 801 WebInspector.HeapSnapshotRetainingObjectNode = class extends WebInspector.HeapSn
apshotObjectNode { |
| 802 /** |
| 803 * @param {!WebInspector.HeapSnapshotSortableDataGrid} dataGrid |
| 804 * @param {!WebInspector.HeapSnapshotProxy} snapshot |
| 805 * @param {!WebInspector.HeapSnapshotCommon.Edge} edge |
| 806 * @param {?WebInspector.HeapSnapshotRetainingObjectNode} parentRetainingObjec
tNode |
| 807 */ |
| 808 constructor(dataGrid, snapshot, edge, parentRetainingObjectNode) { |
| 809 super(dataGrid, snapshot, edge, parentRetainingObjectNode); |
| 810 } |
| 811 |
| 812 /** |
| 813 * @override |
| 814 * @return {!WebInspector.HeapSnapshotProviderProxy} |
| 815 */ |
| 816 createProvider() { |
| 817 return this._snapshot.createRetainingEdgesProvider(this.snapshotNodeIndex); |
| 818 } |
| 819 |
| 820 /** |
| 821 * @override |
| 822 * @param {!WebInspector.HeapSnapshotCommon.Edge} item |
| 823 * @return {!WebInspector.HeapSnapshotRetainingObjectNode} |
| 824 */ |
| 825 _createChildNode(item) { |
| 826 return new WebInspector.HeapSnapshotRetainingObjectNode(this._dataGrid, this
._snapshot, item, this); |
| 827 } |
| 828 |
| 829 /** |
| 830 * @override |
| 831 * @return {string} |
| 832 */ |
| 833 _edgeNodeSeparator() { |
| 834 return ' in '; |
| 835 } |
| 836 |
| 837 /** |
| 838 * @override |
| 839 */ |
| 840 expand() { |
| 841 this._expandRetainersChain(20); |
| 842 } |
| 843 |
| 844 /** |
| 845 * @param {number} maxExpandLevels |
| 846 */ |
| 847 _expandRetainersChain(maxExpandLevels) { |
| 721 /** | 848 /** |
| 722 * @override | 849 * @this {!WebInspector.HeapSnapshotRetainingObjectNode} |
| 723 * @return {?{snapshot:!WebInspector.HeapSnapshotProxy, snapshotNodeIndex:nu
mber}} | |
| 724 */ | 850 */ |
| 725 retainersDataSource: function() | 851 function populateComplete() { |
| 726 { | 852 this.removeEventListener(WebInspector.HeapSnapshotGridNode.Events.Populate
Complete, populateComplete, this); |
| 727 return {snapshot: this._snapshot, snapshotNodeIndex: this.snapshotNodeIn
dex}; | 853 this._expandRetainersChain(maxExpandLevels); |
| 728 }, | 854 } |
| 729 | 855 |
| 730 /** | 856 if (!this._populated) { |
| 731 * @override | 857 this.addEventListener(WebInspector.HeapSnapshotGridNode.Events.PopulateCom
plete, populateComplete, this); |
| 732 * @return {!WebInspector.HeapSnapshotProviderProxy} | 858 this.populate(); |
| 733 */ | 859 return; |
| 734 createProvider: function() | 860 } |
| 735 { | 861 super.expand(); |
| 736 return this._snapshot.createEdgesProvider(this.snapshotNodeIndex); | 862 if (--maxExpandLevels > 0 && this.children.length > 0) { |
| 737 }, | 863 var retainer = this.children[0]; |
| 738 | 864 if (retainer._distance > 1) { |
| 739 _findAncestorWithSameSnapshotNodeId: function() | 865 retainer._expandRetainersChain(maxExpandLevels); |
| 740 { | 866 return; |
| 741 var ancestor = this._parentObjectNode; | 867 } |
| 742 while (ancestor) { | 868 } |
| 743 if (ancestor.snapshotNodeId === this.snapshotNodeId) | 869 this._dataGrid.dispatchEventToListeners(WebInspector.HeapSnapshotRetainmentD
ataGrid.Events.ExpandRetainersComplete); |
| 744 return ancestor; | 870 } |
| 745 ancestor = ancestor._parentObjectNode; | |
| 746 } | |
| 747 return null; | |
| 748 }, | |
| 749 | |
| 750 /** | |
| 751 * @param {!WebInspector.HeapSnapshotCommon.Edge} item | |
| 752 * @return {!WebInspector.HeapSnapshotObjectNode} | |
| 753 */ | |
| 754 _createChildNode: function(item) | |
| 755 { | |
| 756 return new WebInspector.HeapSnapshotObjectNode(this._dataGrid, this._sna
pshot, item, this); | |
| 757 }, | |
| 758 | |
| 759 /** | |
| 760 * @param {!WebInspector.HeapSnapshotCommon.Edge} edge | |
| 761 * @return {number} | |
| 762 */ | |
| 763 _childHashForEntity: function(edge) | |
| 764 { | |
| 765 return edge.edgeIndex; | |
| 766 }, | |
| 767 | |
| 768 /** | |
| 769 * @param {!WebInspector.HeapSnapshotObjectNode} childNode | |
| 770 * @return {number} | |
| 771 */ | |
| 772 _childHashForNode: function(childNode) | |
| 773 { | |
| 774 return childNode._edgeIndex; | |
| 775 }, | |
| 776 | |
| 777 /** | |
| 778 * @return {!WebInspector.HeapSnapshotCommon.ComparatorConfig} | |
| 779 */ | |
| 780 comparator: function() | |
| 781 { | |
| 782 var sortAscending = this._dataGrid.isSortOrderAscending(); | |
| 783 var sortColumnId = this._dataGrid.sortColumnId(); | |
| 784 var sortFields = { | |
| 785 object: ["!edgeName", sortAscending, "retainedSize", false], | |
| 786 count: ["!edgeName", true, "retainedSize", false], | |
| 787 shallowSize: ["selfSize", sortAscending, "!edgeName", true], | |
| 788 retainedSize: ["retainedSize", sortAscending, "!edgeName", true], | |
| 789 distance: ["distance", sortAscending, "_name", true] | |
| 790 }[sortColumnId] || ["!edgeName", true, "retainedSize", false]; | |
| 791 return WebInspector.HeapSnapshotGridNode.createComparator(sortFields); | |
| 792 }, | |
| 793 | |
| 794 _prefixObjectCell: function(div) | |
| 795 { | |
| 796 var name = this._referenceName || "(empty)"; | |
| 797 var nameClass = "name"; | |
| 798 switch (this._referenceType) { | |
| 799 case "context": | |
| 800 nameClass = "object-value-number"; | |
| 801 break; | |
| 802 case "internal": | |
| 803 case "hidden": | |
| 804 case "weak": | |
| 805 nameClass = "object-value-null"; | |
| 806 break; | |
| 807 case "element": | |
| 808 name = "[" + name + "]"; | |
| 809 break; | |
| 810 } | |
| 811 | |
| 812 if (this._cycledWithAncestorGridNode) | |
| 813 div.className += " cycled-ancessor-node"; | |
| 814 | |
| 815 var nameSpan = createElement("span"); | |
| 816 nameSpan.className = nameClass; | |
| 817 nameSpan.textContent = name; | |
| 818 div.appendChild(nameSpan); | |
| 819 | |
| 820 var separatorSpan = createElement("span"); | |
| 821 separatorSpan.className = "grayed"; | |
| 822 separatorSpan.textContent = this._edgeNodeSeparator(); | |
| 823 div.appendChild(separatorSpan); | |
| 824 }, | |
| 825 | |
| 826 /** | |
| 827 * @return {string} | |
| 828 */ | |
| 829 _edgeNodeSeparator: function() | |
| 830 { | |
| 831 return " :: "; | |
| 832 }, | |
| 833 | |
| 834 __proto__: WebInspector.HeapSnapshotGenericObjectNode.prototype | |
| 835 }; | 871 }; |
| 836 | 872 |
| 837 /** | 873 /** |
| 838 * @constructor | 874 * @unrestricted |
| 839 * @extends {WebInspector.HeapSnapshotObjectNode} | |
| 840 * @param {!WebInspector.HeapSnapshotSortableDataGrid} dataGrid | |
| 841 * @param {!WebInspector.HeapSnapshotProxy} snapshot | |
| 842 * @param {!WebInspector.HeapSnapshotCommon.Edge} edge | |
| 843 * @param {?WebInspector.HeapSnapshotRetainingObjectNode} parentRetainingObjectN
ode | |
| 844 */ | 875 */ |
| 845 WebInspector.HeapSnapshotRetainingObjectNode = function(dataGrid, snapshot, edge
, parentRetainingObjectNode) | 876 WebInspector.HeapSnapshotInstanceNode = class extends WebInspector.HeapSnapshotG
enericObjectNode { |
| 846 { | 877 /** |
| 847 WebInspector.HeapSnapshotObjectNode.call(this, dataGrid, snapshot, edge, par
entRetainingObjectNode); | 878 * @param {!WebInspector.HeapSnapshotSortableDataGrid} dataGrid |
| 848 }; | 879 * @param {!WebInspector.HeapSnapshotProxy} snapshot |
| 849 | 880 * @param {!WebInspector.HeapSnapshotCommon.Node} node |
| 850 WebInspector.HeapSnapshotRetainingObjectNode.prototype = { | 881 * @param {boolean} isDeletedNode |
| 851 /** | 882 */ |
| 852 * @override | 883 constructor(dataGrid, snapshot, node, isDeletedNode) { |
| 853 * @return {!WebInspector.HeapSnapshotProviderProxy} | 884 super(dataGrid, node); |
| 854 */ | |
| 855 createProvider: function() | |
| 856 { | |
| 857 return this._snapshot.createRetainingEdgesProvider(this.snapshotNodeInde
x); | |
| 858 }, | |
| 859 | |
| 860 /** | |
| 861 * @override | |
| 862 * @param {!WebInspector.HeapSnapshotCommon.Edge} item | |
| 863 * @return {!WebInspector.HeapSnapshotRetainingObjectNode} | |
| 864 */ | |
| 865 _createChildNode: function(item) | |
| 866 { | |
| 867 return new WebInspector.HeapSnapshotRetainingObjectNode(this._dataGrid,
this._snapshot, item, this); | |
| 868 }, | |
| 869 | |
| 870 /** | |
| 871 * @override | |
| 872 * @return {string} | |
| 873 */ | |
| 874 _edgeNodeSeparator: function() | |
| 875 { | |
| 876 return " in "; | |
| 877 }, | |
| 878 | |
| 879 expand: function() | |
| 880 { | |
| 881 this._expandRetainersChain(20); | |
| 882 }, | |
| 883 | |
| 884 /** | |
| 885 * @param {number} maxExpandLevels | |
| 886 */ | |
| 887 _expandRetainersChain: function(maxExpandLevels) | |
| 888 { | |
| 889 /** | |
| 890 * @this {!WebInspector.HeapSnapshotRetainingObjectNode} | |
| 891 */ | |
| 892 function populateComplete() | |
| 893 { | |
| 894 this.removeEventListener(WebInspector.HeapSnapshotGridNode.Events.Po
pulateComplete, populateComplete, this); | |
| 895 this._expandRetainersChain(maxExpandLevels); | |
| 896 } | |
| 897 | |
| 898 if (!this._populated) { | |
| 899 this.addEventListener(WebInspector.HeapSnapshotGridNode.Events.Popul
ateComplete, populateComplete, this); | |
| 900 this.populate(); | |
| 901 return; | |
| 902 } | |
| 903 WebInspector.HeapSnapshotGenericObjectNode.prototype.expand.call(this); | |
| 904 if (--maxExpandLevels > 0 && this.children.length > 0) { | |
| 905 var retainer = this.children[0]; | |
| 906 if (retainer._distance > 1) { | |
| 907 retainer._expandRetainersChain(maxExpandLevels); | |
| 908 return; | |
| 909 } | |
| 910 } | |
| 911 this._dataGrid.dispatchEventToListeners(WebInspector.HeapSnapshotRetainm
entDataGrid.Events.ExpandRetainersComplete); | |
| 912 }, | |
| 913 | |
| 914 __proto__: WebInspector.HeapSnapshotObjectNode.prototype | |
| 915 }; | |
| 916 | |
| 917 /** | |
| 918 * @constructor | |
| 919 * @extends {WebInspector.HeapSnapshotGenericObjectNode} | |
| 920 * @param {!WebInspector.HeapSnapshotSortableDataGrid} dataGrid | |
| 921 * @param {!WebInspector.HeapSnapshotProxy} snapshot | |
| 922 * @param {!WebInspector.HeapSnapshotCommon.Node} node | |
| 923 * @param {boolean} isDeletedNode | |
| 924 */ | |
| 925 WebInspector.HeapSnapshotInstanceNode = function(dataGrid, snapshot, node, isDel
etedNode) | |
| 926 { | |
| 927 WebInspector.HeapSnapshotGenericObjectNode.call(this, dataGrid, node); | |
| 928 this._baseSnapshotOrSnapshot = snapshot; | 885 this._baseSnapshotOrSnapshot = snapshot; |
| 929 this._isDeletedNode = isDeletedNode; | 886 this._isDeletedNode = isDeletedNode; |
| 930 this.updateHasChildren(); | 887 this.updateHasChildren(); |
| 931 | 888 |
| 932 var data = this.data; | 889 var data = this.data; |
| 933 data["count"] = ""; | 890 data['count'] = ''; |
| 934 data["countDelta"] = ""; | 891 data['countDelta'] = ''; |
| 935 data["sizeDelta"] = ""; | 892 data['sizeDelta'] = ''; |
| 936 if (this._isDeletedNode) { | 893 if (this._isDeletedNode) { |
| 937 data["addedCount"] = ""; | 894 data['addedCount'] = ''; |
| 938 data["addedSize"] = ""; | 895 data['addedSize'] = ''; |
| 939 data["removedCount"] = "\u2022"; | 896 data['removedCount'] = '\u2022'; |
| 940 data["removedSize"] = Number.withThousandsSeparator(this._shallowSize); | 897 data['removedSize'] = Number.withThousandsSeparator(this._shallowSize); |
| 941 } else { | 898 } else { |
| 942 data["addedCount"] = "\u2022"; | 899 data['addedCount'] = '\u2022'; |
| 943 data["addedSize"] = Number.withThousandsSeparator(this._shallowSize); | 900 data['addedSize'] = Number.withThousandsSeparator(this._shallowSize); |
| 944 data["removedCount"] = ""; | 901 data['removedCount'] = ''; |
| 945 data["removedSize"] = ""; | 902 data['removedSize'] = ''; |
| 946 } | 903 } |
| 904 } |
| 905 |
| 906 /** |
| 907 * @override |
| 908 * @return {?{snapshot:!WebInspector.HeapSnapshotProxy, snapshotNodeIndex:numb
er}} |
| 909 */ |
| 910 retainersDataSource() { |
| 911 return {snapshot: this._baseSnapshotOrSnapshot, snapshotNodeIndex: this.snap
shotNodeIndex}; |
| 912 } |
| 913 |
| 914 /** |
| 915 * @override |
| 916 * @return {!WebInspector.HeapSnapshotProviderProxy} |
| 917 */ |
| 918 createProvider() { |
| 919 return this._baseSnapshotOrSnapshot.createEdgesProvider(this.snapshotNodeInd
ex); |
| 920 } |
| 921 |
| 922 /** |
| 923 * @param {!WebInspector.HeapSnapshotCommon.Edge} item |
| 924 * @return {!WebInspector.HeapSnapshotObjectNode} |
| 925 */ |
| 926 _createChildNode(item) { |
| 927 return new WebInspector.HeapSnapshotObjectNode(this._dataGrid, this._baseSna
pshotOrSnapshot, item, null); |
| 928 } |
| 929 |
| 930 /** |
| 931 * @param {!WebInspector.HeapSnapshotCommon.Edge} edge |
| 932 * @return {number} |
| 933 */ |
| 934 _childHashForEntity(edge) { |
| 935 return edge.edgeIndex; |
| 936 } |
| 937 |
| 938 /** |
| 939 * @param {!WebInspector.HeapSnapshotObjectNode} childNode |
| 940 * @return {number} |
| 941 */ |
| 942 _childHashForNode(childNode) { |
| 943 return childNode._edgeIndex; |
| 944 } |
| 945 |
| 946 /** |
| 947 * @return {!WebInspector.HeapSnapshotCommon.ComparatorConfig} |
| 948 */ |
| 949 comparator() { |
| 950 var sortAscending = this._dataGrid.isSortOrderAscending(); |
| 951 var sortColumnId = this._dataGrid.sortColumnId(); |
| 952 var sortFields = { |
| 953 object: ['!edgeName', sortAscending, 'retainedSize', false], |
| 954 distance: ['distance', sortAscending, 'retainedSize', false], |
| 955 count: ['!edgeName', true, 'retainedSize', false], |
| 956 addedSize: ['selfSize', sortAscending, '!edgeName', true], |
| 957 removedSize: ['selfSize', sortAscending, '!edgeName', true], |
| 958 shallowSize: ['selfSize', sortAscending, '!edgeName', true], |
| 959 retainedSize: ['retainedSize', sortAscending, '!edgeName', true] |
| 960 }[sortColumnId] || |
| 961 ['!edgeName', true, 'retainedSize', false]; |
| 962 return WebInspector.HeapSnapshotGridNode.createComparator(sortFields); |
| 963 } |
| 947 }; | 964 }; |
| 948 | 965 |
| 949 WebInspector.HeapSnapshotInstanceNode.prototype = { | |
| 950 /** | |
| 951 * @override | |
| 952 * @return {?{snapshot:!WebInspector.HeapSnapshotProxy, snapshotNodeIndex:nu
mber}} | |
| 953 */ | |
| 954 retainersDataSource: function() | |
| 955 { | |
| 956 return {snapshot: this._baseSnapshotOrSnapshot, snapshotNodeIndex: this.
snapshotNodeIndex}; | |
| 957 }, | |
| 958 | |
| 959 /** | |
| 960 * @override | |
| 961 * @return {!WebInspector.HeapSnapshotProviderProxy} | |
| 962 */ | |
| 963 createProvider: function() | |
| 964 { | |
| 965 return this._baseSnapshotOrSnapshot.createEdgesProvider(this.snapshotNod
eIndex); | |
| 966 }, | |
| 967 | |
| 968 /** | |
| 969 * @param {!WebInspector.HeapSnapshotCommon.Edge} item | |
| 970 * @return {!WebInspector.HeapSnapshotObjectNode} | |
| 971 */ | |
| 972 _createChildNode: function(item) | |
| 973 { | |
| 974 return new WebInspector.HeapSnapshotObjectNode(this._dataGrid, this._bas
eSnapshotOrSnapshot, item, null); | |
| 975 }, | |
| 976 | |
| 977 /** | |
| 978 * @param {!WebInspector.HeapSnapshotCommon.Edge} edge | |
| 979 * @return {number} | |
| 980 */ | |
| 981 _childHashForEntity: function(edge) | |
| 982 { | |
| 983 return edge.edgeIndex; | |
| 984 }, | |
| 985 | |
| 986 /** | |
| 987 * @param {!WebInspector.HeapSnapshotObjectNode} childNode | |
| 988 * @return {number} | |
| 989 */ | |
| 990 _childHashForNode: function(childNode) | |
| 991 { | |
| 992 return childNode._edgeIndex; | |
| 993 }, | |
| 994 | |
| 995 /** | |
| 996 * @return {!WebInspector.HeapSnapshotCommon.ComparatorConfig} | |
| 997 */ | |
| 998 comparator: function() | |
| 999 { | |
| 1000 var sortAscending = this._dataGrid.isSortOrderAscending(); | |
| 1001 var sortColumnId = this._dataGrid.sortColumnId(); | |
| 1002 var sortFields = { | |
| 1003 object: ["!edgeName", sortAscending, "retainedSize", false], | |
| 1004 distance: ["distance", sortAscending, "retainedSize", false], | |
| 1005 count: ["!edgeName", true, "retainedSize", false], | |
| 1006 addedSize: ["selfSize", sortAscending, "!edgeName", true], | |
| 1007 removedSize: ["selfSize", sortAscending, "!edgeName", true], | |
| 1008 shallowSize: ["selfSize", sortAscending, "!edgeName", true], | |
| 1009 retainedSize: ["retainedSize", sortAscending, "!edgeName", true] | |
| 1010 }[sortColumnId] || ["!edgeName", true, "retainedSize", false]; | |
| 1011 return WebInspector.HeapSnapshotGridNode.createComparator(sortFields); | |
| 1012 }, | |
| 1013 | |
| 1014 __proto__: WebInspector.HeapSnapshotGenericObjectNode.prototype | |
| 1015 }; | |
| 1016 | |
| 1017 /** | 966 /** |
| 1018 * @constructor | 967 * @unrestricted |
| 1019 * @param {!WebInspector.HeapSnapshotConstructorsDataGrid} dataGrid | |
| 1020 * @param {string} className | |
| 1021 * @param {!WebInspector.HeapSnapshotCommon.Aggregate} aggregate | |
| 1022 * @param {!WebInspector.HeapSnapshotCommon.NodeFilter} nodeFilter | |
| 1023 * @extends {WebInspector.HeapSnapshotGridNode} | |
| 1024 */ | 968 */ |
| 1025 WebInspector.HeapSnapshotConstructorNode = function(dataGrid, className, aggrega
te, nodeFilter) | 969 WebInspector.HeapSnapshotConstructorNode = class extends WebInspector.HeapSnapsh
otGridNode { |
| 1026 { | 970 /** |
| 1027 WebInspector.HeapSnapshotGridNode.call(this, dataGrid, aggregate.count > 0); | 971 * @param {!WebInspector.HeapSnapshotConstructorsDataGrid} dataGrid |
| 972 * @param {string} className |
| 973 * @param {!WebInspector.HeapSnapshotCommon.Aggregate} aggregate |
| 974 * @param {!WebInspector.HeapSnapshotCommon.NodeFilter} nodeFilter |
| 975 */ |
| 976 constructor(dataGrid, className, aggregate, nodeFilter) { |
| 977 super(dataGrid, aggregate.count > 0); |
| 1028 this._name = className; | 978 this._name = className; |
| 1029 this._nodeFilter = nodeFilter; | 979 this._nodeFilter = nodeFilter; |
| 1030 this._distance = aggregate.distance; | 980 this._distance = aggregate.distance; |
| 1031 this._count = aggregate.count; | 981 this._count = aggregate.count; |
| 1032 this._shallowSize = aggregate.self; | 982 this._shallowSize = aggregate.self; |
| 1033 this._retainedSize = aggregate.maxRet; | 983 this._retainedSize = aggregate.maxRet; |
| 1034 | 984 |
| 1035 var snapshot = dataGrid.snapshot; | 985 var snapshot = dataGrid.snapshot; |
| 1036 var countPercent = this._count / snapshot.nodeCount * 100.0; | 986 var countPercent = this._count / snapshot.nodeCount * 100.0; |
| 1037 var retainedSizePercent = this._retainedSize / snapshot.totalSize * 100.0; | 987 var retainedSizePercent = this._retainedSize / snapshot.totalSize * 100.0; |
| 1038 var shallowSizePercent = this._shallowSize / snapshot.totalSize * 100.0; | 988 var shallowSizePercent = this._shallowSize / snapshot.totalSize * 100.0; |
| 1039 | 989 |
| 1040 this.data = { | 990 this.data = { |
| 1041 "object": className, | 991 'object': className, |
| 1042 "count": Number.withThousandsSeparator(this._count), | 992 'count': Number.withThousandsSeparator(this._count), |
| 1043 "distance": this._toUIDistance(this._distance), | 993 'distance': this._toUIDistance(this._distance), |
| 1044 "shallowSize": Number.withThousandsSeparator(this._shallowSize), | 994 'shallowSize': Number.withThousandsSeparator(this._shallowSize), |
| 1045 "retainedSize": Number.withThousandsSeparator(this._retainedSize), | 995 'retainedSize': Number.withThousandsSeparator(this._retainedSize), |
| 1046 "count-percent": this._toPercentString(countPercent), | 996 'count-percent': this._toPercentString(countPercent), |
| 1047 "shallowSize-percent": this._toPercentString(shallowSizePercent), | 997 'shallowSize-percent': this._toPercentString(shallowSizePercent), |
| 1048 "retainedSize-percent": this._toPercentString(retainedSizePercent) | 998 'retainedSize-percent': this._toPercentString(retainedSizePercent) |
| 1049 }; | 999 }; |
| 1050 }; | 1000 } |
| 1051 | 1001 |
| 1052 WebInspector.HeapSnapshotConstructorNode.prototype = { | 1002 /** |
| 1053 /** | 1003 * @override |
| 1054 * @override | 1004 * @return {!WebInspector.HeapSnapshotProviderProxy} |
| 1055 * @return {!WebInspector.HeapSnapshotProviderProxy} | 1005 */ |
| 1056 */ | 1006 createProvider() { |
| 1057 createProvider: function() | 1007 return this._dataGrid.snapshot.createNodesProviderForClass(this._name, this.
_nodeFilter); |
| 1058 { | 1008 } |
| 1059 return this._dataGrid.snapshot.createNodesProviderForClass(this._name, t
his._nodeFilter); | 1009 |
| 1060 }, | 1010 /** |
| 1061 | 1011 * @param {number} snapshotObjectId |
| 1062 /** | 1012 * @return {!Promise<!Array<!WebInspector.HeapSnapshotGridNode>>} |
| 1063 * @param {number} snapshotObjectId | 1013 */ |
| 1014 populateNodeBySnapshotObjectId(snapshotObjectId) { |
| 1015 /** |
| 1016 * @this {WebInspector.HeapSnapshotConstructorNode} |
| 1017 */ |
| 1018 function didExpand() { |
| 1019 return this._provider().nodePosition(snapshotObjectId).then(didGetNodePosi
tion.bind(this)); |
| 1020 } |
| 1021 |
| 1022 /** |
| 1023 * @this {WebInspector.HeapSnapshotConstructorNode} |
| 1024 * @param {number} nodePosition |
| 1064 * @return {!Promise<!Array<!WebInspector.HeapSnapshotGridNode>>} | 1025 * @return {!Promise<!Array<!WebInspector.HeapSnapshotGridNode>>} |
| 1065 */ | 1026 */ |
| 1066 populateNodeBySnapshotObjectId: function(snapshotObjectId) | 1027 function didGetNodePosition(nodePosition) { |
| 1067 { | 1028 if (nodePosition === -1) { |
| 1029 this.collapse(); |
| 1030 return Promise.resolve([]); |
| 1031 } else { |
| 1068 /** | 1032 /** |
| 1033 * @param {function(!Array<!WebInspector.HeapSnapshotGridNode>)} fulfill |
| 1069 * @this {WebInspector.HeapSnapshotConstructorNode} | 1034 * @this {WebInspector.HeapSnapshotConstructorNode} |
| 1070 */ | 1035 */ |
| 1071 function didExpand() | 1036 function action(fulfill) { |
| 1072 { | 1037 this._populateChildren(nodePosition, null, didPopulateChildren.bind(th
is, nodePosition, fulfill)); |
| 1073 return this._provider().nodePosition(snapshotObjectId).then(didGetNo
dePosition.bind(this)); | |
| 1074 } | 1038 } |
| 1075 | 1039 return new Promise(action.bind(this)); |
| 1076 /** | 1040 } |
| 1077 * @this {WebInspector.HeapSnapshotConstructorNode} | 1041 } |
| 1078 * @param {number} nodePosition | 1042 |
| 1079 * @return {!Promise<!Array<!WebInspector.HeapSnapshotGridNode>>} | 1043 /** |
| 1080 */ | 1044 * @this {WebInspector.HeapSnapshotConstructorNode} |
| 1081 function didGetNodePosition(nodePosition) | 1045 * @param {number} nodePosition |
| 1082 { | 1046 * @param {function(!Array<!WebInspector.HeapSnapshotGridNode>)} callback |
| 1083 if (nodePosition === -1) { | 1047 */ |
| 1084 this.collapse(); | 1048 function didPopulateChildren(nodePosition, callback) { |
| 1085 return Promise.resolve([]); | 1049 var node = /** @type {?WebInspector.HeapSnapshotGridNode} */ (this.childFo
rPosition(nodePosition)); |
| 1086 } else { | 1050 callback(node ? [this, node] : []); |
| 1087 /** | 1051 } |
| 1088 * @param {function(!Array<!WebInspector.HeapSnapshotGridNode>)}
fulfill | 1052 |
| 1089 * @this {WebInspector.HeapSnapshotConstructorNode} | 1053 this._dataGrid.resetNameFilter(); |
| 1090 */ | 1054 return this.expandWithoutPopulate().then(didExpand.bind(this)); |
| 1091 function action(fulfill) | 1055 } |
| 1092 { | 1056 |
| 1093 this._populateChildren(nodePosition, null, didPopulateChildr
en.bind(this, nodePosition, fulfill)); | 1057 /** |
| 1094 } | 1058 * @param {string} filterValue |
| 1095 return new Promise(action.bind(this)); | 1059 * @return {boolean} |
| 1096 } | 1060 */ |
| 1097 } | 1061 filteredOut(filterValue) { |
| 1098 | 1062 return this._name.toLowerCase().indexOf(filterValue) === -1; |
| 1099 /** | 1063 } |
| 1100 * @this {WebInspector.HeapSnapshotConstructorNode} | 1064 |
| 1101 * @param {number} nodePosition | 1065 /** |
| 1102 * @param {function(!Array<!WebInspector.HeapSnapshotGridNode>)} callbac
k | 1066 * @override |
| 1103 */ | 1067 * @param {string} columnId |
| 1104 function didPopulateChildren(nodePosition, callback) | 1068 * @return {!Element} |
| 1105 { | 1069 */ |
| 1106 var node = /** @type {?WebInspector.HeapSnapshotGridNode} */ (this.c
hildForPosition(nodePosition)); | 1070 createCell(columnId) { |
| 1107 callback(node ? [this, node] : []); | 1071 var cell = columnId !== 'object' ? this._createValueCell(columnId) : super.c
reateCell(columnId); |
| 1108 } | 1072 if (this._searchMatched) |
| 1109 | 1073 cell.classList.add('highlight'); |
| 1110 this._dataGrid.resetNameFilter(); | 1074 return cell; |
| 1111 return this.expandWithoutPopulate().then(didExpand.bind(this)); | 1075 } |
| 1112 }, | 1076 |
| 1113 | 1077 /** |
| 1114 /** | 1078 * @param {!WebInspector.HeapSnapshotCommon.Node} item |
| 1115 * @param {string} filterValue | 1079 * @return {!WebInspector.HeapSnapshotInstanceNode} |
| 1116 * @return {boolean} | 1080 */ |
| 1117 */ | 1081 _createChildNode(item) { |
| 1118 filteredOut: function(filterValue) | 1082 return new WebInspector.HeapSnapshotInstanceNode(this._dataGrid, this._dataG
rid.snapshot, item, false); |
| 1119 { | 1083 } |
| 1120 return this._name.toLowerCase().indexOf(filterValue) === -1; | 1084 |
| 1121 }, | 1085 /** |
| 1122 | 1086 * @return {!WebInspector.HeapSnapshotCommon.ComparatorConfig} |
| 1123 /** | 1087 */ |
| 1124 * @override | 1088 comparator() { |
| 1125 * @param {string} columnId | 1089 var sortAscending = this._dataGrid.isSortOrderAscending(); |
| 1126 * @return {!Element} | 1090 var sortColumnId = this._dataGrid.sortColumnId(); |
| 1127 */ | 1091 var sortFields = { |
| 1128 createCell: function(columnId) | 1092 object: ['name', sortAscending, 'id', true], |
| 1129 { | 1093 distance: ['distance', sortAscending, 'retainedSize', false], |
| 1130 var cell = columnId !== "object" ? this._createValueCell(columnId) : Web
Inspector.HeapSnapshotGridNode.prototype.createCell.call(this, columnId); | 1094 count: ['name', true, 'id', true], |
| 1131 if (this._searchMatched) | 1095 shallowSize: ['selfSize', sortAscending, 'id', true], |
| 1132 cell.classList.add("highlight"); | 1096 retainedSize: ['retainedSize', sortAscending, 'id', true] |
| 1133 return cell; | 1097 }[sortColumnId]; |
| 1134 }, | 1098 return WebInspector.HeapSnapshotGridNode.createComparator(sortFields); |
| 1135 | 1099 } |
| 1136 /** | 1100 |
| 1137 * @param {!WebInspector.HeapSnapshotCommon.Node} item | 1101 /** |
| 1138 * @return {!WebInspector.HeapSnapshotInstanceNode} | 1102 * @param {!WebInspector.HeapSnapshotCommon.Node} node |
| 1139 */ | 1103 * @return {number} |
| 1140 _createChildNode: function(item) | 1104 */ |
| 1141 { | 1105 _childHashForEntity(node) { |
| 1142 return new WebInspector.HeapSnapshotInstanceNode(this._dataGrid, this._d
ataGrid.snapshot, item, false); | 1106 return node.id; |
| 1143 }, | 1107 } |
| 1144 | 1108 |
| 1145 /** | 1109 /** |
| 1146 * @return {!WebInspector.HeapSnapshotCommon.ComparatorConfig} | 1110 * @param {!WebInspector.HeapSnapshotInstanceNode} childNode |
| 1147 */ | 1111 * @return {number} |
| 1148 comparator: function() | 1112 */ |
| 1149 { | 1113 _childHashForNode(childNode) { |
| 1150 var sortAscending = this._dataGrid.isSortOrderAscending(); | 1114 return childNode.snapshotNodeId; |
| 1151 var sortColumnId = this._dataGrid.sortColumnId(); | 1115 } |
| 1152 var sortFields = { | |
| 1153 object: ["name", sortAscending, "id", true], | |
| 1154 distance: ["distance", sortAscending, "retainedSize", false], | |
| 1155 count: ["name", true, "id", true], | |
| 1156 shallowSize: ["selfSize", sortAscending, "id", true], | |
| 1157 retainedSize: ["retainedSize", sortAscending, "id", true] | |
| 1158 }[sortColumnId]; | |
| 1159 return WebInspector.HeapSnapshotGridNode.createComparator(sortFields); | |
| 1160 }, | |
| 1161 | |
| 1162 /** | |
| 1163 * @param {!WebInspector.HeapSnapshotCommon.Node} node | |
| 1164 * @return {number} | |
| 1165 */ | |
| 1166 _childHashForEntity: function(node) | |
| 1167 { | |
| 1168 return node.id; | |
| 1169 }, | |
| 1170 | |
| 1171 /** | |
| 1172 * @param {!WebInspector.HeapSnapshotInstanceNode} childNode | |
| 1173 * @return {number} | |
| 1174 */ | |
| 1175 _childHashForNode: function(childNode) | |
| 1176 { | |
| 1177 return childNode.snapshotNodeId; | |
| 1178 }, | |
| 1179 | |
| 1180 __proto__: WebInspector.HeapSnapshotGridNode.prototype | |
| 1181 }; | 1116 }; |
| 1182 | 1117 |
| 1183 | |
| 1184 /** | 1118 /** |
| 1185 * @constructor | |
| 1186 * @implements {WebInspector.HeapSnapshotGridNode.ChildrenProvider} | 1119 * @implements {WebInspector.HeapSnapshotGridNode.ChildrenProvider} |
| 1187 * @param {!WebInspector.HeapSnapshotProviderProxy} addedNodesProvider | 1120 * @unrestricted |
| 1188 * @param {!WebInspector.HeapSnapshotProviderProxy} deletedNodesProvider | |
| 1189 * @param {number} addedCount | |
| 1190 * @param {number} removedCount | |
| 1191 */ | 1121 */ |
| 1192 WebInspector.HeapSnapshotDiffNodesProvider = function(addedNodesProvider, delete
dNodesProvider, addedCount, removedCount) | 1122 WebInspector.HeapSnapshotDiffNodesProvider = class { |
| 1193 { | 1123 /** |
| 1124 * @param {!WebInspector.HeapSnapshotProviderProxy} addedNodesProvider |
| 1125 * @param {!WebInspector.HeapSnapshotProviderProxy} deletedNodesProvider |
| 1126 * @param {number} addedCount |
| 1127 * @param {number} removedCount |
| 1128 */ |
| 1129 constructor(addedNodesProvider, deletedNodesProvider, addedCount, removedCount
) { |
| 1194 this._addedNodesProvider = addedNodesProvider; | 1130 this._addedNodesProvider = addedNodesProvider; |
| 1195 this._deletedNodesProvider = deletedNodesProvider; | 1131 this._deletedNodesProvider = deletedNodesProvider; |
| 1196 this._addedCount = addedCount; | 1132 this._addedCount = addedCount; |
| 1197 this._removedCount = removedCount; | 1133 this._removedCount = removedCount; |
| 1134 } |
| 1135 |
| 1136 /** |
| 1137 * @override |
| 1138 */ |
| 1139 dispose() { |
| 1140 this._addedNodesProvider.dispose(); |
| 1141 this._deletedNodesProvider.dispose(); |
| 1142 } |
| 1143 |
| 1144 /** |
| 1145 * @override |
| 1146 * @param {number} snapshotObjectId |
| 1147 * @return {!Promise<number>} |
| 1148 */ |
| 1149 nodePosition(snapshotObjectId) { |
| 1150 throw new Error('Unreachable'); |
| 1151 } |
| 1152 |
| 1153 /** |
| 1154 * @override |
| 1155 * @param {function(boolean)} callback |
| 1156 */ |
| 1157 isEmpty(callback) { |
| 1158 callback(false); |
| 1159 } |
| 1160 |
| 1161 /** |
| 1162 * @override |
| 1163 * @param {number} beginPosition |
| 1164 * @param {number} endPosition |
| 1165 * @param {function(!WebInspector.HeapSnapshotCommon.ItemsRange)} callback |
| 1166 */ |
| 1167 serializeItemsRange(beginPosition, endPosition, callback) { |
| 1168 /** |
| 1169 * @param {!WebInspector.HeapSnapshotCommon.ItemsRange} items |
| 1170 * @this {WebInspector.HeapSnapshotDiffNodesProvider} |
| 1171 */ |
| 1172 function didReceiveAllItems(items) { |
| 1173 items.totalLength = this._addedCount + this._removedCount; |
| 1174 callback(items); |
| 1175 } |
| 1176 |
| 1177 /** |
| 1178 * @param {!WebInspector.HeapSnapshotCommon.ItemsRange} addedItems |
| 1179 * @param {!WebInspector.HeapSnapshotCommon.ItemsRange} itemsRange |
| 1180 * @this {WebInspector.HeapSnapshotDiffNodesProvider} |
| 1181 */ |
| 1182 function didReceiveDeletedItems(addedItems, itemsRange) { |
| 1183 var items = itemsRange.items; |
| 1184 if (!addedItems.items.length) |
| 1185 addedItems.startPosition = this._addedCount + itemsRange.startPosition; |
| 1186 for (var i = 0; i < items.length; i++) { |
| 1187 items[i].isAddedNotRemoved = false; |
| 1188 addedItems.items.push(items[i]); |
| 1189 } |
| 1190 addedItems.endPosition = this._addedCount + itemsRange.endPosition; |
| 1191 didReceiveAllItems.call(this, addedItems); |
| 1192 } |
| 1193 |
| 1194 /** |
| 1195 * @param {!WebInspector.HeapSnapshotCommon.ItemsRange} itemsRange |
| 1196 * @this {WebInspector.HeapSnapshotDiffNodesProvider} |
| 1197 */ |
| 1198 function didReceiveAddedItems(itemsRange) { |
| 1199 var items = itemsRange.items; |
| 1200 for (var i = 0; i < items.length; i++) |
| 1201 items[i].isAddedNotRemoved = true; |
| 1202 if (itemsRange.endPosition < endPosition) |
| 1203 return this._deletedNodesProvider.serializeItemsRange( |
| 1204 0, endPosition - itemsRange.endPosition, didReceiveDeletedItems.bind
(this, itemsRange)); |
| 1205 |
| 1206 itemsRange.totalLength = this._addedCount + this._removedCount; |
| 1207 didReceiveAllItems.call(this, itemsRange); |
| 1208 } |
| 1209 |
| 1210 if (beginPosition < this._addedCount) { |
| 1211 this._addedNodesProvider.serializeItemsRange(beginPosition, endPosition, d
idReceiveAddedItems.bind(this)); |
| 1212 } else { |
| 1213 var emptyRange = new WebInspector.HeapSnapshotCommon.ItemsRange(0, 0, 0, [
]); |
| 1214 this._deletedNodesProvider.serializeItemsRange( |
| 1215 beginPosition - this._addedCount, endPosition - this._addedCount, |
| 1216 didReceiveDeletedItems.bind(this, emptyRange)); |
| 1217 } |
| 1218 } |
| 1219 |
| 1220 /** |
| 1221 * @override |
| 1222 * @param {!WebInspector.HeapSnapshotCommon.ComparatorConfig} comparator |
| 1223 * @return {!Promise<?>} |
| 1224 */ |
| 1225 sortAndRewind(comparator) { |
| 1226 /** |
| 1227 * @this {WebInspector.HeapSnapshotDiffNodesProvider} |
| 1228 * @return {!Promise<?>} |
| 1229 */ |
| 1230 function afterSort() { |
| 1231 return this._deletedNodesProvider.sortAndRewind(comparator); |
| 1232 } |
| 1233 return this._addedNodesProvider.sortAndRewind(comparator).then(afterSort.bin
d(this)); |
| 1234 } |
| 1198 }; | 1235 }; |
| 1199 | 1236 |
| 1200 WebInspector.HeapSnapshotDiffNodesProvider.prototype = { | |
| 1201 /** | |
| 1202 * @override | |
| 1203 */ | |
| 1204 dispose: function() | |
| 1205 { | |
| 1206 this._addedNodesProvider.dispose(); | |
| 1207 this._deletedNodesProvider.dispose(); | |
| 1208 }, | |
| 1209 | |
| 1210 /** | |
| 1211 * @override | |
| 1212 * @param {number} snapshotObjectId | |
| 1213 * @return {!Promise<number>} | |
| 1214 */ | |
| 1215 nodePosition: function(snapshotObjectId) | |
| 1216 { | |
| 1217 throw new Error("Unreachable"); | |
| 1218 }, | |
| 1219 | |
| 1220 /** | |
| 1221 * @override | |
| 1222 * @param {function(boolean)} callback | |
| 1223 */ | |
| 1224 isEmpty: function(callback) | |
| 1225 { | |
| 1226 callback(false); | |
| 1227 }, | |
| 1228 | |
| 1229 /** | |
| 1230 * @override | |
| 1231 * @param {number} beginPosition | |
| 1232 * @param {number} endPosition | |
| 1233 * @param {function(!WebInspector.HeapSnapshotCommon.ItemsRange)} callback | |
| 1234 */ | |
| 1235 serializeItemsRange: function(beginPosition, endPosition, callback) | |
| 1236 { | |
| 1237 /** | |
| 1238 * @param {!WebInspector.HeapSnapshotCommon.ItemsRange} items | |
| 1239 * @this {WebInspector.HeapSnapshotDiffNodesProvider} | |
| 1240 */ | |
| 1241 function didReceiveAllItems(items) | |
| 1242 { | |
| 1243 items.totalLength = this._addedCount + this._removedCount; | |
| 1244 callback(items); | |
| 1245 } | |
| 1246 | |
| 1247 /** | |
| 1248 * @param {!WebInspector.HeapSnapshotCommon.ItemsRange} addedItems | |
| 1249 * @param {!WebInspector.HeapSnapshotCommon.ItemsRange} itemsRange | |
| 1250 * @this {WebInspector.HeapSnapshotDiffNodesProvider} | |
| 1251 */ | |
| 1252 function didReceiveDeletedItems(addedItems, itemsRange) | |
| 1253 { | |
| 1254 var items = itemsRange.items; | |
| 1255 if (!addedItems.items.length) | |
| 1256 addedItems.startPosition = this._addedCount + itemsRange.startPo
sition; | |
| 1257 for (var i = 0; i < items.length; i++) { | |
| 1258 items[i].isAddedNotRemoved = false; | |
| 1259 addedItems.items.push(items[i]); | |
| 1260 } | |
| 1261 addedItems.endPosition = this._addedCount + itemsRange.endPosition; | |
| 1262 didReceiveAllItems.call(this, addedItems); | |
| 1263 } | |
| 1264 | |
| 1265 /** | |
| 1266 * @param {!WebInspector.HeapSnapshotCommon.ItemsRange} itemsRange | |
| 1267 * @this {WebInspector.HeapSnapshotDiffNodesProvider} | |
| 1268 */ | |
| 1269 function didReceiveAddedItems(itemsRange) | |
| 1270 { | |
| 1271 var items = itemsRange.items; | |
| 1272 for (var i = 0; i < items.length; i++) | |
| 1273 items[i].isAddedNotRemoved = true; | |
| 1274 if (itemsRange.endPosition < endPosition) | |
| 1275 return this._deletedNodesProvider.serializeItemsRange(0, endPosi
tion - itemsRange.endPosition, didReceiveDeletedItems.bind(this, itemsRange)); | |
| 1276 | |
| 1277 itemsRange.totalLength = this._addedCount + this._removedCount; | |
| 1278 didReceiveAllItems.call(this, itemsRange); | |
| 1279 } | |
| 1280 | |
| 1281 if (beginPosition < this._addedCount) { | |
| 1282 this._addedNodesProvider.serializeItemsRange(beginPosition, endPosit
ion, didReceiveAddedItems.bind(this)); | |
| 1283 } else { | |
| 1284 var emptyRange = new WebInspector.HeapSnapshotCommon.ItemsRange(0, 0
, 0, []); | |
| 1285 this._deletedNodesProvider.serializeItemsRange(beginPosition - this.
_addedCount, endPosition - this._addedCount, didReceiveDeletedItems.bind(this, e
mptyRange)); | |
| 1286 } | |
| 1287 }, | |
| 1288 | |
| 1289 /** | |
| 1290 * @override | |
| 1291 * @param {!WebInspector.HeapSnapshotCommon.ComparatorConfig} comparator | |
| 1292 * @return {!Promise<?>} | |
| 1293 */ | |
| 1294 sortAndRewind: function(comparator) | |
| 1295 { | |
| 1296 /** | |
| 1297 * @this {WebInspector.HeapSnapshotDiffNodesProvider} | |
| 1298 * @return {!Promise<?>} | |
| 1299 */ | |
| 1300 function afterSort() | |
| 1301 { | |
| 1302 return this._deletedNodesProvider.sortAndRewind(comparator); | |
| 1303 } | |
| 1304 return this._addedNodesProvider.sortAndRewind(comparator).then(afterSort
.bind(this)); | |
| 1305 } | |
| 1306 }; | |
| 1307 | |
| 1308 /** | 1237 /** |
| 1309 * @constructor | 1238 * @unrestricted |
| 1310 * @param {!WebInspector.HeapSnapshotDiffDataGrid} dataGrid | |
| 1311 * @param {string} className | |
| 1312 * @param {!WebInspector.HeapSnapshotCommon.DiffForClass} diffForClass | |
| 1313 * @extends {WebInspector.HeapSnapshotGridNode} | |
| 1314 */ | 1239 */ |
| 1315 WebInspector.HeapSnapshotDiffNode = function(dataGrid, className, diffForClass) | 1240 WebInspector.HeapSnapshotDiffNode = class extends WebInspector.HeapSnapshotGridN
ode { |
| 1316 { | 1241 /** |
| 1317 WebInspector.HeapSnapshotGridNode.call(this, dataGrid, true); | 1242 * @param {!WebInspector.HeapSnapshotDiffDataGrid} dataGrid |
| 1243 * @param {string} className |
| 1244 * @param {!WebInspector.HeapSnapshotCommon.DiffForClass} diffForClass |
| 1245 */ |
| 1246 constructor(dataGrid, className, diffForClass) { |
| 1247 super(dataGrid, true); |
| 1318 this._name = className; | 1248 this._name = className; |
| 1319 this._addedCount = diffForClass.addedCount; | 1249 this._addedCount = diffForClass.addedCount; |
| 1320 this._removedCount = diffForClass.removedCount; | 1250 this._removedCount = diffForClass.removedCount; |
| 1321 this._countDelta = diffForClass.countDelta; | 1251 this._countDelta = diffForClass.countDelta; |
| 1322 this._addedSize = diffForClass.addedSize; | 1252 this._addedSize = diffForClass.addedSize; |
| 1323 this._removedSize = diffForClass.removedSize; | 1253 this._removedSize = diffForClass.removedSize; |
| 1324 this._sizeDelta = diffForClass.sizeDelta; | 1254 this._sizeDelta = diffForClass.sizeDelta; |
| 1325 this._deletedIndexes = diffForClass.deletedIndexes; | 1255 this._deletedIndexes = diffForClass.deletedIndexes; |
| 1326 this.data = { | 1256 this.data = { |
| 1327 "object": className, | 1257 'object': className, |
| 1328 "addedCount": Number.withThousandsSeparator(this._addedCount), | 1258 'addedCount': Number.withThousandsSeparator(this._addedCount), |
| 1329 "removedCount": Number.withThousandsSeparator(this._removedCount), | 1259 'removedCount': Number.withThousandsSeparator(this._removedCount), |
| 1330 "countDelta": this._signForDelta(this._countDelta) + Number.withThousan
dsSeparator(Math.abs(this._countDelta)), | 1260 'countDelta': this._signForDelta(this._countDelta) + Number.withThousandsS
eparator(Math.abs(this._countDelta)), |
| 1331 "addedSize": Number.withThousandsSeparator(this._addedSize), | 1261 'addedSize': Number.withThousandsSeparator(this._addedSize), |
| 1332 "removedSize": Number.withThousandsSeparator(this._removedSize), | 1262 'removedSize': Number.withThousandsSeparator(this._removedSize), |
| 1333 "sizeDelta": this._signForDelta(this._sizeDelta) + Number.withThousandsS
eparator(Math.abs(this._sizeDelta)) | 1263 'sizeDelta': this._signForDelta(this._sizeDelta) + Number.withThousandsSep
arator(Math.abs(this._sizeDelta)) |
| 1334 }; | 1264 }; |
| 1265 } |
| 1266 |
| 1267 /** |
| 1268 * @override |
| 1269 * @return {!WebInspector.HeapSnapshotDiffNodesProvider} |
| 1270 */ |
| 1271 createProvider() { |
| 1272 var tree = this._dataGrid; |
| 1273 return new WebInspector.HeapSnapshotDiffNodesProvider( |
| 1274 tree.snapshot.createAddedNodesProvider(tree.baseSnapshot.uid, this._name
), |
| 1275 tree.baseSnapshot.createDeletedNodesProvider(this._deletedIndexes), this
._addedCount, this._removedCount); |
| 1276 } |
| 1277 |
| 1278 /** |
| 1279 * @override |
| 1280 * @param {string} columnId |
| 1281 * @return {!Element} |
| 1282 */ |
| 1283 createCell(columnId) { |
| 1284 var cell = super.createCell(columnId); |
| 1285 if (columnId !== 'object') |
| 1286 cell.classList.add('numeric-column'); |
| 1287 return cell; |
| 1288 } |
| 1289 |
| 1290 /** |
| 1291 * @param {!WebInspector.HeapSnapshotCommon.Node} item |
| 1292 * @return {!WebInspector.HeapSnapshotInstanceNode} |
| 1293 */ |
| 1294 _createChildNode(item) { |
| 1295 if (item.isAddedNotRemoved) |
| 1296 return new WebInspector.HeapSnapshotInstanceNode(this._dataGrid, this._dat
aGrid.snapshot, item, false); |
| 1297 else |
| 1298 return new WebInspector.HeapSnapshotInstanceNode(this._dataGrid, this._dat
aGrid.baseSnapshot, item, true); |
| 1299 } |
| 1300 |
| 1301 /** |
| 1302 * @param {!WebInspector.HeapSnapshotCommon.Node} node |
| 1303 * @return {number} |
| 1304 */ |
| 1305 _childHashForEntity(node) { |
| 1306 return node.id; |
| 1307 } |
| 1308 |
| 1309 /** |
| 1310 * @param {!WebInspector.HeapSnapshotInstanceNode} childNode |
| 1311 * @return {number} |
| 1312 */ |
| 1313 _childHashForNode(childNode) { |
| 1314 return childNode.snapshotNodeId; |
| 1315 } |
| 1316 |
| 1317 /** |
| 1318 * @return {!WebInspector.HeapSnapshotCommon.ComparatorConfig} |
| 1319 */ |
| 1320 comparator() { |
| 1321 var sortAscending = this._dataGrid.isSortOrderAscending(); |
| 1322 var sortColumnId = this._dataGrid.sortColumnId(); |
| 1323 var sortFields = { |
| 1324 object: ['name', sortAscending, 'id', true], |
| 1325 addedCount: ['name', true, 'id', true], |
| 1326 removedCount: ['name', true, 'id', true], |
| 1327 countDelta: ['name', true, 'id', true], |
| 1328 addedSize: ['selfSize', sortAscending, 'id', true], |
| 1329 removedSize: ['selfSize', sortAscending, 'id', true], |
| 1330 sizeDelta: ['selfSize', sortAscending, 'id', true] |
| 1331 }[sortColumnId]; |
| 1332 return WebInspector.HeapSnapshotGridNode.createComparator(sortFields); |
| 1333 } |
| 1334 |
| 1335 /** |
| 1336 * @param {string} filterValue |
| 1337 * @return {boolean} |
| 1338 */ |
| 1339 filteredOut(filterValue) { |
| 1340 return this._name.toLowerCase().indexOf(filterValue) === -1; |
| 1341 } |
| 1342 |
| 1343 _signForDelta(delta) { |
| 1344 if (delta === 0) |
| 1345 return ''; |
| 1346 if (delta > 0) |
| 1347 return '+'; |
| 1348 else |
| 1349 return '\u2212'; // Math minus sign, same width as plus. |
| 1350 } |
| 1335 }; | 1351 }; |
| 1336 | 1352 |
| 1337 WebInspector.HeapSnapshotDiffNode.prototype = { | |
| 1338 /** | |
| 1339 * @override | |
| 1340 * @return {!WebInspector.HeapSnapshotDiffNodesProvider} | |
| 1341 */ | |
| 1342 createProvider: function() | |
| 1343 { | |
| 1344 var tree = this._dataGrid; | |
| 1345 return new WebInspector.HeapSnapshotDiffNodesProvider( | |
| 1346 tree.snapshot.createAddedNodesProvider(tree.baseSnapshot.uid, this._
name), | |
| 1347 tree.baseSnapshot.createDeletedNodesProvider(this._deletedIndexes), | |
| 1348 this._addedCount, | |
| 1349 this._removedCount); | |
| 1350 }, | |
| 1351 | |
| 1352 /** | |
| 1353 * @override | |
| 1354 * @param {string} columnId | |
| 1355 * @return {!Element} | |
| 1356 */ | |
| 1357 createCell: function(columnId) | |
| 1358 { | |
| 1359 var cell = WebInspector.HeapSnapshotGridNode.prototype.createCell.call(t
his, columnId); | |
| 1360 if (columnId !== "object") | |
| 1361 cell.classList.add("numeric-column"); | |
| 1362 return cell; | |
| 1363 }, | |
| 1364 | |
| 1365 /** | |
| 1366 * @param {!WebInspector.HeapSnapshotCommon.Node} item | |
| 1367 * @return {!WebInspector.HeapSnapshotInstanceNode} | |
| 1368 */ | |
| 1369 _createChildNode: function(item) | |
| 1370 { | |
| 1371 if (item.isAddedNotRemoved) | |
| 1372 return new WebInspector.HeapSnapshotInstanceNode(this._dataGrid, thi
s._dataGrid.snapshot, item, false); | |
| 1373 else | |
| 1374 return new WebInspector.HeapSnapshotInstanceNode(this._dataGrid, thi
s._dataGrid.baseSnapshot, item, true); | |
| 1375 }, | |
| 1376 | |
| 1377 /** | |
| 1378 * @param {!WebInspector.HeapSnapshotCommon.Node} node | |
| 1379 * @return {number} | |
| 1380 */ | |
| 1381 _childHashForEntity: function(node) | |
| 1382 { | |
| 1383 return node.id; | |
| 1384 }, | |
| 1385 | |
| 1386 /** | |
| 1387 * @param {!WebInspector.HeapSnapshotInstanceNode} childNode | |
| 1388 * @return {number} | |
| 1389 */ | |
| 1390 _childHashForNode: function(childNode) | |
| 1391 { | |
| 1392 return childNode.snapshotNodeId; | |
| 1393 }, | |
| 1394 | |
| 1395 /** | |
| 1396 * @return {!WebInspector.HeapSnapshotCommon.ComparatorConfig} | |
| 1397 */ | |
| 1398 comparator: function() | |
| 1399 { | |
| 1400 var sortAscending = this._dataGrid.isSortOrderAscending(); | |
| 1401 var sortColumnId = this._dataGrid.sortColumnId(); | |
| 1402 var sortFields = { | |
| 1403 object: ["name", sortAscending, "id", true], | |
| 1404 addedCount: ["name", true, "id", true], | |
| 1405 removedCount: ["name", true, "id", true], | |
| 1406 countDelta: ["name", true, "id", true], | |
| 1407 addedSize: ["selfSize", sortAscending, "id", true], | |
| 1408 removedSize: ["selfSize", sortAscending, "id", true], | |
| 1409 sizeDelta: ["selfSize", sortAscending, "id", true] | |
| 1410 }[sortColumnId]; | |
| 1411 return WebInspector.HeapSnapshotGridNode.createComparator(sortFields); | |
| 1412 }, | |
| 1413 | |
| 1414 /** | |
| 1415 * @param {string} filterValue | |
| 1416 * @return {boolean} | |
| 1417 */ | |
| 1418 filteredOut: function(filterValue) | |
| 1419 { | |
| 1420 return this._name.toLowerCase().indexOf(filterValue) === -1; | |
| 1421 }, | |
| 1422 | |
| 1423 _signForDelta: function(delta) | |
| 1424 { | |
| 1425 if (delta === 0) | |
| 1426 return ""; | |
| 1427 if (delta > 0) | |
| 1428 return "+"; | |
| 1429 else | |
| 1430 return "\u2212"; // Math minus sign, same width as plus. | |
| 1431 }, | |
| 1432 | |
| 1433 __proto__: WebInspector.HeapSnapshotGridNode.prototype | |
| 1434 }; | |
| 1435 | |
| 1436 | |
| 1437 /** | 1353 /** |
| 1438 * @constructor | 1354 * @unrestricted |
| 1439 * @extends {WebInspector.HeapSnapshotGridNode} | |
| 1440 * @param {!WebInspector.AllocationDataGrid} dataGrid | |
| 1441 * @param {!WebInspector.HeapSnapshotCommon.SerializedAllocationNode} data | |
| 1442 */ | 1355 */ |
| 1443 WebInspector.AllocationGridNode = function(dataGrid, data) | 1356 WebInspector.AllocationGridNode = class extends WebInspector.HeapSnapshotGridNod
e { |
| 1444 { | 1357 /** |
| 1445 WebInspector.HeapSnapshotGridNode.call(this, dataGrid, data.hasChildren); | 1358 * @param {!WebInspector.AllocationDataGrid} dataGrid |
| 1359 * @param {!WebInspector.HeapSnapshotCommon.SerializedAllocationNode} data |
| 1360 */ |
| 1361 constructor(dataGrid, data) { |
| 1362 super(dataGrid, data.hasChildren); |
| 1446 this._populated = false; | 1363 this._populated = false; |
| 1447 this._allocationNode = data; | 1364 this._allocationNode = data; |
| 1448 this.data = { | 1365 this.data = { |
| 1449 "liveCount": Number.withThousandsSeparator(data.liveCount), | 1366 'liveCount': Number.withThousandsSeparator(data.liveCount), |
| 1450 "count": Number.withThousandsSeparator(data.count), | 1367 'count': Number.withThousandsSeparator(data.count), |
| 1451 "liveSize": Number.withThousandsSeparator(data.liveSize), | 1368 'liveSize': Number.withThousandsSeparator(data.liveSize), |
| 1452 "size": Number.withThousandsSeparator(data.size), | 1369 'size': Number.withThousandsSeparator(data.size), |
| 1453 "name": data.name | 1370 'name': data.name |
| 1454 }; | 1371 }; |
| 1455 }; | 1372 } |
| 1456 | 1373 |
| 1457 WebInspector.AllocationGridNode.prototype = { | 1374 /** |
| 1458 populate: function() | 1375 * @override |
| 1459 { | 1376 */ |
| 1460 if (this._populated) | 1377 populate() { |
| 1461 return; | 1378 if (this._populated) |
| 1462 this._populated = true; | 1379 return; |
| 1463 this._dataGrid.snapshot.allocationNodeCallers(this._allocationNode.id, d
idReceiveCallers.bind(this)); | 1380 this._populated = true; |
| 1464 | 1381 this._dataGrid.snapshot.allocationNodeCallers(this._allocationNode.id, didRe
ceiveCallers.bind(this)); |
| 1465 /** | |
| 1466 * @param {!WebInspector.HeapSnapshotCommon.AllocationNodeCallers} calle
rs | |
| 1467 * @this {WebInspector.AllocationGridNode} | |
| 1468 */ | |
| 1469 function didReceiveCallers(callers) | |
| 1470 { | |
| 1471 var callersChain = callers.nodesWithSingleCaller; | |
| 1472 var parentNode = this; | |
| 1473 var dataGrid = /** @type {!WebInspector.AllocationDataGrid} */ (this
._dataGrid); | |
| 1474 for (var i = 0; i < callersChain.length; i++) { | |
| 1475 var child = new WebInspector.AllocationGridNode(dataGrid, caller
sChain[i]); | |
| 1476 dataGrid.appendNode(parentNode, child); | |
| 1477 parentNode = child; | |
| 1478 parentNode._populated = true; | |
| 1479 if (this.expanded) | |
| 1480 parentNode.expand(); | |
| 1481 } | |
| 1482 | |
| 1483 var callersBranch = callers.branchingCallers; | |
| 1484 callersBranch.sort(this._dataGrid._createComparator()); | |
| 1485 for (var i = 0; i < callersBranch.length; i++) | |
| 1486 dataGrid.appendNode(parentNode, new WebInspector.AllocationGridN
ode(dataGrid, callersBranch[i])); | |
| 1487 dataGrid.updateVisibleNodes(true); | |
| 1488 } | |
| 1489 }, | |
| 1490 | 1382 |
| 1491 /** | 1383 /** |
| 1492 * @override | 1384 * @param {!WebInspector.HeapSnapshotCommon.AllocationNodeCallers} callers |
| 1385 * @this {WebInspector.AllocationGridNode} |
| 1493 */ | 1386 */ |
| 1494 expand: function() | 1387 function didReceiveCallers(callers) { |
| 1495 { | 1388 var callersChain = callers.nodesWithSingleCaller; |
| 1496 WebInspector.HeapSnapshotGridNode.prototype.expand.call(this); | 1389 var parentNode = this; |
| 1497 if (this.children.length === 1) | 1390 var dataGrid = /** @type {!WebInspector.AllocationDataGrid} */ (this._data
Grid); |
| 1498 this.children[0].expand(); | 1391 for (var i = 0; i < callersChain.length; i++) { |
| 1499 }, | 1392 var child = new WebInspector.AllocationGridNode(dataGrid, callersChain[i
]); |
| 1393 dataGrid.appendNode(parentNode, child); |
| 1394 parentNode = child; |
| 1395 parentNode._populated = true; |
| 1396 if (this.expanded) |
| 1397 parentNode.expand(); |
| 1398 } |
| 1500 | 1399 |
| 1501 /** | 1400 var callersBranch = callers.branchingCallers; |
| 1502 * @override | 1401 callersBranch.sort(this._dataGrid._createComparator()); |
| 1503 * @param {string} columnId | 1402 for (var i = 0; i < callersBranch.length; i++) |
| 1504 * @return {!Element} | 1403 dataGrid.appendNode(parentNode, new WebInspector.AllocationGridNode(data
Grid, callersBranch[i])); |
| 1505 */ | 1404 dataGrid.updateVisibleNodes(true); |
| 1506 createCell: function(columnId) | 1405 } |
| 1507 { | 1406 } |
| 1508 if (columnId !== "name") | |
| 1509 return this._createValueCell(columnId); | |
| 1510 | 1407 |
| 1511 var cell = WebInspector.HeapSnapshotGridNode.prototype.createCell.call(t
his, columnId); | 1408 /** |
| 1512 var allocationNode = this._allocationNode; | 1409 * @override |
| 1513 var target = this._dataGrid.target(); | 1410 */ |
| 1514 if (allocationNode.scriptId) { | 1411 expand() { |
| 1515 var linkifier = this._dataGrid._linkifier; | 1412 super.expand(); |
| 1516 var urlElement = linkifier.linkifyScriptLocation(target, String(allo
cationNode.scriptId), allocationNode.scriptName, allocationNode.line - 1, alloca
tionNode.column - 1, "profile-node-file"); | 1413 if (this.children.length === 1) |
| 1517 urlElement.style.maxWidth = "75%"; | 1414 this.children[0].expand(); |
| 1518 cell.insertBefore(urlElement, cell.firstChild); | 1415 } |
| 1519 } | |
| 1520 return cell; | |
| 1521 }, | |
| 1522 | 1416 |
| 1523 /** | 1417 /** |
| 1524 * @return {number} | 1418 * @override |
| 1525 */ | 1419 * @param {string} columnId |
| 1526 allocationNodeId: function() | 1420 * @return {!Element} |
| 1527 { | 1421 */ |
| 1528 return this._allocationNode.id; | 1422 createCell(columnId) { |
| 1529 }, | 1423 if (columnId !== 'name') |
| 1424 return this._createValueCell(columnId); |
| 1530 | 1425 |
| 1531 __proto__: WebInspector.HeapSnapshotGridNode.prototype | 1426 var cell = super.createCell(columnId); |
| 1427 var allocationNode = this._allocationNode; |
| 1428 var target = this._dataGrid.target(); |
| 1429 if (allocationNode.scriptId) { |
| 1430 var linkifier = this._dataGrid._linkifier; |
| 1431 var urlElement = linkifier.linkifyScriptLocation( |
| 1432 target, String(allocationNode.scriptId), allocationNode.scriptName, al
locationNode.line - 1, |
| 1433 allocationNode.column - 1, 'profile-node-file'); |
| 1434 urlElement.style.maxWidth = '75%'; |
| 1435 cell.insertBefore(urlElement, cell.firstChild); |
| 1436 } |
| 1437 return cell; |
| 1438 } |
| 1439 |
| 1440 /** |
| 1441 * @return {number} |
| 1442 */ |
| 1443 allocationNodeId() { |
| 1444 return this._allocationNode.id; |
| 1445 } |
| 1532 }; | 1446 }; |
| OLD | NEW |