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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js

Issue 2623743002: DevTools: extract modules (non-extensions) (Closed)
Patch Set: rebaseline Created 3 years, 11 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 /** 4 /**
5 * @unrestricted 5 * @unrestricted
6 */ 6 */
7 Timeline.TimelineTreeView = class extends UI.VBox { 7 Timeline.TimelineTreeView = class extends UI.VBox {
8 constructor() { 8 constructor() {
9 super(); 9 super();
10 this.element.classList.add('timeline-tree-view'); 10 this.element.classList.add('timeline-tree-view');
(...skipping 14 matching lines...) Expand all
25 /** 25 /**
26 * @param {!TimelineModel.TimelineModel} model 26 * @param {!TimelineModel.TimelineModel} model
27 * @param {!Array<!TimelineModel.TimelineModel.Filter>} filters 27 * @param {!Array<!TimelineModel.TimelineModel.Filter>} filters
28 */ 28 */
29 _init(model, filters) { 29 _init(model, filters) {
30 this._model = model; 30 this._model = model;
31 this._linkifier = new Components.Linkifier(); 31 this._linkifier = new Components.Linkifier();
32 32
33 this._filters = filters.slice(); 33 this._filters = filters.slice();
34 34
35 var columns = /** @type {!Array<!UI.DataGrid.ColumnDescriptor>} */ ([]); 35 var columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([] );
36 this._populateColumns(columns); 36 this._populateColumns(columns);
37 37
38 var mainView = new UI.VBox(); 38 var mainView = new UI.VBox();
39 this._populateToolbar(mainView.element); 39 this._populateToolbar(mainView.element);
40 this._dataGrid = new UI.SortableDataGrid(columns); 40 this._dataGrid = new DataGrid.SortableDataGrid(columns);
41 this._dataGrid.addEventListener(UI.DataGrid.Events.SortingChanged, this._sor tingChanged, this); 41 this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, thi s._sortingChanged, this);
42 this._dataGrid.element.addEventListener('mousemove', this._onMouseMove.bind( this), true); 42 this._dataGrid.element.addEventListener('mousemove', this._onMouseMove.bind( this), true);
43 this._dataGrid.setResizeMethod(UI.DataGrid.ResizeMethod.Last); 43 this._dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.Last);
44 this._dataGrid.setRowContextMenuCallback(this._onContextMenu.bind(this)); 44 this._dataGrid.setRowContextMenuCallback(this._onContextMenu.bind(this));
45 this._dataGrid.asWidget().show(mainView.element); 45 this._dataGrid.asWidget().show(mainView.element);
46 46
47 this._splitWidget = new UI.SplitWidget(true, true, 'timelineTreeViewDetailsS plitWidget'); 47 this._splitWidget = new UI.SplitWidget(true, true, 'timelineTreeViewDetailsS plitWidget');
48 this._splitWidget.show(this.element); 48 this._splitWidget.show(this.element);
49 this._splitWidget.setMainWidget(mainView); 49 this._splitWidget.setMainWidget(mainView);
50 50
51 this._detailsView = new UI.VBox(); 51 this._detailsView = new UI.VBox();
52 this._detailsView.element.classList.add('timeline-details-view', 'timeline-d etails-view-body'); 52 this._detailsView.element.classList.add('timeline-details-view', 'timeline-d etails-view-body');
53 this._splitWidget.setSidebarWidget(this._detailsView); 53 this._splitWidget.setSidebarWidget(this._detailsView);
54 this._dataGrid.addEventListener(UI.DataGrid.Events.SelectedNode, this._updat eDetailsForSelection, this); 54 this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SelectedNode, this. _updateDetailsForSelection, this);
55 55
56 /** @type {?TimelineModel.TimelineProfileTree.Node|undefined} */ 56 /** @type {?TimelineModel.TimelineProfileTree.Node|undefined} */
57 this._lastSelectedNode; 57 this._lastSelectedNode;
58 } 58 }
59 59
60 /** 60 /**
61 * @param {!Timeline.TimelineSelection} selection 61 * @param {!Timeline.TimelineSelection} selection
62 */ 62 */
63 updateContents(selection) { 63 updateContents(selection) {
64 this.setRange(selection.startTime(), selection.endTime()); 64 this.setRange(selection.startTime(), selection.endTime());
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 /** 165 /**
166 * @param {function(!SDK.TracingModel.Event):(string|symbol)=} eventIdCallback 166 * @param {function(!SDK.TracingModel.Event):(string|symbol)=} eventIdCallback
167 * @return {!TimelineModel.TimelineProfileTree.Node} 167 * @return {!TimelineModel.TimelineProfileTree.Node}
168 */ 168 */
169 _buildTopDownTree(eventIdCallback) { 169 _buildTopDownTree(eventIdCallback) {
170 return TimelineModel.TimelineProfileTree.buildTopDown( 170 return TimelineModel.TimelineProfileTree.buildTopDown(
171 this._model.mainThreadEvents(), this._filters, this._startTime, this._en dTime, eventIdCallback); 171 this._model.mainThreadEvents(), this._filters, this._startTime, this._en dTime, eventIdCallback);
172 } 172 }
173 173
174 /** 174 /**
175 * @param {!Array<!UI.DataGrid.ColumnDescriptor>} columns 175 * @param {!Array<!DataGrid.DataGrid.ColumnDescriptor>} columns
176 */ 176 */
177 _populateColumns(columns) { 177 _populateColumns(columns) {
178 columns.push({id: 'self', title: Common.UIString('Self Time'), width: '110px ', fixedWidth: true, sortable: true}); 178 columns.push({id: 'self', title: Common.UIString('Self Time'), width: '110px ', fixedWidth: true, sortable: true});
179 columns.push({id: 'total', title: Common.UIString('Total Time'), width: '110 px', fixedWidth: true, sortable: true}); 179 columns.push({id: 'total', title: Common.UIString('Total Time'), width: '110 px', fixedWidth: true, sortable: true});
180 columns.push({id: 'activity', title: Common.UIString('Activity'), disclosure : true, sortable: true}); 180 columns.push({id: 'activity', title: Common.UIString('Activity'), disclosure : true, sortable: true});
181 } 181 }
182 182
183 _sortingChanged() { 183 _sortingChanged() {
184 var columnId = this._dataGrid.sortColumnId(); 184 var columnId = this._dataGrid.sortColumnId();
185 if (!columnId) 185 if (!columnId)
(...skipping 13 matching lines...) Expand all
199 sortFunction = compareName; 199 sortFunction = compareName;
200 break; 200 break;
201 default: 201 default:
202 console.assert(false, 'Unknown sort field: ' + columnId); 202 console.assert(false, 'Unknown sort field: ' + columnId);
203 return; 203 return;
204 } 204 }
205 this._dataGrid.sortNodes(sortFunction, !this._dataGrid.isSortOrderAscending( )); 205 this._dataGrid.sortNodes(sortFunction, !this._dataGrid.isSortOrderAscending( ));
206 206
207 /** 207 /**
208 * @param {string} field 208 * @param {string} field
209 * @param {!UI.DataGridNode} a 209 * @param {!DataGrid.DataGridNode} a
210 * @param {!UI.DataGridNode} b 210 * @param {!DataGrid.DataGridNode} b
211 * @return {number} 211 * @return {number}
212 */ 212 */
213 function compareNumericField(field, a, b) { 213 function compareNumericField(field, a, b) {
214 var nodeA = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (a); 214 var nodeA = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (a);
215 var nodeB = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (b); 215 var nodeB = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (b);
216 return nodeA._profileNode[field] - nodeB._profileNode[field]; 216 return nodeA._profileNode[field] - nodeB._profileNode[field];
217 } 217 }
218 218
219 /** 219 /**
220 * @param {!UI.DataGridNode} a 220 * @param {!DataGrid.DataGridNode} a
221 * @param {!UI.DataGridNode} b 221 * @param {!DataGrid.DataGridNode} b
222 * @return {number} 222 * @return {number}
223 */ 223 */
224 function compareStartTime(a, b) { 224 function compareStartTime(a, b) {
225 var nodeA = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (a); 225 var nodeA = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (a);
226 var nodeB = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (b); 226 var nodeB = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (b);
227 return nodeA._profileNode.event.startTime - nodeB._profileNode.event.start Time; 227 return nodeA._profileNode.event.startTime - nodeB._profileNode.event.start Time;
228 } 228 }
229 229
230 /** 230 /**
231 * @param {!UI.DataGridNode} a 231 * @param {!DataGrid.DataGridNode} a
232 * @param {!UI.DataGridNode} b 232 * @param {!DataGrid.DataGridNode} b
233 * @return {number} 233 * @return {number}
234 */ 234 */
235 function compareName(a, b) { 235 function compareName(a, b) {
236 var nodeA = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (a); 236 var nodeA = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (a);
237 var nodeB = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (b); 237 var nodeB = /** @type {!Timeline.TimelineTreeView.TreeGridNode} */ (b);
238 var nameA = Timeline.TimelineTreeView.eventNameForSorting(nodeA._profileNo de.event); 238 var nameA = Timeline.TimelineTreeView.eventNameForSorting(nodeA._profileNo de.event);
239 var nameB = Timeline.TimelineTreeView.eventNameForSorting(nodeB._profileNo de.event); 239 var nameB = Timeline.TimelineTreeView.eventNameForSorting(nodeB._profileNo de.event);
240 return nameA.localeCompare(nameB); 240 return nameA.localeCompare(nameB);
241 } 241 }
242 } 242 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 null; 274 null;
275 var profileNode = gridNode && gridNode._profileNode; 275 var profileNode = gridNode && gridNode._profileNode;
276 if (profileNode === this._lastHoveredProfileNode) 276 if (profileNode === this._lastHoveredProfileNode)
277 return; 277 return;
278 this._lastHoveredProfileNode = profileNode; 278 this._lastHoveredProfileNode = profileNode;
279 this._onHover(profileNode); 279 this._onHover(profileNode);
280 } 280 }
281 281
282 /** 282 /**
283 * @param {!UI.ContextMenu} contextMenu 283 * @param {!UI.ContextMenu} contextMenu
284 * @param {!UI.DataGridNode} gridNode 284 * @param {!DataGrid.DataGridNode} gridNode
285 */ 285 */
286 _onContextMenu(contextMenu, gridNode) { 286 _onContextMenu(contextMenu, gridNode) {
287 var profileNode = gridNode._profileNode; 287 var profileNode = gridNode._profileNode;
288 if (!profileNode) 288 if (!profileNode)
289 return; 289 return;
290 this._appendContextMenuItems(contextMenu, profileNode); 290 this._appendContextMenuItems(contextMenu, profileNode);
291 } 291 }
292 292
293 /** 293 /**
294 * @param {!TimelineModel.TimelineProfileTree.Node} treeNode 294 * @param {!TimelineModel.TimelineProfileTree.Node} treeNode
295 * @return {?Timeline.TimelineTreeView.GridNode} 295 * @return {?Timeline.TimelineTreeView.GridNode}
296 */ 296 */
297 _dataGridNodeForTreeNode(treeNode) { 297 _dataGridNodeForTreeNode(treeNode) {
298 return treeNode[Timeline.TimelineTreeView.TreeGridNode._gridNodeSymbol] || n ull; 298 return treeNode[Timeline.TimelineTreeView.TreeGridNode._gridNodeSymbol] || n ull;
299 } 299 }
300 }; 300 };
301 301
302 302
303 /** 303 /**
304 * @unrestricted 304 * @unrestricted
305 */ 305 */
306 Timeline.TimelineTreeView.GridNode = class extends UI.SortableDataGridNode { 306 Timeline.TimelineTreeView.GridNode = class extends DataGrid.SortableDataGridNode {
307 /** 307 /**
308 * @param {!TimelineModel.TimelineProfileTree.Node} profileNode 308 * @param {!TimelineModel.TimelineProfileTree.Node} profileNode
309 * @param {number} grandTotalTime 309 * @param {number} grandTotalTime
310 * @param {number} maxSelfTime 310 * @param {number} maxSelfTime
311 * @param {number} maxTotalTime 311 * @param {number} maxTotalTime
312 * @param {!Timeline.TimelineTreeView} treeView 312 * @param {!Timeline.TimelineTreeView} treeView
313 */ 313 */
314 constructor(profileNode, grandTotalTime, maxSelfTime, maxTotalTime, treeView) { 314 constructor(profileNode, grandTotalTime, maxSelfTime, maxTotalTime, treeView) {
315 super(null, false); 315 super(null, false);
316 316
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 /** 724 /**
725 * @unrestricted 725 * @unrestricted
726 */ 726 */
727 Timeline.CallTreeTimelineTreeView = class extends Timeline.AggregatedTimelineTre eView { 727 Timeline.CallTreeTimelineTreeView = class extends Timeline.AggregatedTimelineTre eView {
728 /** 728 /**
729 * @param {!TimelineModel.TimelineModel} model 729 * @param {!TimelineModel.TimelineModel} model
730 * @param {!Array<!TimelineModel.TimelineModel.Filter>} filters 730 * @param {!Array<!TimelineModel.TimelineModel.Filter>} filters
731 */ 731 */
732 constructor(model, filters) { 732 constructor(model, filters) {
733 super(model, filters); 733 super(model, filters);
734 this._dataGrid.markColumnAsSortedBy('total', UI.DataGrid.Order.Descending); 734 this._dataGrid.markColumnAsSortedBy('total', DataGrid.DataGrid.Order.Descend ing);
735 } 735 }
736 736
737 /** 737 /**
738 * @override 738 * @override
739 * @return {!TimelineModel.TimelineProfileTree.Node} 739 * @return {!TimelineModel.TimelineProfileTree.Node}
740 */ 740 */
741 _buildTree() { 741 _buildTree() {
742 var grouping = this._groupBySetting.get(); 742 var grouping = this._groupBySetting.get();
743 var topDown = this._buildTopDownTree(this._groupingFunction(grouping)); 743 var topDown = this._buildTopDownTree(this._groupingFunction(grouping));
744 if (grouping === Timeline.AggregatedTimelineTreeView.GroupBy.None) 744 if (grouping === Timeline.AggregatedTimelineTreeView.GroupBy.None)
745 return topDown; 745 return topDown;
746 return new TimelineModel.TimelineAggregator().performGrouping(topDown); 746 return new TimelineModel.TimelineAggregator().performGrouping(topDown);
747 } 747 }
748 }; 748 };
749 749
750 /** 750 /**
751 * @unrestricted 751 * @unrestricted
752 */ 752 */
753 Timeline.BottomUpTimelineTreeView = class extends Timeline.AggregatedTimelineTre eView { 753 Timeline.BottomUpTimelineTreeView = class extends Timeline.AggregatedTimelineTre eView {
754 /** 754 /**
755 * @param {!TimelineModel.TimelineModel} model 755 * @param {!TimelineModel.TimelineModel} model
756 * @param {!Array<!TimelineModel.TimelineModel.Filter>} filters 756 * @param {!Array<!TimelineModel.TimelineModel.Filter>} filters
757 */ 757 */
758 constructor(model, filters) { 758 constructor(model, filters) {
759 super(model, filters); 759 super(model, filters);
760 this._dataGrid.markColumnAsSortedBy('self', UI.DataGrid.Order.Descending); 760 this._dataGrid.markColumnAsSortedBy('self', DataGrid.DataGrid.Order.Descendi ng);
761 } 761 }
762 762
763 /** 763 /**
764 * @override 764 * @override
765 * @return {!TimelineModel.TimelineProfileTree.Node} 765 * @return {!TimelineModel.TimelineProfileTree.Node}
766 */ 766 */
767 _buildTree() { 767 _buildTree() {
768 var topDown = this._buildTopDownTree(this._groupingFunction(this._groupBySet ting.get())); 768 var topDown = this._buildTopDownTree(this._groupingFunction(this._groupBySet ting.get()));
769 return TimelineModel.TimelineProfileTree.buildBottomUp(topDown); 769 return TimelineModel.TimelineProfileTree.buildBottomUp(topDown);
770 } 770 }
771 }; 771 };
772 772
773 /** 773 /**
774 * @unrestricted 774 * @unrestricted
775 */ 775 */
776 Timeline.EventsTimelineTreeView = class extends Timeline.TimelineTreeView { 776 Timeline.EventsTimelineTreeView = class extends Timeline.TimelineTreeView {
777 /** 777 /**
778 * @param {!TimelineModel.TimelineModel} model 778 * @param {!TimelineModel.TimelineModel} model
779 * @param {!Array<!TimelineModel.TimelineModel.Filter>} filters 779 * @param {!Array<!TimelineModel.TimelineModel.Filter>} filters
780 * @param {!Timeline.TimelineModeViewDelegate} delegate 780 * @param {!Timeline.TimelineModeViewDelegate} delegate
781 */ 781 */
782 constructor(model, filters, delegate) { 782 constructor(model, filters, delegate) {
783 super(); 783 super();
784 this._filtersControl = new Timeline.TimelineFilters(); 784 this._filtersControl = new Timeline.TimelineFilters();
785 this._filtersControl.addEventListener(Timeline.TimelineFilters.Events.Filter Changed, this._onFilterChanged, this); 785 this._filtersControl.addEventListener(Timeline.TimelineFilters.Events.Filter Changed, this._onFilterChanged, this);
786 this._init(model, filters); 786 this._init(model, filters);
787 this._delegate = delegate; 787 this._delegate = delegate;
788 this._filters.push.apply(this._filters, this._filtersControl.filters()); 788 this._filters.push.apply(this._filters, this._filtersControl.filters());
789 this._dataGrid.markColumnAsSortedBy('startTime', UI.DataGrid.Order.Ascending ); 789 this._dataGrid.markColumnAsSortedBy('startTime', DataGrid.DataGrid.Order.Asc ending);
790 } 790 }
791 791
792 /** 792 /**
793 * @override 793 * @override
794 * @param {!Timeline.TimelineSelection} selection 794 * @param {!Timeline.TimelineSelection} selection
795 */ 795 */
796 updateContents(selection) { 796 updateContents(selection) {
797 super.updateContents(selection); 797 super.updateContents(selection);
798 if (selection.type() === Timeline.TimelineSelection.Type.TraceEvent) { 798 if (selection.type() === Timeline.TimelineSelection.Type.TraceEvent) {
799 var event = /** @type {!SDK.TracingModel.Event} */ (selection.object()); 799 var event = /** @type {!SDK.TracingModel.Event} */ (selection.object());
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 var node = this._findNodeWithEvent(event); 847 var node = this._findNodeWithEvent(event);
848 if (!node) 848 if (!node)
849 return; 849 return;
850 this.selectProfileNode(node, false); 850 this.selectProfileNode(node, false);
851 if (expand) 851 if (expand)
852 this._dataGridNodeForTreeNode(node).expand(); 852 this._dataGridNodeForTreeNode(node).expand();
853 } 853 }
854 854
855 /** 855 /**
856 * @override 856 * @override
857 * @param {!Array<!UI.DataGrid.ColumnDescriptor>} columns 857 * @param {!Array<!DataGrid.DataGrid.ColumnDescriptor>} columns
858 */ 858 */
859 _populateColumns(columns) { 859 _populateColumns(columns) {
860 columns.push( 860 columns.push(
861 {id: 'startTime', title: Common.UIString('Start Time'), width: '110px', fixedWidth: true, sortable: true}); 861 {id: 'startTime', title: Common.UIString('Start Time'), width: '110px', fixedWidth: true, sortable: true});
862 super._populateColumns(columns); 862 super._populateColumns(columns);
863 } 863 }
864 864
865 /** 865 /**
866 * @override 866 * @override
867 * @param {!Element} parent 867 * @param {!Element} parent
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 905
906 /** 906 /**
907 * @unrestricted 907 * @unrestricted
908 */ 908 */
909 Timeline.TimelineStackView = class extends UI.VBox { 909 Timeline.TimelineStackView = class extends UI.VBox {
910 constructor(treeView) { 910 constructor(treeView) {
911 super(); 911 super();
912 var header = this.element.createChild('div', 'timeline-stack-view-header'); 912 var header = this.element.createChild('div', 'timeline-stack-view-header');
913 header.textContent = Common.UIString('Heaviest stack'); 913 header.textContent = Common.UIString('Heaviest stack');
914 this._treeView = treeView; 914 this._treeView = treeView;
915 var columns = /** @type {!Array<!UI.DataGrid.ColumnDescriptor>} */ ([ 915 var columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
916 {id: 'total', title: Common.UIString('Total Time'), fixedWidth: true, widt h: '110px'}, 916 {id: 'total', title: Common.UIString('Total Time'), fixedWidth: true, widt h: '110px'},
917 {id: 'activity', title: Common.UIString('Activity')} 917 {id: 'activity', title: Common.UIString('Activity')}
918 ]); 918 ]);
919 this._dataGrid = new UI.ViewportDataGrid(columns); 919 this._dataGrid = new DataGrid.ViewportDataGrid(columns);
920 this._dataGrid.setResizeMethod(UI.DataGrid.ResizeMethod.Last); 920 this._dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.Last);
921 this._dataGrid.addEventListener(UI.DataGrid.Events.SelectedNode, this._onSel ectionChanged, this); 921 this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SelectedNode, this. _onSelectionChanged, this);
922 this._dataGrid.asWidget().show(this.element); 922 this._dataGrid.asWidget().show(this.element);
923 } 923 }
924 924
925 /** 925 /**
926 * @param {!Array<!TimelineModel.TimelineProfileTree.Node>} stack 926 * @param {!Array<!TimelineModel.TimelineProfileTree.Node>} stack
927 * @param {!TimelineModel.TimelineProfileTree.Node} selectedNode 927 * @param {!TimelineModel.TimelineProfileTree.Node} selectedNode
928 */ 928 */
929 setStack(stack, selectedNode) { 929 setStack(stack, selectedNode) {
930 var rootNode = this._dataGrid.rootNode(); 930 var rootNode = this._dataGrid.rootNode();
931 rootNode.removeChildren(); 931 rootNode.removeChildren();
(...skipping 18 matching lines...) Expand all
950 950
951 _onSelectionChanged() { 951 _onSelectionChanged() {
952 this.dispatchEventToListeners(Timeline.TimelineStackView.Events.SelectionCha nged); 952 this.dispatchEventToListeners(Timeline.TimelineStackView.Events.SelectionCha nged);
953 } 953 }
954 }; 954 };
955 955
956 /** @enum {symbol} */ 956 /** @enum {symbol} */
957 Timeline.TimelineStackView.Events = { 957 Timeline.TimelineStackView.Events = {
958 SelectionChanged: Symbol('SelectionChanged') 958 SelectionChanged: Symbol('SelectionChanged')
959 }; 959 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698