2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
33 * @extends {WebInspector.Object}
34 * @implements {WebInspector.TargetManager.Observer}
35 * @param {?WebInspector.Setting} breakpointsSetting
36 * @param {!WebInspector.Workspace} workspace
37 * @param {!WebInspector.NetworkMapping} networkMapping
38 * @param {!WebInspector.TargetManager} targetManager
39 * @param {!WebInspector.DebuggerWorkspaceBinding} debuggerWorkspaceBinding
41 WebInspector
.BreakpointManager = function(breakpointsSetting
, workspace
, networkMapping
, targetManager
, debuggerWorkspaceBinding
)
43 this._storage
= new WebInspector
.BreakpointManager
.Storage(this, breakpointsSetting
);
44 this._workspace
= workspace
;
45 this._networkMapping
= networkMapping
;
46 this._targetManager
= targetManager
;
47 this._debuggerWorkspaceBinding
= debuggerWorkspaceBinding
;
49 this._breakpointsActive
= true;
50 this._breakpointsForUISourceCode
= new Map();
51 this._breakpointsForPrimaryUISourceCode
= new Map();
52 /** @type {!Multimap.<string, !WebInspector.BreakpointManager.Breakpoint>} */
53 this._provisionalBreakpoints
= new Multimap();
55 this._workspace
.addEventListener(WebInspector
.Workspace
.Events
.ProjectRemoved
, this._projectRemoved
, this);
56 this._workspace
.addEventListener(WebInspector
.Workspace
.Events
.UISourceCodeAdded
, this._uiSourceCodeAdded
, this);
57 this._workspace
.addEventListener(WebInspector
.Workspace
.Events
.UISourceCodeRemoved
, this._uiSourceCodeRemoved
, this);
60 WebInspector
.BreakpointManager
.Events
= {
61 BreakpointAdded
: "breakpoint-added",
62 BreakpointRemoved
: "breakpoint-removed",
63 BreakpointsActiveStateChanged
: "BreakpointsActiveStateChanged"
67 * @param {string} sourceFileId
68 * @param {number} lineNumber
69 * @param {number} columnNumber
72 WebInspector
.BreakpointManager
._breakpointStorageId = function(sourceFileId
, lineNumber
, columnNumber
)
76 return sourceFileId
+ ":" + lineNumber
+ ":" + columnNumber
;
79 WebInspector
.BreakpointManager
.prototype = {
81 * @param {!WebInspector.UISourceCode} uiSourceCode
84 _sourceFileId: function(uiSourceCode
)
86 var networkURL
= this._networkMapping
.networkURL(uiSourceCode
)
89 return uiSourceCode
.uri();
94 * @param {!WebInspector.Target} target
96 targetAdded: function(target
)
98 var debuggerModel
= WebInspector
.DebuggerModel
.fromTarget(target
);
99 if (debuggerModel
&& !this._breakpointsActive
)
100 debuggerModel
.setBreakpointsActive(this._breakpointsActive
);
105 * @param {!WebInspector.Target} target
107 targetRemoved: function(target
) { },
110 * @param {string} sourceFileId
111 * @return {!Map.<string, !WebInspector.BreakpointManager.Breakpoint>}
113 _provisionalBreakpointsForSourceFileId: function(sourceFileId
)
115 var result
= new Map();
116 var breakpoints
= this._provisionalBreakpoints
.get(sourceFileId
).valuesArray();
117 for (var i
= 0; i
< breakpoints
.length
; ++i
)
118 result
.set(breakpoints
[i
]._breakpointStorageId(), breakpoints
[i
]);
122 removeProvisionalBreakpointsForTest: function()
124 var breakpoints
= this._provisionalBreakpoints
.valuesArray();
125 for (var i
= 0; i
< breakpoints
.length
; ++i
)
126 breakpoints
[i
].remove();
127 this._provisionalBreakpoints
.clear();
131 * @param {!WebInspector.UISourceCode} uiSourceCode
133 _restoreBreakpoints: function(uiSourceCode
)
135 var sourceFileId
= this._sourceFileId(uiSourceCode
);
139 this._storage
.mute();
140 var breakpointItems
= this._storage
.breakpointItems(this._sourceFileId(uiSourceCode
));
141 var provisionalBreakpoints
= this._provisionalBreakpointsForSourceFileId(sourceFileId
);
142 for (var i
= 0; i
< breakpointItems
.length
; ++i
) {
143 var breakpointItem
= breakpointItems
[i
];
144 var itemStorageId
= WebInspector
.BreakpointManager
._breakpointStorageId(breakpointItem
.sourceFileId
, breakpointItem
.lineNumber
, breakpointItem
.columnNumber
);
145 var provisionalBreakpoint
= provisionalBreakpoints
.get(itemStorageId
);
146 if (provisionalBreakpoint
) {
147 if (!this._breakpointsForPrimaryUISourceCode
.get(uiSourceCode
))
148 this._breakpointsForPrimaryUISourceCode
.set(uiSourceCode
, []);
149 this._breakpointsForPrimaryUISourceCode
.get(uiSourceCode
).push(provisionalBreakpoint
);
150 provisionalBreakpoint
._updateBreakpoint();
152 this._innerSetBreakpoint(uiSourceCode
, breakpointItem
.lineNumber
, breakpointItem
.columnNumber
, breakpointItem
.condition
, breakpointItem
.enabled
);
155 this._provisionalBreakpoints
.removeAll(sourceFileId
);
156 this._storage
.unmute();
160 * @param {!WebInspector.Event} event
162 _uiSourceCodeAdded: function(event
)
164 var uiSourceCode
= /** @type {!WebInspector.UISourceCode} */ (event
.data
);
165 this._restoreBreakpoints(uiSourceCode
);
166 if (uiSourceCode
.contentType() === WebInspector
.resourceTypes
.Script
|| uiSourceCode
.contentType() === WebInspector
.resourceTypes
.Document
)
167 uiSourceCode
.addEventListener(WebInspector
.UISourceCode
.Events
.SourceMappingChanged
, this._uiSourceCodeMappingChanged
, this);
171 * @param {!WebInspector.Event} event
173 _uiSourceCodeRemoved: function(event
)
175 var uiSourceCode
= /** @type {!WebInspector.UISourceCode} */ (event
.data
);
176 this._removeUISourceCode(uiSourceCode
);
180 * @param {!WebInspector.Event} event
182 _uiSourceCodeMappingChanged: function(event
)
184 var uiSourceCode
= /** @type {!WebInspector.UISourceCode} */ (event
.target
);
185 var isIdentity
= /** @type {boolean} */ (event
.data
.isIdentity
);
186 var target
= /** @type {!WebInspector.Target} */ (event
.data
.target
);
189 var breakpoints
= this._breakpointsForPrimaryUISourceCode
.get(uiSourceCode
) || [];
190 for (var i
= 0; i
< breakpoints
.length
; ++i
)
191 breakpoints
[i
]._updateInDebuggerForTarget(target
);
195 * @param {!WebInspector.UISourceCode} uiSourceCode
197 _removeUISourceCode: function(uiSourceCode
)
199 var breakpoints
= this._breakpointsForPrimaryUISourceCode
.get(uiSourceCode
) || [];
200 var sourceFileId
= this._sourceFileId(uiSourceCode
);
201 for (var i
= 0; i
< breakpoints
.length
; ++i
) {
202 breakpoints
[i
]._resetLocations();
203 if (breakpoints
[i
].enabled())
204 this._provisionalBreakpoints
.set(sourceFileId
, breakpoints
[i
]);
206 uiSourceCode
.removeEventListener(WebInspector
.UISourceCode
.Events
.SourceMappingChanged
, this._uiSourceCodeMappingChanged
, this);
207 this._breakpointsForPrimaryUISourceCode
.remove(uiSourceCode
);
211 * @param {!WebInspector.UISourceCode} uiSourceCode
212 * @param {number} lineNumber
213 * @param {number} columnNumber
214 * @param {string} condition
215 * @param {boolean} enabled
216 * @return {!WebInspector.BreakpointManager.Breakpoint}
218 setBreakpoint: function(uiSourceCode
, lineNumber
, columnNumber
, condition
, enabled
)
220 var uiLocation
= new WebInspector
.UILocation(uiSourceCode
, lineNumber
, columnNumber
);
221 var normalizedLocation
= this._debuggerWorkspaceBinding
.normalizeUILocation(uiLocation
);
222 if (normalizedLocation
.id() !== uiLocation
.id()) {
223 WebInspector
.Revealer
.reveal(normalizedLocation
);
224 uiLocation
= normalizedLocation
;
226 this.setBreakpointsActive(true);
227 return this._innerSetBreakpoint(uiLocation
.uiSourceCode
, uiLocation
.lineNumber
, uiLocation
.columnNumber
, condition
, enabled
);
231 * @param {!WebInspector.UISourceCode} uiSourceCode
232 * @param {number} lineNumber
233 * @param {number} columnNumber
234 * @param {string} condition
235 * @param {boolean} enabled
236 * @return {!WebInspector.BreakpointManager.Breakpoint}
238 _innerSetBreakpoint: function(uiSourceCode
, lineNumber
, columnNumber
, condition
, enabled
)
240 var breakpoint
= this.findBreakpoint(uiSourceCode
, lineNumber
, columnNumber
);
242 breakpoint
._updateState(condition
, enabled
);
245 var projectId
= uiSourceCode
.project().id();
246 var path
= uiSourceCode
.path();
247 var sourceFileId
= this._sourceFileId(uiSourceCode
);
248 breakpoint
= new WebInspector
.BreakpointManager
.Breakpoint(this, projectId
, path
, sourceFileId
, lineNumber
, columnNumber
, condition
, enabled
);
249 if (!this._breakpointsForPrimaryUISourceCode
.get(uiSourceCode
))
250 this._breakpointsForPrimaryUISourceCode
.set(uiSourceCode
, []);
251 this._breakpointsForPrimaryUISourceCode
.get(uiSourceCode
).push(breakpoint
);
256 * @param {!WebInspector.UISourceCode} uiSourceCode
257 * @param {number} lineNumber
258 * @param {number} columnNumber
259 * @return {?WebInspector.BreakpointManager.Breakpoint}
261 findBreakpoint: function(uiSourceCode
, lineNumber
, columnNumber
)
263 var breakpoints
= this._breakpointsForUISourceCode
.get(uiSourceCode
);
264 var lineBreakpoints
= breakpoints
? breakpoints
.get(String(lineNumber
)) : null;
265 var columnBreakpoints
= lineBreakpoints
? lineBreakpoints
.get(String(columnNumber
)) : null;
266 return columnBreakpoints
? columnBreakpoints
[0] : null;
270 * @param {!WebInspector.UISourceCode} uiSourceCode
271 * @param {number} lineNumber
272 * @return {?WebInspector.BreakpointManager.Breakpoint}
274 findBreakpointOnLine: function(uiSourceCode
, lineNumber
)
276 var breakpoints
= this._breakpointsForUISourceCode
.get(uiSourceCode
);
277 var lineBreakpoints
= breakpoints
? breakpoints
.get(String(lineNumber
)) : null;
278 return lineBreakpoints
? lineBreakpoints
.valuesArray()[0][0] : null;
282 * @param {!WebInspector.UISourceCode} uiSourceCode
283 * @return {!Array.<!WebInspector.BreakpointManager.Breakpoint>}
285 breakpointsForUISourceCode: function(uiSourceCode
)
288 var uiSourceCodeBreakpoints
= this._breakpointsForUISourceCode
.get(uiSourceCode
);
289 var breakpoints
= uiSourceCodeBreakpoints
? uiSourceCodeBreakpoints
.valuesArray() : [];
290 for (var i
= 0; i
< breakpoints
.length
; ++i
) {
291 var lineBreakpoints
= breakpoints
[i
];
292 var columnBreakpointArrays
= lineBreakpoints
? lineBreakpoints
.valuesArray() : [];
293 result
= result
.concat
.apply(result
, columnBreakpointArrays
);
299 * @return {!Array.<!WebInspector.BreakpointManager.Breakpoint>}
301 allBreakpoints: function()
304 var uiSourceCodes
= this._breakpointsForUISourceCode
.keysArray();
305 for (var i
= 0; i
< uiSourceCodes
.length
; ++i
)
306 result
= result
.concat(this.breakpointsForUISourceCode(uiSourceCodes
[i
]));
311 * @param {!WebInspector.UISourceCode} uiSourceCode
312 * @return {!Array.<!{breakpoint: !WebInspector.BreakpointManager.Breakpoint, uiLocation: !WebInspector.UILocation}>}
314 breakpointLocationsForUISourceCode: function(uiSourceCode
)
316 var uiSourceCodeBreakpoints
= this._breakpointsForUISourceCode
.get(uiSourceCode
);
317 var lineNumbers
= uiSourceCodeBreakpoints
? uiSourceCodeBreakpoints
.keysArray() : [];
319 for (var i
= 0; i
< lineNumbers
.length
; ++i
) {
320 var lineBreakpoints
= uiSourceCodeBreakpoints
.get(lineNumbers
[i
]);
321 var columnNumbers
= lineBreakpoints
.keysArray();
322 for (var j
= 0; j
< columnNumbers
.length
; ++j
) {
323 var columnBreakpoints
= lineBreakpoints
.get(columnNumbers
[j
]);
324 var lineNumber
= parseInt(lineNumbers
[i
], 10);
325 var columnNumber
= parseInt(columnNumbers
[j
], 10);
326 for (var k
= 0; k
< columnBreakpoints
.length
; ++k
) {
327 var breakpoint
= columnBreakpoints
[k
];
328 var uiLocation
= uiSourceCode
.uiLocation(lineNumber
, columnNumber
);
329 result
.push({breakpoint
: breakpoint
, uiLocation
: uiLocation
});
337 * @return {!Array.<!{breakpoint: !WebInspector.BreakpointManager.Breakpoint, uiLocation: !WebInspector.UILocation}>}
339 allBreakpointLocations: function()
342 var uiSourceCodes
= this._breakpointsForUISourceCode
.keysArray();
343 for (var i
= 0; i
< uiSourceCodes
.length
; ++i
)
344 result
= result
.concat(this.breakpointLocationsForUISourceCode(uiSourceCodes
[i
]));
349 * @param {boolean} toggleState
351 toggleAllBreakpoints: function(toggleState
)
353 var breakpoints
= this.allBreakpoints();
354 for (var i
= 0; i
< breakpoints
.length
; ++i
)
355 breakpoints
[i
].setEnabled(toggleState
);
358 removeAllBreakpoints: function()
360 var breakpoints
= this.allBreakpoints();
361 for (var i
= 0; i
< breakpoints
.length
; ++i
)
362 breakpoints
[i
].remove();
365 _projectRemoved: function(event
)
367 var project
= /** @type {!WebInspector.Project} */ (event
.data
);
368 var uiSourceCodes
= project
.uiSourceCodes();
369 for (var i
= 0; i
< uiSourceCodes
.length
; ++i
)
370 this._removeUISourceCode(uiSourceCodes
[i
]);
374 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
375 * @param {boolean} removeFromStorage
377 _removeBreakpoint: function(breakpoint
, removeFromStorage
)
379 var uiSourceCode
= breakpoint
.uiSourceCode();
380 var breakpoints
= uiSourceCode
? this._breakpointsForPrimaryUISourceCode
.get(uiSourceCode
) || [] : [];
381 breakpoints
.remove(breakpoint
);
382 if (removeFromStorage
)
383 this._storage
._removeBreakpoint(breakpoint
);
384 this._provisionalBreakpoints
.remove(breakpoint
._sourceFileId
, breakpoint
);
388 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
389 * @param {!WebInspector.UILocation} uiLocation
391 _uiLocationAdded: function(breakpoint
, uiLocation
)
393 var breakpoints
= this._breakpointsForUISourceCode
.get(uiLocation
.uiSourceCode
);
395 breakpoints
= new Map();
396 this._breakpointsForUISourceCode
.set(uiLocation
.uiSourceCode
, breakpoints
);
398 var lineBreakpoints
= breakpoints
.get(String(uiLocation
.lineNumber
));
399 if (!lineBreakpoints
) {
400 lineBreakpoints
= new Map();
401 breakpoints
.set(String(uiLocation
.lineNumber
), lineBreakpoints
);
403 var columnBreakpoints
= lineBreakpoints
.get(String(uiLocation
.columnNumber
));
404 if (!columnBreakpoints
) {
405 columnBreakpoints
= [];
406 lineBreakpoints
.set(String(uiLocation
.columnNumber
), columnBreakpoints
);
408 columnBreakpoints
.push(breakpoint
);
409 this.dispatchEventToListeners(WebInspector
.BreakpointManager
.Events
.BreakpointAdded
, {breakpoint
: breakpoint
, uiLocation
: uiLocation
});
413 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
414 * @param {!WebInspector.UILocation} uiLocation
416 _uiLocationRemoved: function(breakpoint
, uiLocation
)
418 var breakpoints
= this._breakpointsForUISourceCode
.get(uiLocation
.uiSourceCode
);
422 var lineBreakpoints
= breakpoints
.get(String(uiLocation
.lineNumber
));
423 if (!lineBreakpoints
)
425 var columnBreakpoints
= lineBreakpoints
.get(String(uiLocation
.columnNumber
));
426 if (!columnBreakpoints
)
428 columnBreakpoints
.remove(breakpoint
);
429 if (!columnBreakpoints
.length
)
430 lineBreakpoints
.remove(String(uiLocation
.columnNumber
));
431 if (!lineBreakpoints
.size
)
432 breakpoints
.remove(String(uiLocation
.lineNumber
));
433 if (!breakpoints
.size
)
434 this._breakpointsForUISourceCode
.remove(uiLocation
.uiSourceCode
);
435 this.dispatchEventToListeners(WebInspector
.BreakpointManager
.Events
.BreakpointRemoved
, {breakpoint
: breakpoint
, uiLocation
: uiLocation
});
439 * @param {boolean} active
441 setBreakpointsActive: function(active
)
443 if (this._breakpointsActive
=== active
)
446 this._breakpointsActive
= active
;
447 var debuggerModels
= WebInspector
.DebuggerModel
.instances();
448 for (var i
= 0; i
< debuggerModels
.length
; ++i
)
449 debuggerModels
[i
].setBreakpointsActive(active
);
451 this.dispatchEventToListeners(WebInspector
.BreakpointManager
.Events
.BreakpointsActiveStateChanged
, active
);
457 breakpointsActive: function()
459 return this._breakpointsActive
;
462 __proto__
: WebInspector
.Object
.prototype
467 * @implements {WebInspector.TargetManager.Observer}
468 * @param {!WebInspector.BreakpointManager} breakpointManager
469 * @param {string} projectId
470 * @param {string} path
471 * @param {string} sourceFileId
472 * @param {number} lineNumber
473 * @param {number} columnNumber
474 * @param {string} condition
475 * @param {boolean} enabled
477 WebInspector
.BreakpointManager
.Breakpoint = function(breakpointManager
, projectId
, path
, sourceFileId
, lineNumber
, columnNumber
, condition
, enabled
)
479 this._breakpointManager
= breakpointManager
;
480 this._projectId
= projectId
;
482 this._lineNumber
= lineNumber
;
483 this._columnNumber
= columnNumber
;
484 this._sourceFileId
= sourceFileId
;
486 /** @type {!Object.<string, number>} */
487 this._numberOfDebuggerLocationForUILocation
= {};
489 // Force breakpoint update.
490 /** @type {string} */ this._condition
;
491 /** @type {boolean} */ this._enabled
;
492 /** @type {boolean} */ this._isRemoved
;
493 /** @type {!WebInspector.UILocation|undefined} */ this._fakePrimaryLocation
;
495 this._currentState
= null;
496 /** @type {!Map.<!WebInspector.Target, !WebInspector.BreakpointManager.TargetBreakpoint>}*/
497 this._targetBreakpoints
= new Map();
498 this._updateState(condition
, enabled
);
499 this._breakpointManager
._targetManager
.observeTargets(this);
502 WebInspector
.BreakpointManager
.Breakpoint
.prototype = {
505 * @param {!WebInspector.Target} target
507 targetAdded: function(target
)
509 var debuggerModel
= WebInspector
.DebuggerModel
.fromTarget(target
);
512 var networkMapping
= this._breakpointManager
._networkMapping
;
513 var debuggerWorkspaceBinding
= this._breakpointManager
._debuggerWorkspaceBinding
;
514 this._targetBreakpoints
.set(target
, new WebInspector
.BreakpointManager
.TargetBreakpoint(debuggerModel
, this, networkMapping
, debuggerWorkspaceBinding
));
519 * @param {!WebInspector.Target} target
521 targetRemoved: function(target
)
523 var debuggerModel
= WebInspector
.DebuggerModel
.fromTarget(target
);
526 var targetBreakpoint
= this._targetBreakpoints
.remove(target
);
527 targetBreakpoint
._cleanUpAfterDebuggerIsGone();
528 targetBreakpoint
._removeEventListeners();
534 projectId: function()
536 return this._projectId
;
550 lineNumber: function()
552 return this._lineNumber
;
558 columnNumber: function()
560 return this._columnNumber
;
564 * @return {?WebInspector.UISourceCode}
566 uiSourceCode: function()
568 return this._breakpointManager
._workspace
.uiSourceCode(this._projectId
, this._path
);
572 * @param {?WebInspector.UILocation} oldUILocation
573 * @param {!WebInspector.UILocation} newUILocation
575 _replaceUILocation: function(oldUILocation
, newUILocation
)
580 this._removeUILocation(oldUILocation
, true);
581 this._removeFakeBreakpointAtPrimaryLocation();
583 if (!this._numberOfDebuggerLocationForUILocation
[newUILocation
.id()])
584 this._numberOfDebuggerLocationForUILocation
[newUILocation
.id()] = 0;
586 if (++this._numberOfDebuggerLocationForUILocation
[newUILocation
.id()] === 1)
587 this._breakpointManager
._uiLocationAdded(this, newUILocation
);
591 * @param {?WebInspector.UILocation} uiLocation
592 * @param {boolean=} muteCreationFakeBreakpoint
594 _removeUILocation: function(uiLocation
, muteCreationFakeBreakpoint
)
596 if (!uiLocation
|| --this._numberOfDebuggerLocationForUILocation
[uiLocation
.id()] !== 0)
599 delete this._numberOfDebuggerLocationForUILocation
[uiLocation
.id()];
600 this._breakpointManager
._uiLocationRemoved(this, uiLocation
);
601 if (!muteCreationFakeBreakpoint
)
602 this._fakeBreakpointAtPrimaryLocation();
610 return this._enabled
;
614 * @param {boolean} enabled
616 setEnabled: function(enabled
)
618 this._updateState(this._condition
, enabled
);
624 condition: function()
626 return this._condition
;
630 * @param {string} condition
632 setCondition: function(condition
)
634 this._updateState(condition
, this._enabled
);
638 * @param {string} condition
639 * @param {boolean} enabled
641 _updateState: function(condition
, enabled
)
643 if (this._enabled
=== enabled
&& this._condition
=== condition
)
645 this._enabled
= enabled
;
646 this._condition
= condition
;
647 this._breakpointManager
._storage
._updateBreakpoint(this);
648 this._updateBreakpoint();
651 _updateBreakpoint: function()
653 this._removeFakeBreakpointAtPrimaryLocation();
654 this._fakeBreakpointAtPrimaryLocation();
655 var targetBreakpoints
= this._targetBreakpoints
.valuesArray();
656 for (var i
= 0; i
< targetBreakpoints
.length
; ++i
)
657 targetBreakpoints
[i
]._scheduleUpdateInDebugger();
661 * @param {boolean=} keepInStorage
663 remove: function(keepInStorage
)
666 this._isRemoved
= true;
667 var removeFromStorage
= !keepInStorage
;
668 this._removeFakeBreakpointAtPrimaryLocation();
669 var targetBreakpoints
= this._targetBreakpoints
.valuesArray();
670 for (var i
= 0; i
< targetBreakpoints
.length
; ++i
) {
671 targetBreakpoints
[i
]._scheduleUpdateInDebugger();
672 targetBreakpoints
[i
]._removeEventListeners();
675 this._breakpointManager
._removeBreakpoint(this, removeFromStorage
);
676 this._breakpointManager
._targetManager
.unobserveTargets(this);
680 * @param {!WebInspector.Target} target
682 _updateInDebuggerForTarget: function(target
)
684 this._targetBreakpoints
.get(target
)._scheduleUpdateInDebugger();
690 _breakpointStorageId: function()
692 return WebInspector
.BreakpointManager
._breakpointStorageId(this._sourceFileId
, this._lineNumber
, this._columnNumber
);
695 _fakeBreakpointAtPrimaryLocation: function()
697 if (this._isRemoved
|| !Object
.isEmpty(this._numberOfDebuggerLocationForUILocation
) || this._fakePrimaryLocation
)
700 var uiSourceCode
= this._breakpointManager
._workspace
.uiSourceCode(this._projectId
, this._path
);
704 this._fakePrimaryLocation
= uiSourceCode
.uiLocation(this._lineNumber
, this._columnNumber
);
705 if (this._fakePrimaryLocation
)
706 this._breakpointManager
._uiLocationAdded(this, this._fakePrimaryLocation
);
709 _removeFakeBreakpointAtPrimaryLocation: function()
711 if (this._fakePrimaryLocation
) {
712 this._breakpointManager
._uiLocationRemoved(this, this._fakePrimaryLocation
);
713 delete this._fakePrimaryLocation
;
717 _resetLocations: function()
719 this._removeFakeBreakpointAtPrimaryLocation();
720 var targetBreakpoints
= this._targetBreakpoints
.valuesArray();
721 for (var i
= 0; i
< targetBreakpoints
.length
; ++i
)
722 targetBreakpoints
[i
]._resetLocations();
728 * @extends {WebInspector.SDKObject}
729 * @param {!WebInspector.DebuggerModel} debuggerModel
730 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
731 * @param {!WebInspector.NetworkMapping} networkMapping
732 * @param {!WebInspector.DebuggerWorkspaceBinding} debuggerWorkspaceBinding
734 WebInspector
.BreakpointManager
.TargetBreakpoint = function(debuggerModel
, breakpoint
, networkMapping
, debuggerWorkspaceBinding
)
736 WebInspector
.SDKObject
.call(this, debuggerModel
.target());
737 this._debuggerModel
= debuggerModel
;
738 this._breakpoint
= breakpoint
;
739 this._networkMapping
= networkMapping
;
740 this._debuggerWorkspaceBinding
= debuggerWorkspaceBinding
;
742 /** @type {!Array.<!WebInspector.DebuggerWorkspaceBinding.Location>} */
743 this._liveLocations
= [];
745 /** @type {!Object.<string, !WebInspector.UILocation>} */
746 this._uiLocations
= {};
747 this._debuggerModel
.addEventListener(WebInspector
.DebuggerModel
.Events
.DebuggerWasDisabled
, this._cleanUpAfterDebuggerIsGone
, this);
748 this._debuggerModel
.addEventListener(WebInspector
.DebuggerModel
.Events
.DebuggerWasEnabled
, this._scheduleUpdateInDebugger
, this);
749 this._hasPendingUpdate
= false;
750 this._isUpdating
= false;
751 this._cancelCallback
= false;
752 this._currentState
= null;
753 if (this._debuggerModel
.debuggerEnabled())
754 this._scheduleUpdateInDebugger();
757 WebInspector
.BreakpointManager
.TargetBreakpoint
.prototype = {
759 _resetLocations: function()
761 var uiLocations
= Object
.values(this._uiLocations
);
762 for (var i
= 0; i
< uiLocations
.length
; ++i
)
763 this._breakpoint
._removeUILocation(uiLocations
[i
]);
765 this._uiLocations
= {};
767 for (var i
= 0; i
< this._liveLocations
.length
; ++i
)
768 this._liveLocations
[i
].dispose();
769 this._liveLocations
= [];
772 _scheduleUpdateInDebugger: function()
774 if (this._isUpdating
) {
775 this._hasPendingUpdate
= true;
779 this._isUpdating
= true;
780 this._updateInDebugger(this._didUpdateInDebugger
.bind(this));
783 _didUpdateInDebugger: function()
785 this._isUpdating
= false;
786 if (this._hasPendingUpdate
) {
787 this._hasPendingUpdate
= false;
788 this._scheduleUpdateInDebugger();
795 _scriptDiverged: function()
797 var uiSourceCode
= this._breakpoint
.uiSourceCode();
800 var scriptFile
= this._debuggerWorkspaceBinding
.scriptFile(uiSourceCode
, this.target());
801 return !!scriptFile
&& scriptFile
.hasDivergedFromVM();
806 * @param {function()} callback
808 _updateInDebugger: function(callback
)
810 if (this.target().isDetached()) {
811 this._cleanUpAfterDebuggerIsGone();
816 var uiSourceCode
= this._breakpoint
.uiSourceCode();
817 var lineNumber
= this._breakpoint
._lineNumber
;
818 var columnNumber
= this._breakpoint
._columnNumber
;
819 var condition
= this._breakpoint
.condition();
821 var debuggerLocation
= uiSourceCode
? this._debuggerWorkspaceBinding
.uiLocationToRawLocation(this.target(), uiSourceCode
, lineNumber
, columnNumber
) : null;
823 if (this._breakpoint
._isRemoved
|| !this._breakpoint
.enabled() || this._scriptDiverged())
825 else if (debuggerLocation
) {
826 var script
= debuggerLocation
.script();
827 if (script
.sourceURL
)
828 newState
= new WebInspector
.BreakpointManager
.Breakpoint
.State(script
.sourceURL
, null, debuggerLocation
.lineNumber
, debuggerLocation
.columnNumber
, condition
);
830 newState
= new WebInspector
.BreakpointManager
.Breakpoint
.State(null, debuggerLocation
.scriptId
, debuggerLocation
.lineNumber
, debuggerLocation
.columnNumber
, condition
);
831 } else if (this._breakpoint
._currentState
&& this._breakpoint
._currentState
.url
) {
832 var position
= this._breakpoint
._currentState
;
833 newState
= new WebInspector
.BreakpointManager
.Breakpoint
.State(position
.url
, null, position
.lineNumber
, position
.columnNumber
, condition
);
834 } else if (uiSourceCode
) {
835 var networkURL
= this._networkMapping
.networkURL(uiSourceCode
);
837 newState
= new WebInspector
.BreakpointManager
.Breakpoint
.State(networkURL
, null, lineNumber
, columnNumber
, condition
);
839 if (this._debuggerId
&& WebInspector
.BreakpointManager
.Breakpoint
.State
.equals(newState
, this._currentState
)) {
844 this._breakpoint
._currentState
= newState
;
846 if (this._debuggerId
) {
847 this._resetLocations();
848 this._debuggerModel
.removeBreakpoint(this._debuggerId
, this._didRemoveFromDebugger
.bind(this, callback
));
849 this._scheduleUpdateInDebugger();
850 this._currentState
= null;
859 var updateCallback
= this._didSetBreakpointInDebugger
.bind(this, callback
);
861 this._debuggerModel
.setBreakpointByURL(newState
.url
, newState
.lineNumber
, newState
.columnNumber
, this._breakpoint
.condition(), updateCallback
);
862 else if (newState
.scriptId
)
863 this._debuggerModel
.setBreakpointBySourceId(/** @type {!WebInspector.DebuggerModel.Location} */ (debuggerLocation
), condition
, updateCallback
);
865 this._currentState
= newState
;
869 * @param {function()} callback
870 * @param {?DebuggerAgent.BreakpointId} breakpointId
871 * @param {!Array.<!WebInspector.DebuggerModel.Location>} locations
873 _didSetBreakpointInDebugger: function(callback
, breakpointId
, locations
)
875 if (this._cancelCallback
) {
876 this._cancelCallback
= false;
882 this._breakpoint
.remove(true);
887 this._debuggerId
= breakpointId
;
888 this._debuggerModel
.addBreakpointListener(this._debuggerId
, this._breakpointResolved
, this);
889 for (var i
= 0; i
< locations
.length
; ++i
) {
890 if (!this._addResolvedLocation(locations
[i
]))
897 * @param {function()} callback
899 _didRemoveFromDebugger: function(callback
)
901 if (this._cancelCallback
) {
902 this._cancelCallback
= false;
907 this._resetLocations();
908 this._debuggerModel
.removeBreakpointListener(this._debuggerId
, this._breakpointResolved
, this);
909 delete this._debuggerId
;
914 * @param {!WebInspector.Event} event
916 _breakpointResolved: function(event
)
918 this._addResolvedLocation(/** @type {!WebInspector.DebuggerModel.Location}*/ (event
.data
));
922 * @param {!WebInspector.DebuggerModel.Location} location
923 * @param {!WebInspector.UILocation} uiLocation
925 _locationUpdated: function(location
, uiLocation
)
927 var oldUILocation
= this._uiLocations
[location
.id()] || null;
928 this._uiLocations
[location
.id()] = uiLocation
;
929 this._breakpoint
._replaceUILocation(oldUILocation
, uiLocation
);
933 * @param {!WebInspector.DebuggerModel.Location} location
936 _addResolvedLocation: function(location
)
938 var uiLocation
= this._debuggerWorkspaceBinding
.rawLocationToUILocation(location
);
939 var breakpoint
= this._breakpoint
._breakpointManager
.findBreakpoint(uiLocation
.uiSourceCode
, uiLocation
.lineNumber
, uiLocation
.columnNumber
);
940 if (breakpoint
&& breakpoint
!== this._breakpoint
) {
942 this._breakpoint
.remove();
945 this._liveLocations
.push(this._debuggerWorkspaceBinding
.createLiveLocation(location
, this._locationUpdated
.bind(this, location
)));
949 _cleanUpAfterDebuggerIsGone: function()
951 if (this._isUpdating
)
952 this._cancelCallback
= true;
954 this._resetLocations();
955 this._currentState
= null;
956 if (this._debuggerId
)
957 this._didRemoveFromDebugger(function() {});
960 _removeEventListeners: function()
962 this._debuggerModel
.removeEventListener(WebInspector
.DebuggerModel
.Events
.DebuggerWasDisabled
, this._cleanUpAfterDebuggerIsGone
, this);
963 this._debuggerModel
.removeEventListener(WebInspector
.DebuggerModel
.Events
.DebuggerWasEnabled
, this._scheduleUpdateInDebugger
, this);
966 __proto__
: WebInspector
.SDKObject
.prototype
971 * @param {?string} url
972 * @param {?string} scriptId
973 * @param {number} lineNumber
974 * @param {number} columnNumber
975 * @param {string} condition
977 WebInspector
.BreakpointManager
.Breakpoint
.State = function(url
, scriptId
, lineNumber
, columnNumber
, condition
)
980 this.scriptId
= scriptId
;
981 this.lineNumber
= lineNumber
;
982 this.columnNumber
= columnNumber
;
983 this.condition
= condition
;
987 * @param {?WebInspector.BreakpointManager.Breakpoint.State|undefined} stateA
988 * @param {?WebInspector.BreakpointManager.Breakpoint.State|undefined} stateB
991 WebInspector
.BreakpointManager
.Breakpoint
.State
.equals = function(stateA
, stateB
)
993 if (!stateA
|| !stateB
)
996 if (stateA
.scriptId
|| stateB
.scriptId
)
999 return stateA
.url
=== stateB
.url
&& stateA
.lineNumber
=== stateB
.lineNumber
&& stateA
.columnNumber
=== stateB
.columnNumber
&& stateA
.condition
=== stateB
.condition
;
1004 * @param {!WebInspector.BreakpointManager} breakpointManager
1005 * @param {?WebInspector.Setting} setting
1007 WebInspector
.BreakpointManager
.Storage = function(breakpointManager
, setting
)
1009 this._breakpointManager
= breakpointManager
;
1010 this._setting
= setting
|| WebInspector
.settings
.createLocalSetting("breakpoints", []);
1011 var breakpoints
= this._setting
.get();
1012 /** @type {!Object.<string, !WebInspector.BreakpointManager.Storage.Item>} */
1013 this._breakpoints
= {};
1014 for (var i
= 0; i
< breakpoints
.length
; ++i
) {
1015 var breakpoint
= /** @type {!WebInspector.BreakpointManager.Storage.Item} */ (breakpoints
[i
]);
1016 breakpoint
.columnNumber
= breakpoint
.columnNumber
|| 0;
1017 this._breakpoints
[breakpoint
.sourceFileId
+ ":" + breakpoint
.lineNumber
+ ":" + breakpoint
.columnNumber
] = breakpoint
;
1021 WebInspector
.BreakpointManager
.Storage
.prototype = {
1033 * @param {string} sourceFileId
1034 * @return {!Array.<!WebInspector.BreakpointManager.Storage.Item>}
1036 breakpointItems: function(sourceFileId
)
1039 for (var id
in this._breakpoints
) {
1040 var breakpoint
= this._breakpoints
[id
];
1041 if (breakpoint
.sourceFileId
=== sourceFileId
)
1042 result
.push(breakpoint
);
1048 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
1050 _updateBreakpoint: function(breakpoint
)
1052 if (this._muted
|| !breakpoint
._breakpointStorageId())
1054 this._breakpoints
[breakpoint
._breakpointStorageId()] = new WebInspector
.BreakpointManager
.Storage
.Item(breakpoint
);
1059 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
1061 _removeBreakpoint: function(breakpoint
)
1065 delete this._breakpoints
[breakpoint
._breakpointStorageId()];
1071 var breakpointsArray
= [];
1072 for (var id
in this._breakpoints
)
1073 breakpointsArray
.push(this._breakpoints
[id
]);
1074 this._setting
.set(breakpointsArray
);
1080 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint
1082 WebInspector
.BreakpointManager
.Storage
.Item = function(breakpoint
)
1084 this.sourceFileId
= breakpoint
._sourceFileId
;
1085 this.lineNumber
= breakpoint
.lineNumber();
1086 this.columnNumber
= breakpoint
.columnNumber();
1087 this.condition
= breakpoint
.condition();
1088 this.enabled
= breakpoint
.enabled();
1091 /** @type {!WebInspector.BreakpointManager} */
1092 WebInspector
.breakpointManager
;