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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotGridNodes.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 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 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698