BreakpointManager.js [plain text]
WebInspector.BreakpointManager = function(breakpointStorage, debuggerModel, sourceMapping)
{
this._storage = new WebInspector.BreakpointManager.Storage(this, breakpointStorage);
this._debuggerModel = debuggerModel;
this._sourceMapping = sourceMapping;
this._breakpoints = [];
this._breakpointForDebuggerId = {};
this._breakpointForUILocation = {};
this._uiSourceCodeIds = {};
this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
}
WebInspector.BreakpointManager.Events = {
BreakpointAdded: "breakpoint-added",
BreakpointRemoved: "breakpoint-removed"
}
WebInspector.BreakpointManager.prototype = {
restoreBreakpoints: function(uiSourceCode)
{
if (!uiSourceCode.id || this._uiSourceCodeIds[uiSourceCode.id])
return;
this._uiSourceCodeIds[uiSourceCode.id] = true;
for (var debuggerId in this._breakpointForDebuggerId) {
var breakpoint = this._breakpointForDebuggerId[debuggerId];
if (breakpoint._primaryUILocation.uiSourceCode.id !== uiSourceCode.id)
continue;
this._debuggerModel.removeBreakpoint(debuggerId);
delete this._breakpointForDebuggerId[debuggerId];
}
this._storage.restoreBreakpoints(uiSourceCode);
},
setBreakpoint: function(uiSourceCode, lineNumber, condition, enabled, doNotActivateBreakpoints)
{
if (!doNotActivateBreakpoints)
this._debuggerModel.setBreakpointsActive(true);
var breakpoint = this.findBreakpoint(uiSourceCode, lineNumber);
if (breakpoint) {
breakpoint._updateBreakpoint(condition, enabled);
return breakpoint;
}
breakpoint = new WebInspector.BreakpointManager.Breakpoint(this, uiSourceCode, lineNumber, condition, enabled);
this._breakpoints.push(breakpoint);
return breakpoint;
},
findBreakpoint: function(uiSourceCode, lineNumber)
{
return this._breakpointForUILocation[uiSourceCode.id + ":" + lineNumber];
},
breakpointLocationsForUISourceCode: function(uiSourceCode)
{
var result = [];
for (var i = 0; i < this._breakpoints.length; ++i) {
var breakpoint = this._breakpoints[i];
var uiLocations = breakpoint._uiLocations.values();
for (var j = 0; j < uiLocations.length; ++j) {
var uiLocation = uiLocations[j];
if (uiLocation.uiSourceCode === uiSourceCode)
result.push({breakpoint: breakpoint, uiLocation: uiLocation});
}
}
return result;
},
removeAllBreakpoints: function()
{
var breakpoints = this._breakpoints.slice();
for (var i = 0; i < breakpoints.length; ++i)
breakpoints[i].remove();
},
reset: function()
{
this._storage._muted = true;
this.removeAllBreakpoints();
delete this._storage._muted;
for (var debuggerId in this._breakpointForDebuggerId)
this._debuggerModel.removeBreakpoint(debuggerId);
this._breakpointForDebuggerId = {};
this._uiSourceCodeIds = {};
},
_debuggerReset: function()
{
var breakpoints = this._breakpoints.slice();
for (var i = 0; i < breakpoints.length; ++i)
breakpoints[i]._resetLocations();
this._breakpoints = [];
this._breakpointForUILocation = {};
this._uiSourceCodeIds = {};
},
_breakpointResolved: function(event)
{
var breakpointId = event.data.breakpointId;
var location = event.data.location;
var breakpoint = this._breakpointForDebuggerId[breakpointId];
if (!breakpoint) {
return;
}
breakpoint._addResolvedLocation(location);
},
_removeBreakpoint: function(breakpoint, removeFromStorage)
{
console.assert(!breakpoint._debuggerId)
this._breakpoints.remove(breakpoint);
if (removeFromStorage)
this._storage._removeBreakpoint(breakpoint);
},
_uiLocationAdded: function(breakpoint, uiLocation)
{
this._breakpointForUILocation[uiLocation.uiSourceCode.id + ":" + uiLocation.lineNumber] = breakpoint;
this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.BreakpointAdded, {breakpoint: breakpoint, uiLocation: uiLocation});
},
_uiLocationRemoved: function(breakpoint, uiLocation)
{
delete this._breakpointForUILocation[uiLocation.uiSourceCode.id + ":" + uiLocation.lineNumber];
this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.BreakpointRemoved, {breakpoint: breakpoint, uiLocation: uiLocation});
}
}
WebInspector.BreakpointManager.prototype.__proto__ = WebInspector.Object.prototype;
WebInspector.BreakpointManager.Breakpoint = function(breakpointManager, uiSourceCode, lineNumber, condition, enabled)
{
this._breakpointManager = breakpointManager;
this._primaryUILocation = new WebInspector.UILocation(uiSourceCode, lineNumber, 0);
this._liveLocations = [];
this._uiLocations = new Map();
this._condition;
this._enabled;
this._updateBreakpoint(condition, enabled);
}
WebInspector.BreakpointManager.Breakpoint.prototype = {
primaryUILocation: function()
{
return this._primaryUILocation;
},
_addResolvedLocation: function(location)
{
this._liveLocations.push(this._breakpointManager._debuggerModel.createLiveLocation(location, this._locationUpdated.bind(this, location)));
},
_locationUpdated: function(location, uiLocation)
{
var oldUILocation = this._uiLocations.get(location);
if (oldUILocation)
this._breakpointManager._uiLocationRemoved(this, oldUILocation);
this._uiLocations.put(location, uiLocation);
this._breakpointManager._uiLocationAdded(this, uiLocation);
},
enabled: function()
{
return this._enabled;
},
setEnabled: function(enabled)
{
this._updateBreakpoint(this._condition, enabled);
},
condition: function()
{
return this._condition;
},
setCondition: function(condition)
{
this._updateBreakpoint(condition, this._enabled);
},
_updateBreakpoint: function(condition, enabled)
{
if (this._enabled === enabled && this._condition === condition)
return;
if (this._enabled)
this._removeFromDebugger();
this._enabled = enabled;
this._condition = condition;
this._breakpointManager._storage._updateBreakpoint(this);
if (this._enabled) {
this._setInDebugger();
return;
}
this._fakeBreakpointAtPrimaryLocation();
},
remove: function()
{
this._resetLocations();
this._removeFromDebugger();
this._breakpointManager._removeBreakpoint(this, true);
},
_setInDebugger: function()
{
var rawLocation = this._breakpointManager._sourceMapping.uiLocationToRawLocation(this._primaryUILocation.uiSourceCode, this._primaryUILocation.lineNumber, 0);
this._breakpointManager._debuggerModel.setBreakpointByScriptLocation(rawLocation, this._condition, didSetBreakpoint.bind(this));
function didSetBreakpoint(breakpointId, locations)
{
if (!breakpointId) {
this._resetLocations();
this._breakpointManager._removeBreakpoint(this, false);
return;
}
this._debuggerId = breakpointId;
this._breakpointManager._breakpointForDebuggerId[breakpointId] = this;
if (!locations.length) {
this._fakeBreakpointAtPrimaryLocation();
return;
}
this._resetLocations();
for (var i = 0; i < locations.length; ++i) {
var script = this._breakpointManager._debuggerModel.scriptForId(locations[i].scriptId);
var uiLocation = script.rawLocationToUILocation(locations[i]);
if (this._breakpointManager.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber)) {
this.remove();
return;
}
}
for (var i = 0; i < locations.length; ++i)
this._addResolvedLocation(locations[i]);
}
},
_removeFromDebugger: function()
{
if (this._debuggerId) {
this._breakpointManager._debuggerModel.removeBreakpoint(this._debuggerId);
delete this._breakpointManager._breakpointForDebuggerId[this._debuggerId];
delete this._debuggerId;
}
},
_resetLocations: function()
{
var uiLocations = this._uiLocations.values();
for (var i = 0; i < uiLocations.length; ++i)
this._breakpointManager._uiLocationRemoved(this, uiLocations[i]);
for (var i = 0; i < this._liveLocations.length; ++i)
this._liveLocations[i].dispose();
this._liveLocations = [];
this._uiLocations = new Map();
},
_breakpointStorageId: function()
{
return this._primaryUILocation.uiSourceCode.id + ":" + this._primaryUILocation.lineNumber;
},
_fakeBreakpointAtPrimaryLocation: function()
{
this._resetLocations();
this._uiLocations.put({}, this._primaryUILocation);
this._breakpointManager._uiLocationAdded(this, this._primaryUILocation);
}
}
WebInspector.BreakpointManager.Storage = function(breakpointManager, setting)
{
this._breakpointManager = breakpointManager;
this._setting = setting;
var breakpoints = this._setting.get();
this._breakpoints = {};
for (var i = 0; i < breakpoints.length; ++i) {
var breakpoint = breakpoints[i];
this._breakpoints[breakpoint.sourceFileId + ":" + breakpoint.lineNumber] = breakpoint;
}
}
WebInspector.BreakpointManager.Storage.prototype = {
restoreBreakpoints: function(uiSourceCode)
{
this._muted = true;
for (var id in this._breakpoints) {
var breakpoint = this._breakpoints[id];
if (breakpoint.sourceFileId === uiSourceCode.id)
this._breakpointManager.setBreakpoint(uiSourceCode, breakpoint.lineNumber, breakpoint.condition, breakpoint.enabled, true);
}
delete this._muted;
},
_updateBreakpoint: function(breakpoint)
{
if (this._muted)
return;
this._breakpoints[breakpoint._breakpointStorageId()] = new WebInspector.BreakpointManager.Storage.Item(breakpoint);
this._save();
},
_removeBreakpoint: function(breakpoint)
{
if (this._muted)
return;
delete this._breakpoints[breakpoint._breakpointStorageId()];
this._save();
},
_save: function()
{
var breakpointsArray = [];
for (var id in this._breakpoints)
breakpointsArray.push(this._breakpoints[id]);
this._setting.set(breakpointsArray);
}
}
WebInspector.BreakpointManager.Storage.Item = function(breakpoint)
{
var primaryUILocation = breakpoint.primaryUILocation();
this.sourceFileId = primaryUILocation.uiSourceCode.id;
this.lineNumber = primaryUILocation.lineNumber;
this.condition = breakpoint.condition();
this.enabled = breakpoint.enabled();
}