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 |