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

Side by Side Diff: chrome/tools/test/reference_build/chrome_linux/resources/inspector/heap_profiler_panel.js

Issue 177049: On Linux, move the passing of filedescriptors to a dedicated socketpair(). (Closed)
Patch Set: Removed *.d files from reference build Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6 * @fileoverview Heap profiler panel implementation.
7 */
8
9 WebInspector.HeapProfilerPanel = function() {
10 WebInspector.Panel.call(this);
11
12 this.element.addStyleClass("heap-profiler");
13
14 this.sidebarElement = document.createElement("div");
15 this.sidebarElement.id = "heap-snapshot-sidebar";
16 this.sidebarElement.className = "sidebar";
17 this.element.appendChild(this.sidebarElement);
18
19 this.sidebarResizeElement = document.createElement("div");
20 this.sidebarResizeElement.className = "sidebar-resizer-vertical";
21 this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDr agging.bind(this), false);
22 this.element.appendChild(this.sidebarResizeElement);
23
24 this.sidebarTreeElement = document.createElement("ol");
25 this.sidebarTreeElement.className = "sidebar-tree";
26 this.sidebarElement.appendChild(this.sidebarTreeElement);
27
28 this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
29
30 this.snapshotViews = document.createElement("div");
31 this.snapshotViews.id = "heap-snapshot-views";
32 this.element.appendChild(this.snapshotViews);
33
34 this.snapshotButton = new WebInspector.StatusBarButton(WebInspector.UIString ("Take heap snapshot."), "heap-snapshot-status-bar-item");
35 this.snapshotButton.addEventListener("click", this._snapshotClicked.bind(thi s), false);
36
37 this.snapshotViewStatusBarItemsContainer = document.createElement("div");
38 this.snapshotViewStatusBarItemsContainer.id = "heap-snapshot-status-bar-item s";
39
40 this.reset();
41 };
42
43 WebInspector.HeapProfilerPanel.prototype = {
44 toolbarItemClass: "heap-profiler",
45
46 get toolbarItemLabel() {
47 return WebInspector.UIString("Heap");
48 },
49
50 get statusBarItems() {
51 return [this.snapshotButton.element, this.snapshotViewStatusBarItemsCont ainer];
52 },
53
54 show: function() {
55 WebInspector.Panel.prototype.show.call(this);
56 this._updateSidebarWidth();
57 },
58
59 reset: function() {
60 if (this._snapshots) {
61 var snapshotsLength = this._snapshots.length;
62 for (var i = 0; i < snapshotsLength; ++i) {
63 var snapshot = this._snapshots[i];
64 delete snapshot._snapshotView;
65 }
66 }
67
68 this._snapshots = [];
69
70 this.sidebarTreeElement.removeStyleClass("some-expandable");
71
72 this.sidebarTree.removeChildren();
73 this.snapshotViews.removeChildren();
74
75 this.snapshotViewStatusBarItemsContainer.removeChildren();
76 },
77
78 handleKeyEvent: function(event) {
79 this.sidebarTree.handleKeyEvent(event);
80 },
81
82 addSnapshot: function(snapshot) {
83 this._snapshots.push(snapshot);
84 snapshot.list = this._snapshots;
85 snapshot.listIndex = this._snapshots.length - 1;
86
87 var snapshotsTreeElement = new WebInspector.HeapSnapshotSidebarTreeEleme nt(snapshot);
88 snapshotsTreeElement.small = false;
89 snapshot._snapshotsTreeElement = snapshotsTreeElement;
90
91 this.sidebarTree.appendChild(snapshotsTreeElement);
92
93 this.dispatchEventToListeners("snapshot added");
94 },
95
96 showSnapshot: function(snapshot) {
97 if (!snapshot)
98 return;
99
100 if (this.visibleView)
101 this.visibleView.hide();
102 var view = this.snapshotViewForSnapshot(snapshot);
103 view.show(this.snapshotViews);
104 this.visibleView = view;
105
106 this.snapshotViewStatusBarItemsContainer.removeChildren();
107 var statusBarItems = view.statusBarItems;
108 for (var i = 0; i < statusBarItems.length; ++i)
109 this.snapshotViewStatusBarItemsContainer.appendChild(statusBarItems[ i]);
110 },
111
112 showView: function(view)
113 {
114 this.showSnapshot(view.snapshot);
115 },
116
117 snapshotViewForSnapshot: function(snapshot)
118 {
119 if (!snapshot)
120 return null;
121 if (!snapshot._snapshotView)
122 snapshot._snapshotView = new WebInspector.HeapSnapshotView(this, sna pshot);
123 return snapshot._snapshotView;
124 },
125
126 closeVisibleView: function()
127 {
128 if (this.visibleView)
129 this.visibleView.hide();
130 delete this.visibleView;
131 },
132
133 _snapshotClicked: function() {
134 devtools.tools.getDebuggerAgent().startProfiling(
135 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_HEAP_SNAPSHOT |
136 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_HEAP_STAT S |
137 devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_JS_CONSTR UCTORS);
138 },
139
140 _startSidebarDragging: function(event)
141 {
142 WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDr agging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
143 },
144
145 _sidebarDragging: function(event)
146 {
147 this._updateSidebarWidth(event.pageX);
148
149 event.preventDefault();
150 },
151
152 _endSidebarDragging: function(event)
153 {
154 WebInspector.elementDragEnd(event);
155 },
156
157 _updateSidebarWidth: function(width)
158 {
159 if (this.sidebarElement.offsetWidth <= 0) {
160 // The stylesheet hasn"t loaded yet or the window is closed,
161 // so we can"t calculate what is need. Return early.
162 return;
163 }
164
165 if (!("_currentSidebarWidth" in this))
166 this._currentSidebarWidth = this.sidebarElement.offsetWidth;
167 if (typeof width === "undefined")
168 width = this._currentSidebarWidth;
169
170 width = Number.constrain(width, Preferences.minSidebarWidth, window.inne rWidth / 2);
171 this._currentSidebarWidth = width;
172 this.sidebarElement.style.width = width + "px";
173 this.snapshotViews.style.left = width + "px";
174 this.snapshotViewStatusBarItemsContainer.style.left = width + "px";
175 this.sidebarResizeElement.style.left = (width - 3) + "px";
176 }
177 };
178
179 WebInspector.HeapProfilerPanel.prototype.__proto__ = WebInspector.Panel.prototyp e;
180
181 WebInspector.HeapSnapshotView = function(parent, snapshot)
182 {
183 WebInspector.View.call(this);
184
185 this.element.addStyleClass("heap-snapshot-view");
186
187 this.parent = parent;
188 this.parent.addEventListener("snapshot added", this._updateBaseOptions, this );
189
190 this.showCountAsPercent = true;
191 this.showSizeAsPercent = true;
192 this.showCountDeltaAsPercent = true;
193 this.showSizeDeltaAsPercent = true;
194
195 this.summaryBar = new WebInspector.SummaryBar(this.categories);
196 this.summaryBar.element.id = "heap-snapshot-summary";
197 this.summaryBar.calculator = new WebInspector.HeapSummaryCalculator(snapshot .used);
198 this.element.appendChild(this.summaryBar.element);
199
200 var columns = { "cons": { title: WebInspector.UIString("Constructor"), discl osure: true, sortable: true },
201 "count": { title: WebInspector.UIString("Count"), width: "54 px", sortable: true },
202 "size": { title: WebInspector.UIString("Size"), width: "72px ", sort: "descending", sortable: true },
203 "countDelta": { title: WebInspector.UIString("\xb1 Count"), width: "72px", sortable: true },
204 "sizeDelta": { title: WebInspector.UIString("\xb1 Size"), wi dth: "72px", sortable: true } };
205
206 this.dataGrid = new WebInspector.DataGrid(columns);
207 this.dataGrid.addEventListener("sorting changed", this._sortData, this);
208 this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGri d.bind(this), true);
209 this.element.appendChild(this.dataGrid.element);
210
211 this.snapshot = snapshot;
212
213 this.baseSelectElement = document.createElement("select");
214 this.baseSelectElement.className = "status-bar-item";
215 this.baseSelectElement.addEventListener("change", this._changeBase.bind(this ), false);
216 this._updateBaseOptions();
217 if (this.snapshot.listIndex > 0)
218 this.baseSelectElement.selectedIndex = this.snapshot.listIndex - 1;
219 else
220 this.baseSelectElement.selectedIndex = this.snapshot.listIndex;
221 this._resetDataGridList();
222
223 this.percentButton = new WebInspector.StatusBarButton("", "percent-time-stat us-bar-item status-bar-item");
224 this.percentButton.addEventListener("click", this._percentClicked.bind(this) , false);
225
226 this.refresh();
227
228 this._updatePercentButton();
229 };
230
231 WebInspector.HeapSnapshotView.prototype = {
232
233 get categories()
234 {
235 return {code: {title: WebInspector.UIString("Code"), color: {r: 255, g: 121, b: 0}}, data: {title: WebInspector.UIString("Objects and Data"), color: {r: 47, g: 102, b: 236}}, other: {title: WebInspector.UIString("Other"), color: {r: 186, g: 186, b: 186}}};
236 },
237
238 get statusBarItems()
239 {
240 return [this.baseSelectElement, this.percentButton.element];
241 },
242
243 get snapshot()
244 {
245 return this._snapshot;
246 },
247
248 set snapshot(snapshot)
249 {
250 this._snapshot = snapshot;
251 },
252
253 show: function(parentElement)
254 {
255 WebInspector.View.prototype.show.call(this, parentElement);
256 this.dataGrid.updateWidths();
257 },
258
259 resize: function()
260 {
261 if (this.dataGrid)
262 this.dataGrid.updateWidths();
263 },
264
265 refresh: function()
266 {
267 this.dataGrid.removeChildren();
268
269 var children = this.snapshotDataGridList.children;
270 var count = children.length;
271 for (var index = 0; index < count; ++index)
272 this.dataGrid.appendChild(children[index]);
273
274 this._updateSummaryGraph();
275 },
276
277 refreshShowAsPercents: function()
278 {
279 this._updatePercentButton();
280 this.refreshVisibleData();
281 },
282
283 refreshVisibleData: function()
284 {
285 var child = this.dataGrid.children[0];
286 while (child) {
287 child.refresh();
288 child = child.traverseNextNode(false, null, true);
289 }
290 this._updateSummaryGraph();
291 },
292
293 _changeBase: function() {
294 if (this.baseSnapshot === this.snapshot.list[this.baseSelectElement.sele ctedIndex])
295 return;
296
297 this._resetDataGridList();
298 this.refresh();
299 },
300
301 _createSnapshotDataGridList: function()
302 {
303 if (this._snapshotDataGridList)
304 delete this._snapshotDataGridList;
305
306 this._snapshotDataGridList = new WebInspector.HeapSnapshotDataGridList(t his, this.baseSnapshot.entries, this.snapshot.entries);
307 return this._snapshotDataGridList;
308 },
309
310 _mouseDownInDataGrid: function(event)
311 {
312 if (event.detail < 2)
313 return;
314
315 var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
316 if (!cell || (!cell.hasStyleClass("count-column") && !cell.hasStyleClass ("size-column") && !cell.hasStyleClass("countDelta-column") && !cell.hasStyleCla ss("sizeDelta-column")))
317 return;
318
319 if (cell.hasStyleClass("count-column"))
320 this.showCountAsPercent = !this.showCountAsPercent;
321 else if (cell.hasStyleClass("size-column"))
322 this.showSizeAsPercent = !this.showSizeAsPercent;
323 else if (cell.hasStyleClass("countDelta-column"))
324 this.showCountDeltaAsPercent = !this.showCountDeltaAsPercent;
325 else if (cell.hasStyleClass("sizeDelta-column"))
326 this.showSizeDeltaAsPercent = !this.showSizeDeltaAsPercent;
327
328 this.refreshShowAsPercents();
329
330 event.preventDefault();
331 event.stopPropagation();
332 },
333
334 get _isShowingAsPercent()
335 {
336 return this.showCountAsPercent && this.showSizeAsPercent && this.showCou ntDeltaAsPercent && this.showSizeDeltaAsPercent;
337 },
338
339 _percentClicked: function(event)
340 {
341 var currentState = this._isShowingAsPercent;
342 this.showCountAsPercent = !currentState;
343 this.showSizeAsPercent = !currentState;
344 this.showCountDeltaAsPercent = !currentState;
345 this.showSizeDeltaAsPercent = !currentState;
346 this.refreshShowAsPercents();
347 },
348
349 _resetDataGridList: function()
350 {
351 this.baseSnapshot = this.snapshot.list[this.baseSelectElement.selectedIn dex];
352 var lastComparator = WebInspector.HeapSnapshotDataGridList.propertyCompa rator("objectsSize", false);
353 if (this.snapshotDataGridList) {
354 lastComparator = this.snapshotDataGridList.lastComparator;
355 }
356 this.snapshotDataGridList = this._createSnapshotDataGridList();
357 this.snapshotDataGridList.sort(lastComparator, true);
358 },
359
360 _sortData: function()
361 {
362 var sortAscending = this.dataGrid.sortOrder === "ascending";
363 var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
364 var sortProperty = {
365 "cons": "constructorName",
366 "count": "objectsCount",
367 "size": "objectsSize",
368 "countDelta": this.showCountDeltaAsPercent ? "objectsCountDeltaP ercent" : "objectsCountDelta",
369 "sizeDelta": this.showSizeDeltaAsPercent ? "objectsSizeDeltaPerc ent" : "objectsSizeDelta"
370 }[sortColumnIdentifier];
371
372 this.snapshotDataGridList.sort(WebInspector.HeapSnapshotDataGridList.pro pertyComparator(sortProperty, sortAscending));
373
374 this.refresh();
375 },
376
377 _updateBaseOptions: function()
378 {
379 // We're assuming that snapshots can only be added.
380 if (this.baseSelectElement.length == this.snapshot.list.length)
381 return;
382
383 for (var i = this.baseSelectElement.length, n = this.snapshot.list.lengt h; i < n; ++i) {
384 var baseOption = document.createElement("option");
385 baseOption.label = WebInspector.UIString("Compared to %s", this.snap shot.list[i].title);
386 this.baseSelectElement.appendChild(baseOption);
387 }
388 },
389
390 _updatePercentButton: function()
391 {
392 if (this._isShowingAsPercent) {
393 this.percentButton.title = WebInspector.UIString("Show absolute coun ts and sizes.");
394 this.percentButton.toggled = true;
395 } else {
396 this.percentButton.title = WebInspector.UIString("Show counts and si zes as percentages.");
397 this.percentButton.toggled = false;
398 }
399 },
400
401 _updateSummaryGraph: function()
402 {
403 this.summaryBar.calculator.showAsPercent = this._isShowingAsPercent;
404 this.summaryBar.update(this.snapshot.lowlevels);
405 }
406 };
407
408 WebInspector.HeapSnapshotView.prototype.__proto__ = WebInspector.View.prototype;
409
410 WebInspector.HeapSummaryCalculator = function(total)
411 {
412 this.total = total;
413 }
414
415 WebInspector.HeapSummaryCalculator.prototype = {
416 computeSummaryValues: function(lowLevels)
417 {
418 function highFromLow(type) {
419 if (type == "CODE_TYPE" || type == "SHARED_FUNCTION_INFO_TYPE" || ty pe == "SCRIPT_TYPE") return "code";
420 if (type == "STRING_TYPE" || type == "HEAP_NUMBER_TYPE" || type.matc h(/^JS_/) || type.match(/_ARRAY_TYPE$/)) return "data";
421 return "other";
422 }
423 var highLevels = {data: 0, code: 0, other: 0};
424 for (var item in lowLevels) {
425 var highItem = highFromLow(item);
426 highLevels[highItem] += lowLevels[item].size;
427 }
428 return {categoryValues: highLevels};
429 },
430
431 formatValue: function(value)
432 {
433 if (this.showAsPercent)
434 return WebInspector.UIString("%.2f%%", value / this.total * 100.0);
435 else
436 return Number.bytesToString(value);
437 },
438
439 get showAsPercent()
440 {
441 return this._showAsPercent;
442 },
443
444 set showAsPercent(x)
445 {
446 this._showAsPercent = x;
447 }
448 }
449
450 WebInspector.HeapSnapshotSidebarTreeElement = function(snapshot)
451 {
452 this.snapshot = snapshot;
453 this.snapshot.title = WebInspector.UIString("Snapshot %d", this.snapshot.num ber);
454
455 WebInspector.SidebarTreeElement.call(this, "heap-snapshot-sidebar-tree-item" , "", "", snapshot, false);
456
457 this.refreshTitles();
458 };
459
460 WebInspector.HeapSnapshotSidebarTreeElement.prototype = {
461 onselect: function()
462 {
463 WebInspector.panels.heap.showSnapshot(this.snapshot);
464 },
465
466 get mainTitle()
467 {
468 if (this._mainTitle)
469 return this._mainTitle;
470 return this.snapshot.title;
471 },
472
473 set mainTitle(x)
474 {
475 this._mainTitle = x;
476 this.refreshTitles();
477 },
478
479 get subtitle()
480 {
481 if (this._subTitle)
482 return this._subTitle;
483 return WebInspector.UIString("Used %s of %s (%.0f%%)", Number.bytesToStr ing(this.snapshot.used, null, false), Number.bytesToString(this.snapshot.capacit y, null, false), this.snapshot.used / this.snapshot.capacity * 100.0);
484 },
485
486 set subtitle(x)
487 {
488 this._subTitle = x;
489 this.refreshTitles();
490 }
491 };
492
493 WebInspector.HeapSnapshotSidebarTreeElement.prototype.__proto__ = WebInspector.S idebarTreeElement.prototype;
494
495 WebInspector.HeapSnapshotDataGridNode = function(snapshotView, baseEntry, snapsh otEntry, owningList)
496 {
497 WebInspector.DataGridNode.call(this, null, false);
498
499 this.snapshotView = snapshotView;
500 this.list = owningList;
501
502 if (!snapshotEntry)
503 snapshotEntry = { cons: baseEntry.cons, count: 0, size: 0 };
504 this.constructorName = snapshotEntry.cons;
505 this.objectsCount = snapshotEntry.count;
506 this.objectsSize = snapshotEntry.size;
507
508 if (!baseEntry)
509 baseEntry = { count: 0, size: 0 };
510 this.baseObjectsCount = baseEntry.count;
511 this.objectsCountDelta = this.objectsCount - this.baseObjectsCount;
512 this.baseObjectsSize = baseEntry.size;
513 this.objectsSizeDelta = this.objectsSize - this.baseObjectsSize;
514 };
515
516 WebInspector.HeapSnapshotDataGridNode.prototype = {
517 get data()
518 {
519 var data = {};
520
521 data["cons"] = this.constructorName;
522
523 if (this.snapshotView.showCountAsPercent)
524 data["count"] = WebInspector.UIString("%.2f%%", this.objectsCountPer cent);
525 else
526 data["count"] = this.objectsCount;
527
528 if (this.snapshotView.showSizeAsPercent)
529 data["size"] = WebInspector.UIString("%.2f%%", this.objectsSizePerce nt);
530 else
531 data["size"] = Number.bytesToString(this.objectsSize);
532
533 function signForDelta(delta) {
534 if (delta == 0)
535 return "";
536 if (delta > 0)
537 return "+";
538 else
539 // Math minus sign, same width as plus.
540 return "\u2212";
541 }
542
543 function showDeltaAsPercent(value) {
544 if (value === Number.POSITIVE_INFINITY)
545 return WebInspector.UIString("new");
546 else if (value === Number.NEGATIVE_INFINITY)
547 return WebInspector.UIString("deleted");
548 if (value > 1000.0)
549 return WebInspector.UIString("%s >1000%%", signForDelta(value));
550 return WebInspector.UIString("%s%.2f%%", signForDelta(value), Math.a bs(value));
551 }
552
553 if (this.snapshotView.showCountDeltaAsPercent)
554 data["countDelta"] = showDeltaAsPercent(this.objectsCountDeltaPercen t);
555 else
556 data["countDelta"] = WebInspector.UIString("%s%d", signForDelta(this .objectsCountDelta), Math.abs(this.objectsCountDelta));
557
558 if (this.snapshotView.showSizeDeltaAsPercent)
559 data["sizeDelta"] = showDeltaAsPercent(this.objectsSizeDeltaPercent) ;
560 else
561 data["sizeDelta"] = WebInspector.UIString("%s%s", signForDelta(this. objectsSizeDelta), Number.bytesToString(Math.abs(this.objectsSizeDelta)));
562
563 return data;
564 },
565
566 get objectsCountPercent()
567 {
568 return this.objectsCount / this.list.objectsCount * 100.0;
569 },
570
571 get objectsSizePercent()
572 {
573 return this.objectsSize / this.list.objectsSize * 100.0;
574 },
575
576 get objectsCountDeltaPercent()
577 {
578 if (this.baseObjectsCount > 0) {
579 if (this.objectsCount > 0)
580 return this.objectsCountDelta / this.baseObjectsCount * 100.0;
581 else
582 return Number.NEGATIVE_INFINITY;
583 } else
584 return Number.POSITIVE_INFINITY;
585 },
586
587 get objectsSizeDeltaPercent()
588 {
589 if (this.baseObjectsSize > 0) {
590 if (this.objectsSize > 0)
591 return this.objectsSizeDelta / this.baseObjectsSize * 100.0;
592 else
593 return Number.NEGATIVE_INFINITY;
594 } else
595 return Number.POSITIVE_INFINITY;
596 }
597 };
598
599 WebInspector.HeapSnapshotDataGridNode.prototype.__proto__ = WebInspector.DataGri dNode.prototype;
600
601 WebInspector.HeapSnapshotDataGridList = function(snapshotView, baseEntries, snap shotEntries)
602 {
603 this.list = this;
604 this.snapshotView = snapshotView;
605 this.children = [];
606 this.lastComparator = null;
607 this.populateChildren(baseEntries, snapshotEntries);
608 };
609
610 WebInspector.HeapSnapshotDataGridList.prototype = {
611 appendChild: function(child)
612 {
613 this.insertChild(child, this.children.length);
614 },
615
616 insertChild: function(child, index)
617 {
618 this.children.splice(index, 0, child);
619 },
620
621 removeChildren: function()
622 {
623 this.children = [];
624 },
625
626 populateChildren: function(baseEntries, snapshotEntries)
627 {
628 for (var item in snapshotEntries)
629 this.appendChild(new WebInspector.HeapSnapshotDataGridNode(this.snap shotView, baseEntries[item], snapshotEntries[item], this));
630
631 for (item in baseEntries) {
632 if (!(item in snapshotEntries))
633 this.appendChild(new WebInspector.HeapSnapshotDataGridNode(this. snapshotView, baseEntries[item], null, this));
634 }
635 },
636
637 sort: function(comparator, force) {
638 if (!force && this.lastComparator === comparator)
639 return;
640
641 this.children.sort(comparator);
642 this.lastComparator = comparator;
643 },
644
645 get objectsCount() {
646 if (!this._objectsCount) {
647 this._objectsCount = 0;
648 for (var i = 0, n = this.children.length; i < n; ++i) {
649 this._objectsCount += this.children[i].objectsCount;
650 }
651 }
652 return this._objectsCount;
653 },
654
655 get objectsSize() {
656 if (!this._objectsSize) {
657 this._objectsSize = 0;
658 for (var i = 0, n = this.children.length; i < n; ++i) {
659 this._objectsSize += this.children[i].objectsSize;
660 }
661 }
662 return this._objectsSize;
663 }
664 };
665
666 WebInspector.HeapSnapshotDataGridList.propertyComparators = [{}, {}];
667
668 WebInspector.HeapSnapshotDataGridList.propertyComparator = function(property, is Ascending)
669 {
670 var comparator = this.propertyComparators[(isAscending ? 1 : 0)][property];
671 if (!comparator) {
672 comparator = function(lhs, rhs) {
673 var l = lhs[property], r = rhs[property];
674 var result = l < r ? -1 : (l > r ? 1 : 0);
675 return isAscending ? result : -result;
676 };
677 this.propertyComparators[(isAscending ? 1 : 0)][property] = comparator;
678 }
679 return comparator;
680 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698