BreakpointManager.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. /*
  2. * Copyright (C) 2011 Google Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. *
  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
  13. * distribution.
  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.
  17. *
  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.
  29. */
  30. /**
  31. * @constructor
  32. * @extends {WebInspector.Object}
  33. * @param {WebInspector.Setting} breakpointStorage
  34. * @param {WebInspector.DebuggerModel} debuggerModel
  35. * @param {WebInspector.Workspace} workspace
  36. */
  37. WebInspector.BreakpointManager = function(breakpointStorage, debuggerModel, workspace)
  38. {
  39. this._storage = new WebInspector.BreakpointManager.Storage(this, breakpointStorage);
  40. this._debuggerModel = debuggerModel;
  41. this._workspace = workspace;
  42. this._breakpoints = new Map();
  43. this._breakpointForDebuggerId = {};
  44. this._breakpointsForUISourceCode = new Map();
  45. this._sourceFilesWithRestoredBreakpoints = {};
  46. this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
  47. this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._projectWillReset, this);
  48. this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
  49. }
  50. WebInspector.BreakpointManager.Events = {
  51. BreakpointAdded: "breakpoint-added",
  52. BreakpointRemoved: "breakpoint-removed"
  53. }
  54. WebInspector.BreakpointManager.sourceFileId = function(uiSourceCode)
  55. {
  56. if (!uiSourceCode.url)
  57. return "";
  58. var deobfuscatedPrefix = uiSourceCode.formatted() ? "deobfuscated:" : "";
  59. return deobfuscatedPrefix + uiSourceCode.uri();
  60. }
  61. WebInspector.BreakpointManager.prototype = {
  62. /**
  63. * @param {WebInspector.UISourceCode} uiSourceCode
  64. */
  65. _restoreBreakpoints: function(uiSourceCode)
  66. {
  67. var sourceFileId = WebInspector.BreakpointManager.sourceFileId(uiSourceCode);
  68. if (!sourceFileId || this._sourceFilesWithRestoredBreakpoints[sourceFileId])
  69. return;
  70. this._sourceFilesWithRestoredBreakpoints[sourceFileId] = true;
  71. // Erase provisional breakpoints prior to restoring them.
  72. for (var debuggerId in this._breakpointForDebuggerId) {
  73. var breakpoint = this._breakpointForDebuggerId[debuggerId];
  74. if (breakpoint._sourceFileId !== sourceFileId)
  75. continue;
  76. breakpoint.remove(true);
  77. }
  78. this._storage._restoreBreakpoints(uiSourceCode);
  79. },
  80. /**
  81. * @param {WebInspector.Event} event
  82. */
  83. _uiSourceCodeAdded: function(event)
  84. {
  85. var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
  86. this._restoreBreakpoints(uiSourceCode);
  87. if (uiSourceCode.contentType() === WebInspector.resourceTypes.Script || uiSourceCode.contentType() === WebInspector.resourceTypes.Document) {
  88. uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.SourceMappingChanged, this._uiSourceCodeMappingChanged, this);
  89. uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.FormattedChanged, this._uiSourceCodeFormatted, this);
  90. }
  91. },
  92. /**
  93. * @param {WebInspector.Event} event
  94. */
  95. _uiSourceCodeFormatted: function(event)
  96. {
  97. var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.target);
  98. this._restoreBreakpoints(uiSourceCode);
  99. },
  100. /**
  101. * @param {WebInspector.UISourceCode} uiSourceCode
  102. */
  103. _resetBreakpoints: function(uiSourceCode)
  104. {
  105. var sourceFileId = WebInspector.BreakpointManager.sourceFileId(uiSourceCode);
  106. var breakpoints = this._breakpoints.keys();
  107. for (var i = 0; i < breakpoints.length; ++i) {
  108. var breakpoint = breakpoints[i];
  109. if (breakpoint._sourceFileId !== sourceFileId)
  110. return;
  111. if (breakpoint.enabled()) {
  112. breakpoint._removeFromDebugger();
  113. breakpoint._setInDebugger();
  114. }
  115. }
  116. },
  117. /**
  118. * @param {WebInspector.Event} event
  119. */
  120. _uiSourceCodeMappingChanged: function(event)
  121. {
  122. var identityHasChanged = /** @type {boolean} */ (event.data.identityHasChanged);
  123. if (!identityHasChanged)
  124. return;
  125. var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.target);
  126. this._resetBreakpoints(uiSourceCode);
  127. },
  128. /**
  129. * @param {WebInspector.UISourceCode} uiSourceCode
  130. * @param {number} lineNumber
  131. * @param {string} condition
  132. * @param {boolean} enabled
  133. * @return {WebInspector.BreakpointManager.Breakpoint}
  134. */
  135. setBreakpoint: function(uiSourceCode, lineNumber, condition, enabled)
  136. {
  137. this._debuggerModel.setBreakpointsActive(true);
  138. return this._innerSetBreakpoint(uiSourceCode, lineNumber, condition, enabled);
  139. },
  140. /**
  141. * @param {WebInspector.UISourceCode} uiSourceCode
  142. * @param {number} lineNumber
  143. * @param {string} condition
  144. * @param {boolean} enabled
  145. * @return {WebInspector.BreakpointManager.Breakpoint}
  146. */
  147. _innerSetBreakpoint: function(uiSourceCode, lineNumber, condition, enabled)
  148. {
  149. var breakpoint = this.findBreakpoint(uiSourceCode, lineNumber);
  150. if (breakpoint) {
  151. breakpoint._updateBreakpoint(condition, enabled);
  152. return breakpoint;
  153. }
  154. breakpoint = new WebInspector.BreakpointManager.Breakpoint(this, uiSourceCode, lineNumber, condition, enabled);
  155. this._breakpoints.put(breakpoint);
  156. return breakpoint;
  157. },
  158. /**
  159. * @param {WebInspector.UISourceCode} uiSourceCode
  160. * @param {number} lineNumber
  161. * @return {?WebInspector.BreakpointManager.Breakpoint}
  162. */
  163. findBreakpoint: function(uiSourceCode, lineNumber)
  164. {
  165. var breakpoints = this._breakpointsForUISourceCode.get(uiSourceCode);
  166. var lineBreakpoints = breakpoints ? breakpoints[lineNumber] : null;
  167. return lineBreakpoints ? lineBreakpoints[0] : null;
  168. },
  169. /**
  170. * @param {WebInspector.UISourceCode} uiSourceCode
  171. * @return {Array.<WebInspector.BreakpointManager.Breakpoint>}
  172. */
  173. breakpointsForUISourceCode: function(uiSourceCode)
  174. {
  175. var result = [];
  176. var breakpoints = /** @type {Array.<WebInspector.BreakpointManager.Breakpoint>} */(this._breakpoints.keys());
  177. for (var i = 0; i < breakpoints.length; ++i) {
  178. var breakpoint = breakpoints[i];
  179. var uiLocation = breakpoint._primaryUILocation;
  180. if (uiLocation.uiSourceCode === uiSourceCode)
  181. result.push(breakpoint);
  182. }
  183. return result;
  184. },
  185. /**
  186. * @return {Array.<WebInspector.BreakpointManager.Breakpoint>}
  187. */
  188. allBreakpoints: function()
  189. {
  190. var result = [];
  191. var breakpoints = /** @type {Array.<WebInspector.BreakpointManager.Breakpoint>} */(this._breakpoints.keys());
  192. return breakpoints;
  193. },
  194. /**
  195. * @param {WebInspector.UISourceCode} uiSourceCode
  196. * @return {Array.<{breakpoint: WebInspector.BreakpointManager.Breakpoint, uiLocation: WebInspector.UILocation}>}
  197. */
  198. breakpointLocationsForUISourceCode: function(uiSourceCode)
  199. {
  200. var result = [];
  201. var breakpoints = /** @type {Array.<WebInspector.BreakpointManager.Breakpoint>} */(this._breakpoints.keys());
  202. for (var i = 0; i < breakpoints.length; ++i) {
  203. var breakpoint = breakpoints[i];
  204. var uiLocations = Object.values(breakpoint._uiLocations);
  205. for (var j = 0; j < uiLocations.length; ++j) {
  206. var uiLocation = uiLocations[j];
  207. if (uiLocation.uiSourceCode === uiSourceCode)
  208. result.push({breakpoint: breakpoint, uiLocation: uiLocations[j]});
  209. }
  210. }
  211. return result;
  212. },
  213. /**
  214. * @return {Array.<{breakpoint: WebInspector.BreakpointManager.Breakpoint, uiLocation: WebInspector.UILocation}>}
  215. */
  216. allBreakpointLocations: function()
  217. {
  218. var result = [];
  219. var breakpoints = /** @type {Array.<WebInspector.BreakpointManager.Breakpoint>} */(this._breakpoints.keys());
  220. for (var i = 0; i < breakpoints.length; ++i) {
  221. var breakpoint = breakpoints[i];
  222. var uiLocations = Object.values(breakpoint._uiLocations);
  223. for (var j = 0; j < uiLocations.length; ++j)
  224. result.push({breakpoint: breakpoint, uiLocation: uiLocations[j]});
  225. }
  226. return result;
  227. },
  228. /**
  229. * @param {boolean} toggleState
  230. */
  231. toggleAllBreakpoints: function(toggleState)
  232. {
  233. var breakpoints = /** @type {Array.<WebInspector.BreakpointManager.Breakpoint>} */(this._breakpoints.keys());
  234. for (var i = 0; i < breakpoints.length; ++i) {
  235. var breakpoint = breakpoints[i];
  236. if (breakpoint.enabled() != toggleState)
  237. breakpoint.setEnabled(toggleState);
  238. }
  239. },
  240. removeAllBreakpoints: function()
  241. {
  242. var breakpoints = /** @type {Array.<WebInspector.BreakpointManager.Breakpoint>} */(this._breakpoints.keys());
  243. for (var i = 0; i < breakpoints.length; ++i)
  244. breakpoints[i].remove();
  245. },
  246. reset: function()
  247. {
  248. // Remove all breakpoints from UI and debugger, do not update storage.
  249. this._storage._muted = true;
  250. this.removeAllBreakpoints();
  251. delete this._storage._muted;
  252. // Remove all provisional breakpoints from the debugger.
  253. for (var debuggerId in this._breakpointForDebuggerId)
  254. this._debuggerModel.removeBreakpoint(debuggerId);
  255. this._breakpointForDebuggerId = {};
  256. this._sourceFilesWithRestoredBreakpoints = {};
  257. },
  258. _projectWillReset: function(event)
  259. {
  260. var project = /** @type {WebInspector.Project} */ (event.data);
  261. var uiSourceCodes = project.uiSourceCodes();
  262. for (var i = 0; i < uiSourceCodes.length; ++i) {
  263. var uiSourceCode = uiSourceCodes[i];
  264. var breakpoints = this._breakpointsForUISourceCode.get(uiSourceCode) || [];
  265. for (var lineNumber in breakpoints) {
  266. var lineBreakpoints = breakpoints[lineNumber];
  267. for (var j = 0; j < lineBreakpoints.length; ++j) {
  268. var breakpoint = lineBreakpoints[j];
  269. breakpoint._resetLocations();
  270. }
  271. }
  272. this._breakpointsForUISourceCode.remove(uiSourceCode);
  273. breakpoints = this.breakpointsForUISourceCode(uiSourceCode);
  274. for (var j = 0; j < breakpoints.length; ++j) {
  275. var breakpoint = breakpoints[j];
  276. this._breakpoints.remove(breakpoint);
  277. }
  278. var sourceFileId = WebInspector.BreakpointManager.sourceFileId(uiSourceCode);
  279. delete this._sourceFilesWithRestoredBreakpoints[sourceFileId];
  280. }
  281. },
  282. _breakpointResolved: function(event)
  283. {
  284. var breakpointId = /** @type {DebuggerAgent.BreakpointId} */ (event.data.breakpointId);
  285. var location = /** @type {WebInspector.DebuggerModel.Location} */ (event.data.location);
  286. var breakpoint = this._breakpointForDebuggerId[breakpointId];
  287. if (!breakpoint)
  288. return;
  289. if (!this._breakpoints.contains(breakpoint))
  290. this._breakpoints.put(breakpoint);
  291. breakpoint._addResolvedLocation(location);
  292. },
  293. /**
  294. * @param {WebInspector.BreakpointManager.Breakpoint} breakpoint
  295. * @param {boolean} removeFromStorage
  296. */
  297. _removeBreakpoint: function(breakpoint, removeFromStorage)
  298. {
  299. console.assert(!breakpoint._debuggerId)
  300. this._breakpoints.remove(breakpoint);
  301. if (removeFromStorage)
  302. this._storage._removeBreakpoint(breakpoint);
  303. },
  304. /**
  305. * @param {WebInspector.BreakpointManager.Breakpoint} breakpoint
  306. * @param {WebInspector.UILocation} uiLocation
  307. */
  308. _uiLocationAdded: function(breakpoint, uiLocation)
  309. {
  310. var breakpoints = this._breakpointsForUISourceCode.get(uiLocation.uiSourceCode);
  311. if (!breakpoints) {
  312. breakpoints = {};
  313. this._breakpointsForUISourceCode.put(uiLocation.uiSourceCode, breakpoints);
  314. }
  315. var lineBreakpoints = breakpoints[uiLocation.lineNumber];
  316. if (!lineBreakpoints) {
  317. lineBreakpoints = [];
  318. breakpoints[uiLocation.lineNumber] = lineBreakpoints;
  319. }
  320. lineBreakpoints.push(breakpoint);
  321. this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.BreakpointAdded, {breakpoint: breakpoint, uiLocation: uiLocation});
  322. },
  323. /**
  324. * @param {WebInspector.BreakpointManager.Breakpoint} breakpoint
  325. * @param {WebInspector.UILocation} uiLocation
  326. */
  327. _uiLocationRemoved: function(breakpoint, uiLocation)
  328. {
  329. var breakpoints = this._breakpointsForUISourceCode.get(uiLocation.uiSourceCode);
  330. if (!breakpoints)
  331. return;
  332. var lineBreakpoints = breakpoints[uiLocation.lineNumber];
  333. if (!lineBreakpoints)
  334. return;
  335. lineBreakpoints.remove(breakpoint);
  336. if (!lineBreakpoints.length)
  337. delete breakpoints[uiLocation.lineNumber];
  338. this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.BreakpointRemoved, {breakpoint: breakpoint, uiLocation: uiLocation});
  339. },
  340. __proto__: WebInspector.Object.prototype
  341. }
  342. /**
  343. * @constructor
  344. * @param {WebInspector.BreakpointManager} breakpointManager
  345. * @param {WebInspector.UISourceCode} uiSourceCode
  346. * @param {number} lineNumber
  347. * @param {string} condition
  348. * @param {boolean} enabled
  349. */
  350. WebInspector.BreakpointManager.Breakpoint = function(breakpointManager, uiSourceCode, lineNumber, condition, enabled)
  351. {
  352. this._breakpointManager = breakpointManager;
  353. this._primaryUILocation = new WebInspector.UILocation(uiSourceCode, lineNumber, 0);
  354. this._sourceFileId = WebInspector.BreakpointManager.sourceFileId(uiSourceCode);
  355. /** @type {Array.<WebInspector.Script.Location>} */
  356. this._liveLocations = [];
  357. /** @type {!Object.<string, WebInspector.UILocation>} */
  358. this._uiLocations = {};
  359. // Force breakpoint update.
  360. /** @type {string} */ this._condition;
  361. /** @type {boolean} */ this._enabled;
  362. this._updateBreakpoint(condition, enabled);
  363. }
  364. WebInspector.BreakpointManager.Breakpoint.prototype = {
  365. /**
  366. * @return {WebInspector.UILocation}
  367. */
  368. primaryUILocation: function()
  369. {
  370. return this._primaryUILocation;
  371. },
  372. /**
  373. * @param {WebInspector.DebuggerModel.Location} location
  374. */
  375. _addResolvedLocation: function(location)
  376. {
  377. this._liveLocations.push(this._breakpointManager._debuggerModel.createLiveLocation(location, this._locationUpdated.bind(this, location)));
  378. },
  379. /**
  380. * @param {WebInspector.DebuggerModel.Location} location
  381. * @param {WebInspector.UILocation} uiLocation
  382. */
  383. _locationUpdated: function(location, uiLocation)
  384. {
  385. var stringifiedLocation = location.scriptId + ":" + location.lineNumber + ":" + location.columnNumber;
  386. var oldUILocation = /** @type {WebInspector.UILocation} */ (this._uiLocations[stringifiedLocation]);
  387. if (oldUILocation)
  388. this._breakpointManager._uiLocationRemoved(this, oldUILocation);
  389. if (this._uiLocations[""]) {
  390. delete this._uiLocations[""];
  391. this._breakpointManager._uiLocationRemoved(this, this._primaryUILocation);
  392. }
  393. this._uiLocations[stringifiedLocation] = uiLocation;
  394. this._breakpointManager._uiLocationAdded(this, uiLocation);
  395. },
  396. /**
  397. * @return {boolean}
  398. */
  399. enabled: function()
  400. {
  401. return this._enabled;
  402. },
  403. /**
  404. * @param {boolean} enabled
  405. */
  406. setEnabled: function(enabled)
  407. {
  408. this._updateBreakpoint(this._condition, enabled);
  409. },
  410. /**
  411. * @return {string}
  412. */
  413. condition: function()
  414. {
  415. return this._condition;
  416. },
  417. /**
  418. * @param {string} condition
  419. */
  420. setCondition: function(condition)
  421. {
  422. this._updateBreakpoint(condition, this._enabled);
  423. },
  424. /**
  425. * @param {string} condition
  426. * @param {boolean} enabled
  427. */
  428. _updateBreakpoint: function(condition, enabled)
  429. {
  430. if (this._enabled === enabled && this._condition === condition)
  431. return;
  432. if (this._enabled)
  433. this._removeFromDebugger();
  434. this._enabled = enabled;
  435. this._condition = condition;
  436. this._breakpointManager._storage._updateBreakpoint(this);
  437. var scriptFile = this._primaryUILocation.uiSourceCode.scriptFile();
  438. if (this._enabled && !(scriptFile && scriptFile.hasDivergedFromVM())) {
  439. if (this._setInDebugger())
  440. return;
  441. }
  442. this._fakeBreakpointAtPrimaryLocation();
  443. },
  444. /**
  445. * @param {boolean=} keepInStorage
  446. */
  447. remove: function(keepInStorage)
  448. {
  449. var removeFromStorage = !keepInStorage;
  450. this._resetLocations();
  451. this._removeFromDebugger();
  452. this._breakpointManager._removeBreakpoint(this, removeFromStorage);
  453. },
  454. _setInDebugger: function()
  455. {
  456. console.assert(!this._debuggerId);
  457. var rawLocation = this._primaryUILocation.uiLocationToRawLocation();
  458. var debuggerModelLocation = /** @type {WebInspector.DebuggerModel.Location} */ (rawLocation);
  459. if (debuggerModelLocation) {
  460. this._breakpointManager._debuggerModel.setBreakpointByScriptLocation(debuggerModelLocation, this._condition, this._didSetBreakpointInDebugger.bind(this));
  461. return true;
  462. }
  463. if (this._primaryUILocation.uiSourceCode.url) {
  464. this._breakpointManager._debuggerModel.setBreakpointByURL(this._primaryUILocation.uiSourceCode.url, this._primaryUILocation.lineNumber, 0, this._condition, this._didSetBreakpointInDebugger.bind(this));
  465. return true;
  466. }
  467. return false;
  468. },
  469. /**
  470. * @this {WebInspector.BreakpointManager.Breakpoint}
  471. * @param {?DebuggerAgent.BreakpointId} breakpointId
  472. * @param {Array.<WebInspector.DebuggerModel.Location>} locations
  473. */
  474. _didSetBreakpointInDebugger: function(breakpointId, locations)
  475. {
  476. if (!breakpointId) {
  477. this._resetLocations();
  478. this._breakpointManager._removeBreakpoint(this, false);
  479. return;
  480. }
  481. this._debuggerId = breakpointId;
  482. this._breakpointManager._breakpointForDebuggerId[breakpointId] = this;
  483. if (!locations.length) {
  484. this._fakeBreakpointAtPrimaryLocation();
  485. return;
  486. }
  487. this._resetLocations();
  488. for (var i = 0; i < locations.length; ++i) {
  489. var script = this._breakpointManager._debuggerModel.scriptForId(locations[i].scriptId);
  490. var uiLocation = script.rawLocationToUILocation(locations[i].lineNumber, locations[i].columnNumber);
  491. if (this._breakpointManager.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber)) {
  492. // location clash
  493. this.remove();
  494. return;
  495. }
  496. }
  497. for (var i = 0; i < locations.length; ++i)
  498. this._addResolvedLocation(locations[i]);
  499. },
  500. _removeFromDebugger: function()
  501. {
  502. if (this._debuggerId) {
  503. this._breakpointManager._debuggerModel.removeBreakpoint(this._debuggerId);
  504. delete this._breakpointManager._breakpointForDebuggerId[this._debuggerId];
  505. delete this._debuggerId;
  506. }
  507. },
  508. _resetLocations: function()
  509. {
  510. for (var stringifiedLocation in this._uiLocations)
  511. this._breakpointManager._uiLocationRemoved(this, this._uiLocations[stringifiedLocation]);
  512. for (var i = 0; i < this._liveLocations.length; ++i)
  513. this._liveLocations[i].dispose();
  514. this._liveLocations = [];
  515. this._uiLocations = {};
  516. },
  517. /**
  518. * @return {string}
  519. */
  520. _breakpointStorageId: function()
  521. {
  522. if (!this._sourceFileId)
  523. return "";
  524. return this._sourceFileId + ":" + this._primaryUILocation.lineNumber;
  525. },
  526. _fakeBreakpointAtPrimaryLocation: function()
  527. {
  528. this._resetLocations();
  529. this._uiLocations[""] = this._primaryUILocation;
  530. this._breakpointManager._uiLocationAdded(this, this._primaryUILocation);
  531. }
  532. }
  533. /**
  534. * @constructor
  535. * @param {WebInspector.BreakpointManager} breakpointManager
  536. * @param {WebInspector.Setting} setting
  537. */
  538. WebInspector.BreakpointManager.Storage = function(breakpointManager, setting)
  539. {
  540. this._breakpointManager = breakpointManager;
  541. this._setting = setting;
  542. var breakpoints = this._setting.get();
  543. /** @type {Object.<string,WebInspector.BreakpointManager.Storage.Item>} */
  544. this._breakpoints = {};
  545. for (var i = 0; i < breakpoints.length; ++i) {
  546. var breakpoint = /** @type {WebInspector.BreakpointManager.Storage.Item} */ (breakpoints[i]);
  547. this._breakpoints[breakpoint.sourceFileId + ":" + breakpoint.lineNumber] = breakpoint;
  548. }
  549. }
  550. WebInspector.BreakpointManager.Storage.prototype = {
  551. /**
  552. * @param {WebInspector.UISourceCode} uiSourceCode
  553. */
  554. _restoreBreakpoints: function(uiSourceCode)
  555. {
  556. this._muted = true;
  557. var sourceFileId = WebInspector.BreakpointManager.sourceFileId(uiSourceCode);
  558. for (var id in this._breakpoints) {
  559. var breakpoint = this._breakpoints[id];
  560. if (breakpoint.sourceFileId === sourceFileId)
  561. this._breakpointManager._innerSetBreakpoint(uiSourceCode, breakpoint.lineNumber, breakpoint.condition, breakpoint.enabled);
  562. }
  563. delete this._muted;
  564. },
  565. /**
  566. * @param {WebInspector.BreakpointManager.Breakpoint} breakpoint
  567. */
  568. _updateBreakpoint: function(breakpoint)
  569. {
  570. if (this._muted || !breakpoint._breakpointStorageId())
  571. return;
  572. this._breakpoints[breakpoint._breakpointStorageId()] = new WebInspector.BreakpointManager.Storage.Item(breakpoint);
  573. this._save();
  574. },
  575. /**
  576. * @param {WebInspector.BreakpointManager.Breakpoint} breakpoint
  577. */
  578. _removeBreakpoint: function(breakpoint)
  579. {
  580. if (this._muted)
  581. return;
  582. delete this._breakpoints[breakpoint._breakpointStorageId()];
  583. this._save();
  584. },
  585. _save: function()
  586. {
  587. var breakpointsArray = [];
  588. for (var id in this._breakpoints)
  589. breakpointsArray.push(this._breakpoints[id]);
  590. this._setting.set(breakpointsArray);
  591. }
  592. }
  593. /**
  594. * @constructor
  595. * @param {WebInspector.BreakpointManager.Breakpoint} breakpoint
  596. */
  597. WebInspector.BreakpointManager.Storage.Item = function(breakpoint)
  598. {
  599. var primaryUILocation = breakpoint.primaryUILocation();
  600. this.sourceFileId = breakpoint._sourceFileId;
  601. this.lineNumber = primaryUILocation.lineNumber;
  602. this.condition = breakpoint.condition();
  603. this.enabled = breakpoint.enabled();
  604. }
  605. /** @type {WebInspector.BreakpointManager} */
  606. WebInspector.breakpointManager = null;