Web Inspector: Debugger: modernize serialization of breakpoints and the maps that...
authordrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Apr 2019 00:20:11 +0000 (00:20 +0000)
committerdrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 Apr 2019 00:20:11 +0000 (00:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196230
<rdar://problem/49236485>

Reviewed by Joseph Pecoraro.

* UserInterface/Controllers/DebuggerManager.js:
(WI.DebuggerManager):
(WI.DebuggerManager.prototype.breakpointsForSourceCode):
(WI.DebuggerManager.prototype.addBreakpoint):
(WI.DebuggerManager.prototype.removeBreakpoint):
(WI.DebuggerManager.prototype._setBreakpoint):
(WI.DebuggerManager.prototype._setBreakpoint.didSetBreakpoint):

* UserInterface/Models/Breakpoint.js:
(WI.Breakpoint):
(WI.Breakpoint.fromJSON): Added.
(WI.Breakpoint.prototype.toJSON):
(WI.Breakpoint.prototype.set resolved):
(WI.Breakpoint.prototype.recreateAction):
(WI.Breakpoint.prototype.saveIdentityToCookie):
(WI.Breakpoint.prototype._isSpecial): Added.
(WI.Breakpoint.set resolved.isSpecialBreakpoint): Deleted.
(WI.Breakpoint.serializeOptions): Deleted.

* UserInterface/Models/BreakpointAction.js:
(WI.BreakpointAction):
(WI.BreakpointAction.fromJSON): Added.
(WI.BreakpointAction.prototype.toProtocol): Added.

* UserInterface/Views/DebuggerSidebarPanel.js:
(WI.DebuggerSidebarPanel.prototype._addBreakpointsForSourceCode):

* UserInterface/Views/SourceCodeTextEditor.js:
(WI.SourceCodeTextEditor.prototype._prepareEditorForInitialContent):
(WI.SourceCodeTextEditor.prototype._breakpointsEnabledDidChange):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243727 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Controllers/DebuggerManager.js
Source/WebInspectorUI/UserInterface/Models/Breakpoint.js
Source/WebInspectorUI/UserInterface/Models/BreakpointAction.js
Source/WebInspectorUI/UserInterface/Views/DebuggerSidebarPanel.js
Source/WebInspectorUI/UserInterface/Views/SourceCodeTextEditor.js

index 0f0158d..2fb7e15 100644 (file)
@@ -1,5 +1,44 @@
 2019-04-01  Devin Rousso  <drousso@apple.com>
 
 2019-04-01  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: Debugger: modernize serialization of breakpoints and the maps that hold them
+        https://bugs.webkit.org/show_bug.cgi?id=196230
+        <rdar://problem/49236485>
+
+        Reviewed by Joseph Pecoraro.
+
+        * UserInterface/Controllers/DebuggerManager.js:
+        (WI.DebuggerManager):
+        (WI.DebuggerManager.prototype.breakpointsForSourceCode):
+        (WI.DebuggerManager.prototype.addBreakpoint):
+        (WI.DebuggerManager.prototype.removeBreakpoint):
+        (WI.DebuggerManager.prototype._setBreakpoint):
+        (WI.DebuggerManager.prototype._setBreakpoint.didSetBreakpoint):
+
+        * UserInterface/Models/Breakpoint.js:
+        (WI.Breakpoint):
+        (WI.Breakpoint.fromJSON): Added.
+        (WI.Breakpoint.prototype.toJSON):
+        (WI.Breakpoint.prototype.set resolved):
+        (WI.Breakpoint.prototype.recreateAction):
+        (WI.Breakpoint.prototype.saveIdentityToCookie):
+        (WI.Breakpoint.prototype._isSpecial): Added.
+        (WI.Breakpoint.set resolved.isSpecialBreakpoint): Deleted.
+        (WI.Breakpoint.serializeOptions): Deleted.
+
+        * UserInterface/Models/BreakpointAction.js:
+        (WI.BreakpointAction):
+        (WI.BreakpointAction.fromJSON): Added.
+        (WI.BreakpointAction.prototype.toProtocol): Added.
+
+        * UserInterface/Views/DebuggerSidebarPanel.js:
+        (WI.DebuggerSidebarPanel.prototype._addBreakpointsForSourceCode):
+
+        * UserInterface/Views/SourceCodeTextEditor.js:
+        (WI.SourceCodeTextEditor.prototype._prepareEditorForInitialContent):
+        (WI.SourceCodeTextEditor.prototype._breakpointsEnabledDidChange):
+
+2019-04-01  Devin Rousso  <drousso@apple.com>
+
         Web Inspector: DOMDebugger: disabling a breakpoint for a specific event listener removes it from the UI
         https://bugs.webkit.org/show_bug.cgi?id=196453
         <rdar://problem/49489318>
         Web Inspector: DOMDebugger: disabling a breakpoint for a specific event listener removes it from the UI
         https://bugs.webkit.org/show_bug.cgi?id=196453
         <rdar://problem/49489318>
index 805858f..2a6a20f 100644 (file)
@@ -58,17 +58,24 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object
 
         let specialBreakpointLocation = new WI.SourceCodeLocation(null, Infinity, Infinity);
 
 
         let specialBreakpointLocation = new WI.SourceCodeLocation(null, Infinity, Infinity);
 
-        this._allExceptionsBreakpoint = new WI.Breakpoint(specialBreakpointLocation, !this._allExceptionsBreakpointEnabledSetting.value);
+        this._allExceptionsBreakpoint = new WI.Breakpoint(specialBreakpointLocation, {
+            disabled: !this._allExceptionsBreakpointEnabledSetting.value,
+        });
         this._allExceptionsBreakpoint.resolved = true;
 
         this._allExceptionsBreakpoint.resolved = true;
 
-        this._uncaughtExceptionsBreakpoint = new WI.Breakpoint(specialBreakpointLocation, !this._uncaughtExceptionsBreakpointEnabledSetting.value);
+        this._uncaughtExceptionsBreakpoint = new WI.Breakpoint(specialBreakpointLocation, {
+            disabled: !this._uncaughtExceptionsBreakpointEnabledSetting.value,
+        });
+        this._uncaughtExceptionsBreakpoint.resolved = true;
 
 
-        this._assertionFailuresBreakpoint = new WI.Breakpoint(specialBreakpointLocation, !this._assertionFailuresBreakpointEnabledSetting.value);
+        this._assertionFailuresBreakpoint = new WI.Breakpoint(specialBreakpointLocation, {
+            disabled: !this._assertionFailuresBreakpointEnabledSetting.value,
+        });
         this._assertionFailuresBreakpoint.resolved = true;
 
         this._breakpoints = [];
         this._assertionFailuresBreakpoint.resolved = true;
 
         this._breakpoints = [];
-        this._breakpointContentIdentifierMap = new Map;
-        this._breakpointScriptIdentifierMap = new Map;
+        this._breakpointContentIdentifierMap = new Multimap;
+        this._breakpointScriptIdentifierMap = new Multimap;
         this._breakpointIdMap = new Map;
 
         this._breakOnExceptionsState = "none";
         this._breakpointIdMap = new Map;
 
         this._breakOnExceptionsState = "none";
@@ -103,14 +110,14 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object
             let existingSerializedBreakpoints = WI.Setting.migrateValue("breakpoints");
             if (existingSerializedBreakpoints) {
                 for (let existingSerializedBreakpoint of existingSerializedBreakpoints)
             let existingSerializedBreakpoints = WI.Setting.migrateValue("breakpoints");
             if (existingSerializedBreakpoints) {
                 for (let existingSerializedBreakpoint of existingSerializedBreakpoints)
-                    await WI.objectStores.breakpoints.putObject(new WI.Breakpoint(existingSerializedBreakpoint));
+                    await WI.objectStores.breakpoints.putObject(WI.Breakpoint.fromJSON(existingSerializedBreakpoint));
             }
 
             let serializedBreakpoints = await WI.objectStores.breakpoints.getAll();
 
             this._restoringBreakpoints = true;
             for (let serializedBreakpoint of serializedBreakpoints) {
             }
 
             let serializedBreakpoints = await WI.objectStores.breakpoints.getAll();
 
             this._restoringBreakpoints = true;
             for (let serializedBreakpoint of serializedBreakpoints) {
-                let breakpoint = new WI.Breakpoint(serializedBreakpoint);
+                let breakpoint = WI.Breakpoint.fromJSON(serializedBreakpoint);
 
                 const key = null;
                 WI.objectStores.breakpoints.associateObject(breakpoint, key, serializedBreakpoint);
 
                 const key = null;
                 WI.objectStores.breakpoints.associateObject(breakpoint, key, serializedBreakpoint);
@@ -211,12 +218,8 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object
     {
         console.assert(sourceCode instanceof WI.Resource || sourceCode instanceof WI.Script);
 
     {
         console.assert(sourceCode instanceof WI.Resource || sourceCode instanceof WI.Script);
 
-        if (sourceCode instanceof WI.SourceMapResource) {
-            let originalSourceCodeBreakpoints = this.breakpointsForSourceCode(sourceCode.sourceMap.originalSourceCode);
-            return originalSourceCodeBreakpoints.filter(function(breakpoint) {
-                return breakpoint.sourceCodeLocation.displaySourceCode === sourceCode;
-            });
-        }
+        if (sourceCode instanceof WI.SourceMapResource)
+            return Array.from(this.breakpointsForSourceCode(sourceCode.sourceMap.originalSourceCode)).filter((breakpoint) => breakpoint.sourceCodeLocation.displaySourceCode === sourceCode);
 
         let contentIdentifierBreakpoints = this._breakpointContentIdentifierMap.get(sourceCode.contentIdentifier);
         if (contentIdentifierBreakpoints) {
 
         let contentIdentifierBreakpoints = this._breakpointContentIdentifierMap.get(sourceCode.contentIdentifier);
         if (contentIdentifierBreakpoints) {
@@ -480,23 +483,11 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object
             return;
         }
 
             return;
         }
 
-        if (breakpoint.contentIdentifier) {
-            let contentIdentifierBreakpoints = this._breakpointContentIdentifierMap.get(breakpoint.contentIdentifier);
-            if (!contentIdentifierBreakpoints) {
-                contentIdentifierBreakpoints = [];
-                this._breakpointContentIdentifierMap.set(breakpoint.contentIdentifier, contentIdentifierBreakpoints);
-            }
-            contentIdentifierBreakpoints.push(breakpoint);
-        }
+        if (breakpoint.contentIdentifier)
+            this._breakpointContentIdentifierMap.add(breakpoint.contentIdentifier, breakpoint);
 
 
-        if (breakpoint.scriptIdentifier) {
-            let scriptIdentifierBreakpoints = this._breakpointScriptIdentifierMap.get(breakpoint.scriptIdentifier);
-            if (!scriptIdentifierBreakpoints) {
-                scriptIdentifierBreakpoints = [];
-                this._breakpointScriptIdentifierMap.set(breakpoint.scriptIdentifier, scriptIdentifierBreakpoints);
-            }
-            scriptIdentifierBreakpoints.push(breakpoint);
-        }
+        if (breakpoint.scriptIdentifier)
+            this._breakpointScriptIdentifierMap.add(breakpoint.scriptIdentifier, breakpoint);
 
         this._breakpoints.push(breakpoint);
 
 
         this._breakpoints.push(breakpoint);
 
@@ -537,23 +528,11 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object
         if (breakpoint.identifier)
             this._removeBreakpoint(breakpoint);
 
         if (breakpoint.identifier)
             this._removeBreakpoint(breakpoint);
 
-        if (breakpoint.contentIdentifier) {
-            let contentIdentifierBreakpoints = this._breakpointContentIdentifierMap.get(breakpoint.contentIdentifier);
-            if (contentIdentifierBreakpoints) {
-                contentIdentifierBreakpoints.remove(breakpoint);
-                if (!contentIdentifierBreakpoints.length)
-                    this._breakpointContentIdentifierMap.delete(breakpoint.contentIdentifier);
-            }
-        }
+        if (breakpoint.contentIdentifier)
+            this._breakpointContentIdentifierMap.delete(breakpoint.contentIdentifier, breakpoint);
 
 
-        if (breakpoint.scriptIdentifier) {
-            let scriptIdentifierBreakpoints = this._breakpointScriptIdentifierMap.get(breakpoint.scriptIdentifier);
-            if (scriptIdentifierBreakpoints) {
-                scriptIdentifierBreakpoints.remove(breakpoint);
-                if (!scriptIdentifierBreakpoints.length)
-                    this._breakpointScriptIdentifierMap.delete(breakpoint.scriptIdentifier);
-            }
-        }
+        if (breakpoint.scriptIdentifier)
+            this._breakpointScriptIdentifierMap.delete(breakpoint.scriptIdentifier, breakpoint);
 
         // Disable the breakpoint first, so removing actions doesn't re-add the breakpoint.
         breakpoint.disabled = true;
 
         // Disable the breakpoint first, so removing actions doesn't re-add the breakpoint.
         breakpoint.disabled = true;
@@ -903,14 +882,13 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object
 
     _debuggerBreakpointOptions(breakpoint)
     {
 
     _debuggerBreakpointOptions(breakpoint)
     {
-        const templatePlaceholderRegex = /\$\{.*?\}/;
-
-        let options = breakpoint.serializeOptions();
-        options.actions = options.actions.filter((action) => {
+        let actions = breakpoint.actions;
+        actions = actions.map((action) => action.toProtocol());
+        actions = actions.filter((action) => {
             if (action.type !== WI.BreakpointAction.Type.Log)
                 return true;
 
             if (action.type !== WI.BreakpointAction.Type.Log)
                 return true;
 
-            if (!templatePlaceholderRegex.test(action.data))
+            if (!/\$\{.*?\}/.test(action.data))
                 return true;
 
             let lexer = new WI.BreakpointLogMessageLexer;
                 return true;
 
             let lexer = new WI.BreakpointLogMessageLexer;
@@ -930,7 +908,13 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object
             action.type = WI.BreakpointAction.Type.Evaluate;
             return true;
         });
             action.type = WI.BreakpointAction.Type.Evaluate;
             return true;
         });
-        return options;
+
+        return {
+            condition: breakpoint.condition,
+            ignoreCount: breakpoint.ignoreCount,
+            autoContinue: breakpoint.autoContinue,
+            actions,
+        };
     }
 
     _setBreakpoint(breakpoint, specificTarget, callback)
     }
 
     _setBreakpoint(breakpoint, specificTarget, callback)
@@ -946,10 +930,11 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object
             this.breakpointsEnabled = true;
         }
 
             this.breakpointsEnabled = true;
         }
 
-        function didSetBreakpoint(target, error, breakpointIdentifier, locations)
-        {
-            if (error)
+        function didSetBreakpoint(target, error, breakpointIdentifier, locations) {
+            if (error) {
+                WI.reportInternalError(error);
                 return;
                 return;
+            }
 
             this._breakpointIdMap.set(breakpointIdentifier, breakpoint);
 
 
             this._breakpointIdMap.set(breakpointIdentifier, breakpoint);
 
@@ -995,7 +980,8 @@ WI.DebuggerManager = class DebuggerManager extends WI.Object
                 location: {scriptId: breakpoint.scriptIdentifier, lineNumber: breakpoint.sourceCodeLocation.lineNumber, columnNumber: breakpoint.sourceCodeLocation.columnNumber},
                 options
             }, didSetBreakpoint.bind(this, target), target.DebuggerAgent);
                 location: {scriptId: breakpoint.scriptIdentifier, lineNumber: breakpoint.sourceCodeLocation.lineNumber, columnNumber: breakpoint.sourceCodeLocation.columnNumber},
                 options
             }, didSetBreakpoint.bind(this, target), target.DebuggerAgent);
-        }
+        } else
+            WI.reportInternalError("Unknown source for breakpoint.");
     }
 
     _removeBreakpoint(breakpoint, callback)
     }
 
     _removeBreakpoint(breakpoint, callback)
index 5c879b4..9a209e8 100644 (file)
 
 WI.Breakpoint = class Breakpoint extends WI.Object
 {
 
 WI.Breakpoint = class Breakpoint extends WI.Object
 {
-    constructor(sourceCodeLocationOrInfo, disabled, condition)
+    constructor(sourceCodeLocation, {contentIdentifier, disabled, condition, ignoreCount, autoContinue} = {})
     {
     {
+        console.assert(sourceCodeLocation instanceof WI.SourceCodeLocation);
+        console.assert(!contentIdentifier || typeof contentIdentifier === "string");
+        console.assert(!disabled || typeof disabled === "boolean");
+        console.assert(!condition || typeof condition === "string");
+        console.assert(!ignoreCount || !isNaN(ignoreCount));
+        console.assert(!autoContinue || typeof autoContinue === "boolean");
+
         super();
 
         super();
 
-        if (sourceCodeLocationOrInfo instanceof WI.SourceCodeLocation) {
-            var sourceCode = sourceCodeLocationOrInfo.sourceCode;
-            var contentIdentifier = sourceCode ? sourceCode.contentIdentifier : null;
-            var scriptIdentifier = sourceCode instanceof WI.Script ? sourceCode.id : null;
-            var target = sourceCode instanceof WI.Script ? sourceCode.target : null;
-            var location = sourceCodeLocationOrInfo;
-        } else if (sourceCodeLocationOrInfo && typeof sourceCodeLocationOrInfo === "object") {
-            // The 'url' fallback is for transitioning from older frontends and should be removed.
-            var contentIdentifier = sourceCodeLocationOrInfo.contentIdentifier || sourceCodeLocationOrInfo.url;
-            var lineNumber = sourceCodeLocationOrInfo.lineNumber || 0;
-            var columnNumber = sourceCodeLocationOrInfo.columnNumber || 0;
-            var location = new WI.SourceCodeLocation(null, lineNumber, columnNumber);
-            var ignoreCount = sourceCodeLocationOrInfo.ignoreCount || 0;
-            var autoContinue = sourceCodeLocationOrInfo.autoContinue || false;
-            var actions = sourceCodeLocationOrInfo.actions || [];
-            for (var i = 0; i < actions.length; ++i)
-                actions[i] = new WI.BreakpointAction(this, actions[i]);
-            disabled = sourceCodeLocationOrInfo.disabled;
-            condition = sourceCodeLocationOrInfo.condition;
+        this._id = null;
+        this._sourceCodeLocation = sourceCodeLocation;
+
+        let sourceCode = this._sourceCodeLocation.sourceCode;
+        if (sourceCode) {
+            this._contentIdentifier = sourceCode.contentIdentifier;
+            console.assert(!contentIdentifier || contentIdentifier === this._contentIdentifier, "The content identifier from the source code should match the given value.");
         } else
         } else
-            console.error("Unexpected type passed to WI.Breakpoint", sourceCodeLocationOrInfo);
+            this._contentIdentifier = contentIdentifier || null;
+        console.assert(this._contentIdentifier || this._isSpecial(), "There should always be a content identifier for a breakpoint.");
 
 
-        this._id = null;
-        this._contentIdentifier = contentIdentifier || null;
-        this._scriptIdentifier = scriptIdentifier || null;
-        this._target = target || null;
+        this._scriptIdentifier = sourceCode instanceof WI.Script ? sourceCode.id : null;
+        this._target = sourceCode instanceof WI.Script ? sourceCode.target : null;
         this._disabled = disabled || false;
         this._condition = condition || "";
         this._ignoreCount = ignoreCount || 0;
         this._autoContinue = autoContinue || false;
         this._disabled = disabled || false;
         this._condition = condition || "";
         this._ignoreCount = ignoreCount || 0;
         this._autoContinue = autoContinue || false;
-        this._actions = actions || [];
+        this._actions = [];
         this._resolved = false;
 
         this._resolved = false;
 
-        this._sourceCodeLocation = location;
         this._sourceCodeLocation.addEventListener(WI.SourceCodeLocation.Event.LocationChanged, this._sourceCodeLocationLocationChanged, this);
         this._sourceCodeLocation.addEventListener(WI.SourceCodeLocation.Event.DisplayLocationChanged, this._sourceCodeLocationDisplayLocationChanged, this);
     }
 
         this._sourceCodeLocation.addEventListener(WI.SourceCodeLocation.Event.LocationChanged, this._sourceCodeLocationLocationChanged, this);
         this._sourceCodeLocation.addEventListener(WI.SourceCodeLocation.Event.DisplayLocationChanged, this._sourceCodeLocationDisplayLocationChanged, this);
     }
 
-    // Public
+    // Import / Export
 
 
-    get identifier()
+    static fromJSON(json)
     {
     {
-        return this._id;
+        const sourceCode = null;
+        let breakpoint = new Breakpoint(new WI.SourceCodeLocation(sourceCode, json.lineNumber || 0, json.columnNumber || 0), {
+            // The 'url' fallback is for transitioning from older frontends and should be removed.
+            contentIdentifier: json.contentIdentifier || json.url,
+            disabled: json.disabled,
+            condition: json.condition,
+            ignoreCount: json.ignoreCount,
+            autoContinue: json.autoContinue,
+        });
+        breakpoint._actions = json.actions.map((actionJSON) => WI.BreakpointAction.fromJSON(actionJSON, breakpoint));
+        return breakpoint;
     }
 
     }
 
-    set identifier(id)
+    toJSON(key)
     {
     {
-        this._id = id || null;
+        // The id, scriptIdentifier, target, and resolved state are tied to the current session, so don't include them for serialization.
+        let json = {
+            contentIdentifier: this._contentIdentifier,
+            lineNumber: this._sourceCodeLocation.lineNumber,
+            columnNumber: this._sourceCodeLocation.columnNumber,
+            disabled: this._disabled,
+            condition: this._condition,
+            ignoreCount: this._ignoreCount,
+            actions: this._actions.map((action) => action.toJSON()),
+            autoContinue: this._autoContinue,
+        };
+        if (key === WI.ObjectStore.toJSONSymbol)
+            json[WI.objectStores.breakpoints.keyPath] = this._contentIdentifier + ":" + this._sourceCodeLocation.lineNumber + ":" + this._sourceCodeLocation.columnNumber;
+        return json;
     }
 
     }
 
-    get contentIdentifier()
-    {
-        return this._contentIdentifier;
-    }
+    // Public
 
 
-    get scriptIdentifier()
-    {
-        return this._scriptIdentifier;
-    }
+    get sourceCodeLocation() { return this._sourceCodeLocation; }
+    get contentIdentifier() { return this._contentIdentifier; }
+    get scriptIdentifier() { return this._scriptIdentifier; }
+    get target() { return this._target; }
 
 
-    get target()
+    get identifier()
     {
     {
-        return this._target;
+        return this._id;
     }
 
     }
 
-    get sourceCodeLocation()
+    set identifier(id)
     {
     {
-        return this._sourceCodeLocation;
+        this._id = id || null;
     }
 
     get resolved()
     }
 
     get resolved()
@@ -109,12 +122,7 @@ WI.Breakpoint = class Breakpoint extends WI.Object
         if (this._resolved === resolved)
             return;
 
         if (this._resolved === resolved)
             return;
 
-        function isSpecialBreakpoint()
-        {
-            return this._sourceCodeLocation.isEqual(new WI.SourceCodeLocation(null, Infinity, Infinity));
-        }
-
-        console.assert(!resolved || this._sourceCodeLocation.sourceCode || isSpecialBreakpoint.call(this), "Breakpoints must have a SourceCode to be resolved.", this);
+        console.assert(!resolved || this._sourceCodeLocation.sourceCode || this._isSpecial(), "Breakpoints must have a SourceCode to be resolved.", this);
 
         this._resolved = resolved || false;
 
 
         this._resolved = resolved || false;
 
@@ -241,18 +249,18 @@ WI.Breakpoint = class Breakpoint extends WI.Object
 
     recreateAction(type, actionToReplace)
     {
 
     recreateAction(type, actionToReplace)
     {
-        var newAction = new WI.BreakpointAction(this, type, null);
-
-        var index = this._actions.indexOf(actionToReplace);
+        let index = this._actions.indexOf(actionToReplace);
         console.assert(index !== -1);
         if (index === -1)
             return null;
 
         console.assert(index !== -1);
         if (index === -1)
             return null;
 
-        this._actions[index] = newAction;
+        const data = null;
+        let action = new WI.BreakpointAction(this, type, data);
+        this._actions[index] = action;
 
         this.dispatchEventToListeners(WI.Breakpoint.Event.ActionsDidChange);
 
 
         this.dispatchEventToListeners(WI.Breakpoint.Event.ActionsDidChange);
 
-        return newAction;
+        return action;
     }
 
     removeAction(action)
     }
 
     removeAction(action)
@@ -282,34 +290,9 @@ WI.Breakpoint = class Breakpoint extends WI.Object
 
     saveIdentityToCookie(cookie)
     {
 
     saveIdentityToCookie(cookie)
     {
-        cookie["breakpoint-content-identifier"] = this.contentIdentifier;
-        cookie["breakpoint-line-number"] = this.sourceCodeLocation.lineNumber;
-        cookie["breakpoint-column-number"] = this.sourceCodeLocation.columnNumber;
-    }
-
-    serializeOptions()
-    {
-        return {
-            condition: this._condition,
-            ignoreCount: this._ignoreCount,
-            actions: this._actions.map((action) => action.toJSON()),
-            autoContinue: this._autoContinue,
-        };
-    }
-
-    toJSON(key)
-    {
-        // The id, scriptIdentifier, target, and resolved state are tied to the current session, so don't include them for serialization.
-        let json = {
-            contentIdentifier: this._contentIdentifier,
-            lineNumber: this._sourceCodeLocation.lineNumber,
-            columnNumber: this._sourceCodeLocation.columnNumber,
-            disabled: this._disabled,
-            ...this.serializeOptions(),
-        };
-        if (key === WI.ObjectStore.toJSONSymbol)
-            json[WI.objectStores.breakpoints.keyPath] = this._contentIdentifier + ":" + this._sourceCodeLocation.lineNumber + ":" + this._sourceCodeLocation.columnNumber;
-        return json;
+        cookie["breakpoint-content-identifier"] = this._contentIdentifier;
+        cookie["breakpoint-line-number"] = this._sourceCodeLocation.lineNumber;
+        cookie["breakpoint-column-number"] = this._sourceCodeLocation.columnNumber;
     }
 
     // Protected (Called by BreakpointAction)
     }
 
     // Protected (Called by BreakpointAction)
@@ -326,6 +309,11 @@ WI.Breakpoint = class Breakpoint extends WI.Object
 
     // Private
 
 
     // Private
 
+    _isSpecial()
+    {
+        return this._sourceCodeLocation.isEqual(new WI.SourceCodeLocation(null, Infinity, Infinity));
+    }
+
     _sourceCodeLocationLocationChanged(event)
     {
         this.dispatchEventToListeners(WI.Breakpoint.Event.LocationDidChange, event.data);
     _sourceCodeLocationLocationChanged(event)
     {
         this.dispatchEventToListeners(WI.Breakpoint.Event.LocationDidChange, event.data);
index 2034615..d8be7f5 100644 (file)
 
 WI.BreakpointAction = class BreakpointAction
 {
 
 WI.BreakpointAction = class BreakpointAction
 {
-    constructor(breakpoint, typeOrInfo, data)
+    constructor(breakpoint, type, data)
     {
     {
-        console.assert(breakpoint);
-        console.assert(typeOrInfo);
+        console.assert(breakpoint instanceof WI.Breakpoint);
+        console.assert(Object.values(WI.BreakpointAction.Type).includes(type));
 
         this._breakpoint = breakpoint;
 
         this._breakpoint = breakpoint;
+        this._type = type;
+        this._data = data || null;
+        this._id = WI.debuggerManager.nextBreakpointActionIdentifier();
+    }
 
 
-        if (typeof typeOrInfo === "string") {
-            this._type = typeOrInfo;
-            this._data = data || null;
-        } else if (typeof typeOrInfo === "object") {
-            this._type = typeOrInfo.type;
-            this._data = typeOrInfo.data || null;
-        } else
-            console.error("Unexpected type passed to WI.BreakpointAction");
+    // Import / Export
 
 
-        console.assert(typeof this._type === "string");
-        this._id = WI.debuggerManager.nextBreakpointActionIdentifier();
+    static fromJSON(json, breakpoint)
+    {
+        return new BreakpointAction(breakpoint, json.type, json.data);
+    }
+
+    toJSON()
+    {
+        let json = {
+            type: this._type,
+        };
+        if (this._data)
+            json.data = this._data;
+        return json;
     }
 
     // Public
     }
 
     // Public
@@ -66,14 +74,10 @@ WI.BreakpointAction = class BreakpointAction
         this._breakpoint.breakpointActionDidChange(this);
     }
 
         this._breakpoint.breakpointActionDidChange(this);
     }
 
-    toJSON()
+    toProtocol()
     {
     {
-        let json = {
-            type: this._type,
-            id: this._id,
-        };
-        if (this._data)
-            json.data = this._data;
+        let json = this.toJSON();
+        json.id = this._id;
         return json;
     }
 };
         return json;
     }
 };
index fc82144..8c1c56b 100644 (file)
@@ -560,9 +560,8 @@ WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSideba
 
     _addBreakpointsForSourceCode(sourceCode)
     {
 
     _addBreakpointsForSourceCode(sourceCode)
     {
-        var breakpoints = WI.debuggerManager.breakpointsForSourceCode(sourceCode);
-        for (var i = 0; i < breakpoints.length; ++i)
-            this._addBreakpoint(breakpoints[i], sourceCode);
+        for (let breakpoint of WI.debuggerManager.breakpointsForSourceCode(sourceCode))
+            this._addBreakpoint(breakpoint, sourceCode);
     }
 
     _addIssuesForSourceCode(sourceCode)
     }
 
     _addIssuesForSourceCode(sourceCode)
index b227400..9ee9df4 100644 (file)
@@ -499,9 +499,7 @@ WI.SourceCodeTextEditor = class SourceCodeTextEditor extends WI.TextEditor
         if (this._supportsDebugging) {
             this._breakpointMap = {};
 
         if (this._supportsDebugging) {
             this._breakpointMap = {};
 
-            var breakpoints = WI.debuggerManager.breakpointsForSourceCode(this._sourceCode);
-            for (var i = 0; i < breakpoints.length; ++i) {
-                var breakpoint = breakpoints[i];
+            for (let breakpoint of WI.debuggerManager.breakpointsForSourceCode(this._sourceCode)) {
                 console.assert(this._matchesBreakpoint(breakpoint));
                 var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
                 this._addBreakpointWithEditorLineInfo(breakpoint, lineInfo);
                 console.assert(this._matchesBreakpoint(breakpoint));
                 var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
                 this._addBreakpointWithEditorLineInfo(breakpoint, lineInfo);
@@ -562,8 +560,7 @@ WI.SourceCodeTextEditor = class SourceCodeTextEditor extends WI.TextEditor
     {
         console.assert(this._supportsDebugging);
 
     {
         console.assert(this._supportsDebugging);
 
-        var breakpoints = WI.debuggerManager.breakpointsForSourceCode(this._sourceCode);
-        for (var breakpoint of breakpoints)
+        for (let breakpoint of WI.debuggerManager.breakpointsForSourceCode(this._sourceCode))
             this._updateBreakpointStatus(breakpoint);
     }
 
             this._updateBreakpointStatus(breakpoint);
     }