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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js

Issue 2491983002: [DevTools] reworked JavaScriptBreakpointsSidebarPane.js (Closed)
Patch Set: addressed offline comments 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
« no previous file with comments | « third_party/WebKit/Source/devtools/front_end/components/breakpointsList.css ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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 * @implements {WebInspector.ContextFlavorListener} 5 * @implements {WebInspector.ContextFlavorListener}
6 * @unrestricted 6 * @unrestricted
7 */ 7 */
8 WebInspector.JavaScriptBreakpointsSidebarPane = class extends WebInspector.VBox { 8 WebInspector.JavaScriptBreakpointsSidebarPane = class extends WebInspector.VBox {
lushnikov 2016/11/12 02:57:06 Use WebInspector.ThrottledWidget!!!
kozy 2016/11/12 03:39:05 Done.
9 constructor() { 9 constructor() {
10 super(); 10 super(true);
11 this.registerRequiredCSS('components/breakpointsList.css'); 11 this.registerRequiredCSS('components/breakpointsList.css');
12 12
13 this._breakpointManager = WebInspector.breakpointManager; 13 this._breakpointManager = WebInspector.breakpointManager;
14 14 this._breakpointManager.addEventListener(
15 this._listElement = createElementWithClass('ol', 'breakpoint-list'); 15 WebInspector.BreakpointManager.Events.BreakpointAdded, this._scheduleUpd ate, this);
16 16 this._breakpointManager.addEventListener(
17 this.emptyElement = this.element.createChild('div', 'gray-info-message'); 17 WebInspector.BreakpointManager.Events.BreakpointRemoved, this._scheduleU pdate, this);
18 this.emptyElement.textContent = WebInspector.UIString('No Breakpoints'); 18 this._breakpointManager.addEventListener(
19 19 WebInspector.BreakpointManager.Events.BreakpointsActiveStateChanged, thi s._scheduleUpdate, this);
20 this._items = new Map(); 20
21 /** @type {?Element} */
22 this._emptyElement = null;
23 /** @type {?Element} */
24 this._listElement = null;
25
26 this._scheduleUpdate();
27 }
28
29 _scheduleUpdate() {
30 if (this._updateScheduled)
31 return;
32 setImmediate(this._update.bind(this));
33 this._updateScheduled = true;
34 }
35
36 _update() {
37 this._updateScheduled = false;
21 38
22 var breakpointLocations = this._breakpointManager.allBreakpointLocations(); 39 var breakpointLocations = this._breakpointManager.allBreakpointLocations();
23 for (var i = 0; i < breakpointLocations.length; ++i) 40 if (!breakpointLocations.length) {
24 this._addBreakpoint(breakpointLocations[i].breakpoint, breakpointLocations [i].uiLocation); 41 if (!this._emptyElement) {
lushnikov 2016/11/12 02:57:07 let's create it right away in the constructor! You
kozy 2016/11/12 03:39:05 Done.
25 42 var emptyElement = this.contentElement.createChild('div', 'gray-info-mes sage');
26 this._breakpointManager.addEventListener( 43 emptyElement.textContent = WebInspector.UIString('No Breakpoints');
27 WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointA dded, this); 44 emptyElement.addEventListener('contextmenu', this._emptyElementContextMe nu.bind(this), true);
lushnikov 2016/11/12 02:57:06 do we need it??
kozy 2016/11/12 03:39:05 Removed.
28 this._breakpointManager.addEventListener( 45 this._emptyElement = emptyElement;
29 WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpoin tRemoved, this); 46 }
30 47 if (this._listElement) {
31 this.emptyElement.addEventListener('contextmenu', this._emptyElementContextM enu.bind(this), true); 48 this.contentElement.removeChild(this._listElement);
32 this._breakpointManager.addEventListener( 49 this._listElement = null;
33 WebInspector.BreakpointManager.Events.BreakpointsActiveStateChanged, thi s._breakpointsActiveStateChanged, this); 50 }
34 this._breakpointsActiveStateChanged(); 51 this.contentElement.appendChild(this._emptyElement);
35 this._update(); 52 return;
36 } 53 }
37 54
55 if (!this._listElement)
56 this._listElement = this.contentElement.createChild('div');
57 if (this._emptyElement) {
58 this.contentElement.removeChild(this._emptyElement);
59 this._emptyElement = null;
60 }
61 this.contentElement.appendChild(this._listElement);
62
63 breakpointLocations.sort((item1, item2) => item1.uiLocation.compareTo(item2. uiLocation));
64
65 /** @type {!Map<string, !Array<!{breakpoint: !WebInspector.BreakpointManager .Breakpoint, uiLocation: !WebInspector.UILocation}>} */
lushnikov 2016/11/12 02:57:06 Multimap!
66 var locationForEntry = new Map();
67 for (var breakpointLocation of breakpointLocations) {
68 var uiLocation = breakpointLocation.uiLocation;
69 var entryDescriptor = uiLocation.uiSourceCode.url() + ':' + uiLocation.lin eNumber;
70 if (!locationForEntry.has(entryDescriptor))
71 locationForEntry.set(entryDescriptor, []);
72 locationForEntry.get(entryDescriptor).push(breakpointLocation);
73 }
74
75 var details = WebInspector.context.flavor(WebInspector.DebuggerPausedDetails );
76 var selectedUILocation = details && details.callFrames.length ?
77 WebInspector.debuggerWorkspaceBinding.rawLocationToUILocation(details.ca llFrames[0].location()) :
78 null;
79
80 var shouldShowView = false;
81 var locationsPerEntry = locationForEntry.valuesArray();
82 for (var i = 0; i < locationsPerEntry.length; ++i) {
83 var locations = locationsPerEntry[i];
84 var entry = this._getOrCreateContainerForEntry(i);
85 this._resetEntry(entry, locations);
86
87 var isSelected = selectedUILocation && locations.some(location => location .uiLocation.id() === selectedUILocation.id());
lushnikov 2016/11/12 02:57:06 if (isSelected) shouldShowView = true;
kozy 2016/11/12 03:39:05 Done.
88 entry.classList.toggle('breakpoint-hit', isSelected);
89 }
90 var entriesToRemove = this._listElement.children.length - locationsPerEntry. length;
91 while (entriesToRemove--)
92 this._listElement.removeChild(this._listElement.lastChild);
93 if (shouldShowView)
94 WebInspector.viewManager.showView('sources.jsBreakpoints');
95 this._listElement.classList.toggle('breakpoints-list-deactivated', !this._br eakpointManager.breakpointsActive());
96 this.didUpdateForTest();
97 }
98
99 /**
100 * @param {number} index
101 * @return {!Element}
102 */
103 _getOrCreateContainerForEntry(index) {
lushnikov 2016/11/12 02:57:06 "I don't need this!" (Alexey)
kozy 2016/11/12 03:39:05 Done.
104 var entries = this._listElement.children;
105 console.assert(index <= entries.length);
106 if (index < entries.length)
107 return entries[index];
108 var entry = createElement('div');
109 this._listElement.appendChild(entry);
110 return entry;
111 }
112
113 _resetEntry(element, locations) {
lushnikov 2016/11/12 02:57:06 jsdoc!!
lushnikov 2016/11/12 02:57:06 element, uiLocation, hasEnabled, hasDisabled, isSe
kozy 2016/11/12 03:39:05 Done.
kozy 2016/11/12 03:39:05 Done.
114 element.removeChildren();
115 element.classList.toggle('breakpoint-entry', true);
116
117 var uiLocation = locations[0].uiLocation;
118 element.addEventListener('contextmenu', this._breakpointContextMenu.bind(thi s, uiLocation), true);
119 element.addEventListener('click', () => WebInspector.Revealer.reveal(uiLocat ion), false);
120
121 var hasEnabled = locations.some(location => location.breakpoint.enabled());
122 var hasDisabled = locations.some(location => !location.breakpoint.enabled()) ;
123
124 var checkboxLabel = createCheckboxLabel(uiLocation.linkText());
125 checkboxLabel.addEventListener('click', this._breakpointCheckboxClicked.bind (this, uiLocation), false);
126 checkboxLabel.checkboxElement.checked = hasEnabled;
127 checkboxLabel.checkboxElement.indeterminate = hasEnabled && hasDisabled;
lushnikov 2016/11/12 02:57:07 hasEnabled && hasDisabled -- crazy!!
kozy 2016/11/12 03:39:05 It's new inline breakpoints world.. :)
128 element.appendChild(checkboxLabel);
129
130 var snippetElement = element.createChild('div', 'source-text monospace');
131 uiLocation.uiSourceCode.requestContent().then(fillSnippetElement.bind(this, snippetElement));
132
133 /**
134 * @param {!Element} snippetElement
135 * @param {?string} content
136 * @this {WebInspector.JavaScriptBreakpointsSidebarPane}
137 */
138 function fillSnippetElement(snippetElement, content) {
139 var lineNumber = uiLocation.lineNumber;
140 var text = new WebInspector.Text(content || '');
141 if (lineNumber < text.lineCount()) {
142 var lineText = text.lineAt(lineNumber);
143 var maxSnippetLength = 200;
144 snippetElement.textContent = lineText.substr(0).trimEnd(maxSnippetLength );
145 }
146 this.didReceiveBreakpointLineForTest(uiLocation.uiSourceCode, lineNumber, 0);
147 }
148 }
149
150 /**
151 * @param {!Event} event
152 */
38 _emptyElementContextMenu(event) { 153 _emptyElementContextMenu(event) {
39 var contextMenu = new WebInspector.ContextMenu(event); 154 var contextMenu = new WebInspector.ContextMenu(event);
40 this._appendBreakpointActiveItem(contextMenu); 155 this._appendBreakpointActiveItem(contextMenu);
41 contextMenu.show(); 156 contextMenu.show();
42 } 157 }
43 158
44 /** 159 /**
45 * @param {!WebInspector.ContextMenu} contextMenu 160 * @param {!WebInspector.ContextMenu} contextMenu
46 */ 161 */
47 _appendBreakpointActiveItem(contextMenu) { 162 _appendBreakpointActiveItem(contextMenu) {
48 var breakpointActive = this._breakpointManager.breakpointsActive(); 163 var breakpointActive = this._breakpointManager.breakpointsActive();
49 var breakpointActiveTitle = breakpointActive ? WebInspector.UIString.capital ize('Deactivate ^breakpoints') : 164 var breakpointActiveTitle = breakpointActive ? WebInspector.UIString('Deacti vate breakpoints') :
50 WebInspector.UIString.capital ize('Activate ^breakpoints'); 165 WebInspector.UIString('Activa te breakpoints');
51 contextMenu.appendItem( 166 contextMenu.appendItem(
52 breakpointActiveTitle, 167 breakpointActiveTitle,
53 this._breakpointManager.setBreakpointsActive.bind(this._breakpointManage r, !breakpointActive)); 168 this._breakpointManager.setBreakpointsActive.bind(this._breakpointManage r, !breakpointActive));
54 } 169 }
55 170
56 /** 171 /**
57 * @param {!WebInspector.Event} event
58 */
59 _breakpointAdded(event) {
60 this._breakpointRemoved(event);
61
62 var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ ( event.data.breakpoint);
63 var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiLocat ion);
64 this._addBreakpoint(breakpoint, uiLocation);
65 }
66
67 /**
68 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
69 * @param {!WebInspector.UILocation} uiLocation 172 * @param {!WebInspector.UILocation} uiLocation
70 */ 173 * @param {!Event} event
71 _addBreakpoint(breakpoint, uiLocation) { 174 */
72 var element = createElementWithClass('li', 'cursor-pointer'); 175 _breakpointCheckboxClicked(uiLocation, event) {
73 element.addEventListener('contextmenu', this._breakpointContextMenu.bind(thi s, breakpoint), true); 176 var breakpoints = this._breakpointManager.findBreakpoints(uiLocation.uiSourc eCode, uiLocation.lineNumber);
74 element.addEventListener('click', this._breakpointClicked.bind(this, uiLocat ion), false); 177 var newState = event.target.checkboxElement.checked;
75 178 for (var breakpoint of breakpoints)
76 var checkboxLabel = createCheckboxLabel(uiLocation.linkText(), breakpoint.en abled()); 179 breakpoint.setEnabled(newState);
77 element.appendChild(checkboxLabel); 180 event.consume();
78 checkboxLabel.addEventListener('click', this._breakpointCheckboxClicked.bind (this, breakpoint), false); 181 }
79 182
80 var snippetElement = element.createChild('div', 'source-text monospace'); 183 /**
81 184 * @param {!WebInspector.UILocation} uiLocation
82 /** 185 * @param {!Event} event
83 * @param {?string} content 186 */
84 * @this {WebInspector.JavaScriptBreakpointsSidebarPane} 187 _breakpointContextMenu(uiLocation, event) {
85 */ 188 var breakpoints = this._breakpointManager.findBreakpoints(uiLocation.uiSourc eCode, uiLocation.lineNumber);
86 function didRequestContent(content) { 189
87 var lineNumber = uiLocation.lineNumber; 190 var contextMenu = new WebInspector.ContextMenu(event);
88 var columnNumber = uiLocation.columnNumber; 191 var removeEntryTitle = breakpoints.length > 1 ? WebInspector.UIString('Remov e all breakpoints in line')
89 var text = new WebInspector.Text(content || ''); 192 : WebInspector.UIString('Remov e breakpoint');
90 if (lineNumber < text.lineCount()) { 193 contextMenu.appendItem(removeEntryTitle, () => breakpoints.map(breakpoint => breakpoint.remove()));
91 var lineText = text.lineAt(lineNumber); 194
92 var maxSnippetLength = 200; 195 contextMenu.appendSeparator();
93 var snippetStartIndex = columnNumber > 100 ? columnNumber : 0; 196 this._appendBreakpointActiveItem(contextMenu);
94 snippetElement.textContent = lineText.substr(snippetStartIndex).trimEnd( maxSnippetLength); 197
95 } 198 contextMenu.appendSeparator();
96 this.didReceiveBreakpointLineForTest(uiLocation.uiSourceCode, lineNumber, columnNumber); 199 if (breakpoints.some(breakpoint => !breakpoint.enabled())) {
97 } 200 var enableTitle = WebInspector.UIString('Enable all breakpoints');
98 201 contextMenu.appendItem(
99 uiLocation.uiSourceCode.requestContent().then(didRequestContent.bind(this)); 202 enableTitle, this._breakpointManager.toggleAllBreakpoints.bind(this._b reakpointManager, true));
100 203 }
101 element._data = uiLocation; 204 if (breakpoints.some(breakpoint => breakpoint.enabled())) {
102 var currentElement = this._listElement.firstChild; 205 var disableTitle = WebInspector.UIString('Disable all breakpoints');
103 while (currentElement) { 206 contextMenu.appendItem(
104 if (currentElement._data && this._compareBreakpoints(currentElement._data, element._data) > 0) 207 disableTitle, this._breakpointManager.toggleAllBreakpoints.bind(this._ breakpointManager, false));
105 break; 208 }
106 currentElement = currentElement.nextSibling; 209 var removeAllTitle = WebInspector.UIString('Remove all breakpoints');
107 } 210 contextMenu.appendItem(
108 this._addListElement(element, currentElement); 211 removeAllTitle, this._breakpointManager.removeAllBreakpoints.bind(this._ breakpointManager));
109 212 contextMenu.show();
110 var breakpointItem = {element: element, checkbox: checkboxLabel.checkboxElem ent}; 213 }
111 this._items.set(breakpoint, breakpointItem); 214
215 /**
216 * @override
217 * @param {?Object} object
218 */
219 flavorChanged(object) {
220 this._scheduleUpdate();
221 }
222
223 didUpdateForTest() {
112 } 224 }
113 225
114 /** 226 /**
115 * @param {!WebInspector.UISourceCode} uiSourceCode 227 * @param {!WebInspector.UISourceCode} uiSourceCode
116 * @param {number} lineNumber 228 * @param {number} lineNumber
117 * @param {number} columnNumber 229 * @param {number} columnNumber
118 */ 230 */
119 didReceiveBreakpointLineForTest(uiSourceCode, lineNumber, columnNumber) { 231 didReceiveBreakpointLineForTest(uiSourceCode, lineNumber, columnNumber) {
120 } 232 }
121
122 /**
123 * @param {!WebInspector.Event} event
124 */
125 _breakpointRemoved(event) {
126 var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint} */ ( event.data.breakpoint);
127 var breakpointItem = this._items.get(breakpoint);
128 if (!breakpointItem)
129 return;
130 this._items.remove(breakpoint);
131 this._removeListElement(breakpointItem.element);
132 }
133
134 /**
135 * @override
136 * @param {?Object} object
137 */
138 flavorChanged(object) {
139 this._update();
140 }
141
142 _update() {
143 var details = WebInspector.context.flavor(WebInspector.DebuggerPausedDetails );
144 var uiLocation = details && details.callFrames.length ?
145 WebInspector.debuggerWorkspaceBinding.rawLocationToUILocation(details.ca llFrames[0].location()) :
146 null;
147 var breakpoint = uiLocation ?
148 this._breakpointManager.findBreakpoint(
149 uiLocation.uiSourceCode, uiLocation.lineNumber, uiLocation.columnNum ber) :
150 null;
151 var breakpointItem = this._items.get(breakpoint);
152 if (!breakpointItem) {
153 if (this._highlightedBreakpointItem) {
154 this._highlightedBreakpointItem.element.classList.remove('breakpoint-hit ');
155 delete this._highlightedBreakpointItem;
156 }
157 return;
158 }
159
160 breakpointItem.element.classList.add('breakpoint-hit');
161 this._highlightedBreakpointItem = breakpointItem;
162 WebInspector.viewManager.showView('sources.jsBreakpoints');
163 }
164
165 _breakpointsActiveStateChanged() {
166 this._listElement.classList.toggle('breakpoints-list-deactivated', !this._br eakpointManager.breakpointsActive());
167 }
168
169 /**
170 * @param {!WebInspector.UILocation} uiLocation
171 */
172 _breakpointClicked(uiLocation) {
173 WebInspector.Revealer.reveal(uiLocation);
174 }
175
176 /**
177 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
178 * @param {!Event} event
179 */
180 _breakpointCheckboxClicked(breakpoint, event) {
181 // Breakpoint element has it's own click handler.
182 event.consume();
183 breakpoint.setEnabled(event.target.checkboxElement.checked);
184 }
185
186 /**
187 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
188 * @param {!Event} event
189 */
190 _breakpointContextMenu(breakpoint, event) {
191 var breakpoints = this._items.valuesArray();
192 var contextMenu = new WebInspector.ContextMenu(event);
193 contextMenu.appendItem(WebInspector.UIString.capitalize('Remove ^breakpoint' ), breakpoint.remove.bind(breakpoint));
194 if (breakpoints.length > 1) {
195 var removeAllTitle = WebInspector.UIString.capitalize('Remove ^all ^breakp oints');
196 contextMenu.appendItem(
197 removeAllTitle, this._breakpointManager.removeAllBreakpoints.bind(this ._breakpointManager));
198 }
199
200 contextMenu.appendSeparator();
201 this._appendBreakpointActiveItem(contextMenu);
202
203 function enabledBreakpointCount(breakpoints) {
204 var count = 0;
205 for (var i = 0; i < breakpoints.length; ++i) {
206 if (breakpoints[i].checkbox.checked)
207 count++;
208 }
209 return count;
210 }
211 if (breakpoints.length > 1) {
212 var enableBreakpointCount = enabledBreakpointCount(breakpoints);
213 var enableTitle = WebInspector.UIString.capitalize('Enable ^all ^breakpoin ts');
214 var disableTitle = WebInspector.UIString.capitalize('Disable ^all ^breakpo ints');
215
216 contextMenu.appendSeparator();
217
218 contextMenu.appendItem(
219 enableTitle, this._breakpointManager.toggleAllBreakpoints.bind(this._b reakpointManager, true),
220 !(enableBreakpointCount !== breakpoints.length));
221 contextMenu.appendItem(
222 disableTitle, this._breakpointManager.toggleAllBreakpoints.bind(this._ breakpointManager, false),
223 !(enableBreakpointCount > 1));
224 }
225
226 contextMenu.show();
227 }
228
229 _addListElement(element, beforeElement) {
230 if (beforeElement)
231 this._listElement.insertBefore(element, beforeElement);
232 else {
233 if (!this._listElement.firstChild) {
234 this.element.removeChild(this.emptyElement);
235 this.element.appendChild(this._listElement);
236 }
237 this._listElement.appendChild(element);
238 }
239 }
240
241 _removeListElement(element) {
242 this._listElement.removeChild(element);
243 if (!this._listElement.firstChild) {
244 this.element.removeChild(this._listElement);
245 this.element.appendChild(this.emptyElement);
246 }
247 }
248
249 _compare(x, y) {
250 if (x !== y)
251 return x < y ? -1 : 1;
252 return 0;
253 }
254
255 _compareBreakpoints(b1, b2) {
256 return this._compare(b1.uiSourceCode.url(), b2.uiSourceCode.url()) || this._ compare(b1.lineNumber, b2.lineNumber);
257 }
258
259 reset() {
260 this._listElement.removeChildren();
261 if (this._listElement.parentElement) {
262 this.element.removeChild(this._listElement);
263 this.element.appendChild(this.emptyElement);
264 }
265 this._items.clear();
266 }
267 }; 233 };
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/devtools/front_end/components/breakpointsList.css ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698