⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 112064 in webkit


Ignore:
Timestamp:
Mar 26, 2012, 1:56:30 AM (15 years ago)
Author:
pfeldman@chromium.org
Message:

Web Inspector: breakpoints should be disabled while live editing JavaScript.
​https://bugs.webkit.org/show_bug.cgi?id=81947

Reviewed by Yury Semikhatsky.

Source/WebCore:

This change disables (removes from the backend) the breakpoints while editing script.
Undoing or committing the change restores the breakpoints. Main logic is implemented within
JavaScriptSourceFrame, but it required minor tweaking of the text editor: more correct
undo/redo wrapper and better detection of the noop opterations.

  • inspector/front-end/JavaScriptSourceFrame.js:

(WebInspector.JavaScriptSourceFrame):
(WebInspector.JavaScriptSourceFrame.prototype.afterTextChanged):
(WebInspector.JavaScriptSourceFrame.prototype.beforeTextChanged):
(WebInspector.JavaScriptSourceFrame.prototype.didEditContent):
(WebInspector.JavaScriptSourceFrame.prototype.addBreakpoint):
(WebInspector.JavaScriptSourceFrame.prototype.removeBreakpoint):
(WebInspector.JavaScriptSourceFrame.prototype._onMouseDown):

  • inspector/front-end/TextEditorModel.js:

(WebInspector.TextEditorModel.endsWithBracketRegex.):

  • inspector/front-end/TextViewer.js:

(WebInspector.TextEditorMainPanel.prototype.handleUndoRedo.before):
(WebInspector.TextEditorMainPanel.prototype.handleUndoRedo.after):
(WebInspector.TextEditorMainPanel.prototype.handleUndoRedo):
(WebInspector.TextEditorMainPanel.prototype._applyDomUpdates):

LayoutTests:

  • inspector/editor/highlighter-basics-expected.txt:
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r112063 r112064  
     12012-03-26  Pavel Feldman  <pfeldman@chromium.org>
     2
     3        Web Inspector: breakpoints should be disabled while live editing JavaScript.
     4        https://bugs.webkit.org/show_bug.cgi?id=81947
     5
     6        Reviewed by Yury Semikhatsky.
     7
     8        * inspector/editor/highlighter-basics-expected.txt:
     9
    1102012-03-26  Csaba Osztrogonác  <ossy@webkit.org>
    211
  • trunk/LayoutTests/inspector/editor/highlighter-basics-expected.txt

    r80704 r112064  
    34342 :  * line #1 : javascript-comment[0-10]
    35353 :  * line #2 : javascript-comment[0-10]
    36 4 : /** : javascript-comment[0-10]
     364 : /** : null
    37375 :  * line #1 : null
    38386 :  * line #2 : null
    … …  
    454513 :  * var a = new A(); //*/ : null
    464614 : some text : null
    47 15 :  * line #6 : null
     4715 :  * line #6 : javascript-comment[0-10]
    484816 :  * line #7 : javascript-comment[0-10]
    494917 :  * line #8 : javascript-comment[0-10]
  • trunk/Source/WebCore/ChangeLog

    r112059 r112064  
     12012-03-26  Pavel Feldman  <pfeldman@chromium.org>
     2
     3        Web Inspector: breakpoints should be disabled while live editing JavaScript.
     4        https://bugs.webkit.org/show_bug.cgi?id=81947
     5
     6        Reviewed by Yury Semikhatsky.
     7
     8        This change disables (removes from the backend) the breakpoints while editing script.
     9        Undoing or committing the change restores the breakpoints. Main logic is implemented within
     10        JavaScriptSourceFrame, but it required minor tweaking of the text editor: more correct
     11        undo/redo wrapper and better detection of the noop opterations.
     12
     13        * inspector/front-end/JavaScriptSourceFrame.js:
     14        (WebInspector.JavaScriptSourceFrame):
     15        (WebInspector.JavaScriptSourceFrame.prototype.afterTextChanged):
     16        (WebInspector.JavaScriptSourceFrame.prototype.beforeTextChanged):
     17        (WebInspector.JavaScriptSourceFrame.prototype.didEditContent):
     18        (WebInspector.JavaScriptSourceFrame.prototype.addBreakpoint):
     19        (WebInspector.JavaScriptSourceFrame.prototype.removeBreakpoint):
     20        (WebInspector.JavaScriptSourceFrame.prototype._onMouseDown):
     21        * inspector/front-end/TextEditorModel.js:
     22        (WebInspector.TextEditorModel.endsWithBracketRegex.):
     23        * inspector/front-end/TextViewer.js:
     24        (WebInspector.TextEditorMainPanel.prototype.handleUndoRedo.before):
     25        (WebInspector.TextEditorMainPanel.prototype.handleUndoRedo.after):
     26        (WebInspector.TextEditorMainPanel.prototype.handleUndoRedo):
     27        (WebInspector.TextEditorMainPanel.prototype._applyDomUpdates):
     28
    1292012-03-25  Nat Duca  <nduca@chromium.org>
    230
  • trunk/Source/WebCore/inspector/front-end/JavaScriptSourceFrame.js

    r111682 r112064  
    4141    this._model = model;
    4242    this._uiSourceCode = uiSourceCode;
    43     this._breakpoints = {};
    4443
    4544    WebInspector.SourceFrame.call(this, uiSourceCode.url);
    … …  
    111110            function addConditionalBreakpoint()
    112111            {
    113                 this.addBreakpoint(lineNumber, true, true, true);
     112                this.addBreakpoint(lineNumber, true, true, true, false);
    114113                function didEditBreakpointCondition(committed, condition)
    115114                {
    … …  
    160159    afterTextChanged: function(oldRange, newRange)
    161160    {
    162         if (!oldRange || !newRange)
    163             return;
    164 
    165         // Adjust execution line number.
    166         if (typeof this._executionLineNumber === "number") {
    167             var newExecutionLineNumber = this._lineNumberAfterEditing(this._executionLineNumber, oldRange, newRange);
    168             this.clearExecutionLine();
    169             this.setExecutionLine(newExecutionLineNumber);
    170         }
    171 
    172         // Adjust breakpoints.
    173         var oldBreakpoints = this._breakpoints;
    174         this._breakpoints = {};
    175         for (var lineNumber in oldBreakpoints) {
    176             lineNumber = Number(lineNumber);
    177             var breakpoint = oldBreakpoints[lineNumber];
    178             var newLineNumber = this._lineNumberAfterEditing(lineNumber, oldRange, newRange);
    179             if (lineNumber === newLineNumber)
    180                 this._breakpoints[lineNumber] = breakpoint;
    181             else {
    182                 this.removeBreakpoint(lineNumber);
    183                 this.addBreakpoint(newLineNumber, breakpoint.resolved, breakpoint.conditional, breakpoint.enabled);
    184             }
    185         }
    186 
    187         this._scriptsPanel.setScriptSourceIsDirty(this._uiSourceCode, this.textModel.copyRange() !== this._originalContent);
     161        var isDirty = this.textModel.copyRange() !== this._originalContent;
     162        if (isDirty)
     163            this._scriptsPanel.setScriptSourceIsDirty(this._uiSourceCode, true);
     164        else
     165            this.didEditContent(null, this._originalContent);
    188166    },
    189167
    190168    beforeTextChanged: function()
    191169    {
    192         if (!this._javaScriptSourceFrameState) {
    193             this._javaScriptSourceFrameState = {
    194                 executionLineNumber: this._executionLineNumber,
    195                 breakpoints: this._breakpoints
    196             }
    197         }
     170        if (!this._isDirty) {
     171            // Disable all breakpoints in the model, store them as muted breakpoints.
     172            for (var lineNumber = 0; lineNumber < this.textModel.linesCount; ++lineNumber) {
     173                var breakpoint = this.textModel.getAttribute(lineNumber, "breakpoint");
     174                if (breakpoint) {
     175                    this._model.removeBreakpoint(this._uiSourceCode, lineNumber);
     176                    // Re-adding decoration only.
     177                    this.addBreakpoint(lineNumber, breakpoint.resolved, breakpoint.conditional, breakpoint.enabled, true);
     178                }
     179            }
     180        }
     181
     182        this._isDirty = true;
    198183        WebInspector.SourceFrame.prototype.beforeTextChanged.call(this);
    199184    },
    … …  
    202187    {
    203188        delete this._editingContent;
     189
    204190        WebInspector.SourceFrame.prototype.didEditContent.call(this, error, content);
    205191        if (error)
    … …  
    207193
    208194        this._originalContent = content;
    209         var newBreakpoints = {};
    210         for (var lineNumber in this._breakpoints) {
    211             newBreakpoints[lineNumber] = this._breakpoints[lineNumber];
    212             this.removeBreakpoint(Number(lineNumber));
    213         }
    214 
    215         for (var lineNumber in this._javaScriptSourceFrameState.breakpoints)
    216             this._model.removeBreakpoint(this._uiSourceCode, Number(lineNumber));
    217 
    218         for (var lineNumber in newBreakpoints) {
    219             var breakpoint = newBreakpoints[lineNumber];
    220             this._setBreakpoint(Number(lineNumber), breakpoint.condition, breakpoint.enabled);
     195        this._isDirty = false;
     196
     197        // Restore all muted breakpoints.
     198        for (var lineNumber = 0; lineNumber < this.textModel.linesCount; ++lineNumber) {
     199            var breakpoint = this.textModel.getAttribute(lineNumber, "breakpoint");
     200            if (breakpoint) {
     201                // Remove fake decoration
     202                this.removeBreakpoint(lineNumber);
     203                // Set new breakpoint
     204                this._setBreakpoint(lineNumber, breakpoint.condition, breakpoint.enabled);
     205            }
    221206        }
    222207        this._scriptsPanel.setScriptSourceIsDirty(this._uiSourceCode, false);
    223         delete this._javaScriptSourceFrameState;
    224208    },
    225209
    … …  
    333317    },
    334318
    335     addBreakpoint: function(lineNumber, resolved, conditional, enabled)
    336     {
    337         this._breakpoints[lineNumber] = {
     319    addBreakpoint: function(lineNumber, resolved, conditional, enabled, mutedWhileEditing)
     320    {
     321        var breakpoint = {
    338322            resolved: resolved,
    339323            conditional: conditional,
    340324            enabled: enabled
    341325        };
     326        this.textModel.setAttribute(lineNumber, "breakpoint", breakpoint);
     327
    342328        this.textViewer.beginUpdates();
    343329        this.textViewer.addDecoration(lineNumber, "webkit-breakpoint");
    344         if (!enabled)
     330        if (!enabled || mutedWhileEditing)
    345331            this.textViewer.addDecoration(lineNumber, "webkit-breakpoint-disabled");
    346332        if (conditional)
    … …  
    351337    removeBreakpoint: function(lineNumber)
    352338    {
    353         delete this._breakpoints[lineNumber];
     339        this.textModel.removeAttribute(lineNumber, "breakpoint");
    354340        this.textViewer.beginUpdates();
    355341        this.textViewer.removeDecoration(lineNumber, "webkit-breakpoint");
    … …  
    367353    _onMouseDown: function(event)
    368354    {
     355        if (this._isDirty)
     356            return;
     357
    369358        if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey)
    370359            return;
  • trunk/Source/WebCore/inspector/front-end/TextEditorModel.js

    r111675 r112064  
    161161        } else {
    162162            this._setLine(range.startLine, prefix + newLines[0]);
     163
    163164            for (var i = 1; i < newLines.length; ++i)
    164                 this._insertLine(range.startLine + i, newLines[i]);
     165                this._lines.splice(range.startLine + i, 0, newLines[i]);
     166            // Adjust attributes, attributes move with the first character of line.
     167            var spliceParameters = new Array(newLines.length + 1); // 2 + number of items to insert.
     168            spliceParameters[0] = range.startColumn ? range.startLine + 1 : range.startLine;
     169            spliceParameters[1] = 0;
     170            this._attributes.splice.apply(this._attributes, spliceParameters);
     171
    165172            this._setLine(range.startLine + newLines.length - 1, newLines[newLines.length - 1] + suffix);
    166173            postCaret = newLines[newLines.length - 1].length;
    167174        }
     175
    168176        return new WebInspector.TextRange(range.startLine, range.startColumn,
    169177                                          range.startLine + newLines.length - 1, postCaret);
    … …  
    178186        var suffix = this._lines[range.endLine].substring(range.endColumn);
    179187
    180         if (range.endLine > range.startLine)
    181             this._removeLines(range.startLine + 1, range.endLine - range.startLine);
     188        if (range.endLine > range.startLine) {
     189            this._lines.splice(range.startLine + 1, range.endLine - range.startLine);
     190            // Adjust attributes, attributes move with the first character of line.
     191            this._attributes.splice(range.startColumn ? range.startLine + 1 : range.startLine, range.endLine - range.startLine);
     192        }
    182193        this._setLine(range.startLine, prefix + suffix);
    183194    },
    … …  
    186197    {
    187198        this._lines[lineNumber] = text;
    188     },
    189 
    190     _removeLines: function(fromLine, count)
    191     {
    192         this._lines.splice(fromLine, count);
    193         this._attributes.splice(fromLine, count);
    194     },
    195 
    196     _insertLine: function(lineNumber, text)
    197     {
    198         this._lines.splice(lineNumber, 0, text);
    199         this._attributes.splice(lineNumber, 0, {});
    200199    },
    201200
    … …  
    283282    },
    284283
    285     undo: function(callback)
     284    undo: function(beforeCallback, afterCallback)
    286285    {
    287286        this._markRedoableState();
    288287
    289288        this._inUndo = true;
    290         var range = this._doUndo(this._undoStack, callback);
     289        var range = this._doUndo(this._undoStack, beforeCallback, afterCallback);
    291290        delete this._inUndo;
    292291
    … …  
    294293    },
    295294
    296     redo: function(callback)
     295    redo: function(beforeCallback, afterCallback)
    297296    {
    298297        this.markUndoableState();
    299298
    300299        this._inRedo = true;
    301         var range = this._doUndo(this._redoStack, callback);
     300        var range = this._doUndo(this._redoStack, beforeCallback, afterCallback);
    302301        delete this._inRedo;
    303302
    … …  
    305304    },
    306305
    307     _doUndo: function(stack, callback)
     306    _doUndo: function(stack, beforeCallback, afterCallback)
    308307    {
    309308        var range = null;
    … …  
    312311            stack.length = i;
    313312
     313            if (beforeCallback)
     314                beforeCallback();
     315
    314316            range = this.setText(command.range, command.text);
    315             if (callback)
    316                 callback(command.range, range);
     317
     318            if (afterCallback)
     319                afterCallback(command.range, range);
     320
    317321            if (i > 0 && stack[i - 1].explicit)
    318322                return range;
  • trunk/Source/WebCore/inspector/front-end/TextViewer.js

    r112053 r112064  
    10701070
    10711071        this.beginUpdates();
    1072         this._enterTextChangeMode();
    1073 
    1074         function callback(oldRange, newRange)
     1072
     1073        function before()
     1074        {
     1075            this._enterTextChangeMode();
     1076        }
     1077
     1078        function after(oldRange, newRange)
    10751079        {
    10761080            this._exitTextChangeMode(oldRange, newRange);
    1077             this._enterTextChangeMode();
    1078         }
    1079         var range = redo ? this._textModel.redo(callback.bind(this)) : this._textModel.undo(callback.bind(this));
    1080         this._exitTextChangeMode(null, null);
     1081        }
     1082
     1083        var range = redo ? this._textModel.redo(before.bind(this), after.bind(this)) : this._textModel.undo(before.bind(this), after.bind(this));
     1084
    10811085        this.endUpdates();
    10821086
    … …  
    17551759        }
    17561760
    1757         // This is a "foreign" call outside of this class. Should be before we delete the dirty lines flag.
    1758         this._enterTextChangeMode();
    1759 
    17601761        var dirtyLines = this._dirtyLines;
    1761         delete this._dirtyLines;
    17621762
    17631763        var firstChunkNumber = this._chunkNumberForLine(dirtyLines.start);
    … …  
    18371837            var oldRange = new WebInspector.TextRange(startLine, startColumn, endLine - 1, endColumn);
    18381838
    1839         var newRange = this._setText(oldRange, lines.join("\n"));
     1839        var newContent = lines.join("\n");
     1840        if (this._textModel.copyRange(oldRange) === newContent) {
     1841            delete this._dirtyLines;
     1842            return; // Noop
     1843        }
     1844
     1845        // This is a "foreign" call outside of this class. Should be before we delete the dirty lines flag.
     1846        this._enterTextChangeMode();
     1847
     1848        delete this._dirtyLines;
     1849
     1850        var newRange = this._setText(oldRange, newContent);
    18401851
    18411852        this._paintScheduledLines(true);
Note: See TracChangeset for help on using the changeset viewer.