Changeset 76341 in webkit


Ignore:
Timestamp:
Jan 21, 2011 3:59:29 AM (13 years ago)
Author:
podivilov@chromium.org
Message:

2011-01-12 Pavel Podivilov <podivilov@chromium.org>

Reviewed by Pavel Feldman.

Web Inspector: breakpoints are restored incorrectly when reverting live edit.
https://bugs.webkit.org/show_bug.cgi?id=52300

Fix breakpoints restoring when reverting to old revision by using text diff.
Move live edit logic from ScriptsPanel to DebuggerModel.
Eliminate unnecessary editLine delegate in TextViewer.

Location:
trunk/Source/WebCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r76340 r76341  
     12011-01-12  Pavel Podivilov  <podivilov@chromium.org>
     2
     3        Reviewed by Pavel Feldman.
     4
     5        Web Inspector: breakpoints are restored incorrectly when reverting live edit.
     6        https://bugs.webkit.org/show_bug.cgi?id=52300
     7
     8        Fix breakpoints restoring when reverting to old revision by using text diff.
     9        Move live edit logic from ScriptsPanel to DebuggerModel.
     10        Eliminate unnecessary editLine delegate in TextViewer.
     11
     12        * inspector/front-end/DebuggerModel.js:
     13        (WebInspector.DebuggerModel):
     14        (WebInspector.DebuggerModel.prototype.reset):
     15        (WebInspector.DebuggerModel.prototype.editScriptSource):
     16        (WebInspector.DebuggerModel.prototype._updateScriptSource):
     17        (WebInspector.DebuggerModel.prototype.get callFrames):
     18        (WebInspector.DebuggerModel.prototype.pausedScript):
     19        (WebInspector.DebuggerModel.prototype.resumedScript):
     20        * inspector/front-end/Script.js:
     21        (WebInspector.Script.prototype.get source):
     22        * inspector/front-end/ScriptView.js:
     23        (WebInspector.ScriptView):
     24        * inspector/front-end/ScriptsPanel.js:
     25        (WebInspector.ScriptsPanel):
     26        (WebInspector.ScriptsPanel.prototype._scriptSourceChanged):
     27        * inspector/front-end/SourceFrame.js:
     28        (WebInspector.SourceFrame):
     29        (WebInspector.SourceFrame.prototype._createViewerIfNeeded):
     30        (WebInspector.SourceFrame.prototype._doubleClick.didEditLine):
     31        (WebInspector.SourceFrame.prototype._doubleClick):
     32        * inspector/front-end/SourceView.js:
     33        (WebInspector.SourceView):
     34        * inspector/front-end/TextViewer.js:
     35        (WebInspector.TextViewer):
     36        (WebInspector.TextViewer.prototype._handleKeyDown):
     37        (WebInspector.TextViewer.prototype.editLine.finishEditing):
     38        (WebInspector.TextViewer.prototype.editLine):
     39        (WebInspector.TextChunk.prototype._createRow):
     40
    1412011-01-21  Adam Klein  <adamk@chromium.org>
    242
  • trunk/Source/WebCore/inspector/front-end/DebuggerModel.js

    r76239 r76341  
    3232{
    3333    this._paused = false;
     34    this._callFrames = [];
    3435    this._breakpoints = {};
    3536    this._sourceIDAndLineToBreakpointId = {};
     
    4445    ParsedScriptSource: "parsed-script-source",
    4546    FailedToParseScriptSource: "failed-to-parse-script-source",
     47    ScriptSourceChanged: "script-source-changed",
    4648    BreakpointAdded: "breakpoint-added",
    4749    BreakpointRemoved: "breakpoint-removed"
     
    136138    {
    137139        this._paused = false;
     140        this._callFrames = [];
    138141        this._breakpoints = {};
    139142        delete this._oneTimeBreakpoint;
     
    163166    },
    164167
     168    editScriptSource: function(sourceID, scriptSource)
     169    {
     170        function didEditScriptSource(success, newBodyOrErrorMessage, callFrames)
     171        {
     172            if (success) {
     173                if (callFrames && callFrames.length)
     174                    this._callFrames = callFrames;
     175                this._updateScriptSource(sourceID, newBodyOrErrorMessage);
     176            } else
     177                WebInspector.log(newBodyOrErrorMessage, WebInspector.ConsoleMessage.MessageLevel.Warning);
     178        }
     179        InspectorBackend.editScriptSource(sourceID, scriptSource, didEditScriptSource.bind(this));
     180    },
     181
     182    _updateScriptSource: function(sourceID, scriptSource)
     183    {
     184        var script = this._scripts[sourceID];
     185        var oldSource = script.source;
     186        script.source = scriptSource;
     187
     188        // Clear and re-create breakpoints according to text diff.
     189        var diff = Array.diff(oldSource.split("\n"), script.source.split("\n"));
     190        for (var id in this._breakpoints) {
     191            var breakpoint = this._breakpoints[id];
     192            if (breakpoint.sourceID !== sourceID)
     193                continue;
     194            breakpoint.remove();
     195            var lineNumber = breakpoint.line - 1;
     196            var newLineNumber = diff.left[lineNumber].row;
     197            if (newLineNumber === undefined) {
     198                for (var i = lineNumber - 1; i >= 0; --i) {
     199                    if (diff.left[i].row === undefined)
     200                        continue;
     201                    var shiftedLineNumber = diff.left[i].row + lineNumber - i;
     202                    if (shiftedLineNumber < diff.right.length) {
     203                        var originalLineNumber = diff.right[shiftedLineNumber].row;
     204                        if (originalLineNumber === lineNumber || originalLineNumber === undefined)
     205                            newLineNumber = shiftedLineNumber;
     206                    }
     207                    break;
     208                }
     209            }
     210            if (newLineNumber !== undefined)
     211                this.setBreakpoint(sourceID, newLineNumber + 1, breakpoint.enabled, breakpoint.condition);
     212        }
     213
     214        this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ScriptSourceChanged, { sourceID: sourceID, oldSource: oldSource });
     215    },
     216
     217    get callFrames()
     218    {
     219        return this._callFrames;
     220    },
     221
    165222    _pausedScript: function(details)
    166223    {
    167224        this._paused = true;
     225        this._callFrames = details.callFrames;
    168226        if ("_continueToLineBreakpointId" in this) {
    169227            InspectorBackend.removeBreakpoint(this._continueToLineBreakpointId);
     
    176234    {
    177235        this._paused = false;
     236        this._callFrames = [];
    178237        this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed);
    179238    },
  • trunk/Source/WebCore/inspector/front-end/Script.js

    r76026 r76341  
    9898    get source()
    9999    {
     100        if (!this._source && this.resource)
     101            this._source = this.resource.content;
    100102        return this._source;
    101103    },
     
    104106    {
    105107        this._source = source;
     108        delete this._lineEndings;
    106109    },
    107110
  • trunk/Source/WebCore/inspector/front-end/ScriptView.js

    r75937 r76341  
    3131
    3232    var contentProvider = new WebInspector.SourceFrameContentProviderForScript(script);
    33     this.sourceFrame = new WebInspector.SourceFrame(this.element, contentProvider, "", WebInspector.panels.scripts.canEditScripts());
     33    this.sourceFrame = new WebInspector.SourceFrame(this.element, contentProvider, "", true);
    3434}
    3535
  • trunk/Source/WebCore/inspector/front-end/ScriptsPanel.js

    r76239 r76341  
    187187    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
    188188    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._failedToParseScriptSource, this);
     189    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ScriptSourceChanged, this._scriptSourceChanged, this);
    189190    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
    190191    WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
     
    250251    {
    251252        this._addScript(event.data);
     253    },
     254
     255    _scriptSourceChanged: function(event)
     256    {
     257        var sourceID = event.data.sourceID;
     258        var oldSource = event.data.oldSource;
     259
     260        var script = WebInspector.debuggerModel.scriptForSourceID(sourceID);
     261        var oldView = script._scriptView;
     262        if (oldView) {
     263            script._scriptView = new WebInspector.ScriptView(script);
     264            this.viewRecreated(oldView, script._scriptView);
     265        }
     266        if (script.resource) {
     267            var revertHandle = WebInspector.debuggerModel.editScriptSource.bind(WebInspector.debuggerModel, sourceID, oldSource);
     268            script.resource.setContent(script.source, revertHandle);
     269        }
     270
     271        var callFrames = WebInspector.debuggerModel.callFrames;
     272        if (callFrames.length)
     273            this._debuggerPaused({ data: { callFrames: callFrames } });
    252274    },
    253275
     
    285307        this._addScriptToFilesMenu(resource._scriptsPendingResourceLoad[0]);
    286308        delete resource._scriptsPendingResourceLoad;
    287     },
    288 
    289     canEditScripts: function()
    290     {
    291         return Preferences.canEditScriptSource;
    292     },
    293 
    294     editScriptSource: function(editData, revertEditingCallback, cancelEditingCallback)
    295     {
    296         if (!this.canEditScripts())
    297             return;
    298 
    299         // Need to clear breakpoints and re-create them later when editing source.
    300         var breakpoints = WebInspector.debuggerModel.queryBreakpoints(function(b) { return b.sourceID === editData.sourceID });
    301         for (var i = 0; i < breakpoints.length; ++i)
    302             breakpoints[i].remove();
    303 
    304         function mycallback(success, newBodyOrErrorMessage, callFrames)
    305         {
    306             if (success) {
    307                 var script = WebInspector.debuggerModel.scriptForSourceID(editData.sourceID);
    308                 script.source = newBodyOrErrorMessage;
    309                 var oldView = script._scriptView
    310                 if (oldView) {
    311                     script._scriptView = new WebInspector.ScriptView(script);
    312                     this.viewRecreated(oldView, script._scriptView);
    313                 }
    314                 if (script.resource)
    315                     script.resource.setContent(newBodyOrErrorMessage, revertEditingCallback);
    316 
    317                 if (callFrames && callFrames.length)
    318                     this._debuggerPaused({ data: { callFrames: callFrames } });
    319             } else {
    320                 if (cancelEditingCallback)
    321                     cancelEditingCallback();
    322                 WebInspector.log(newBodyOrErrorMessage, WebInspector.ConsoleMessage.MessageLevel.Warning);
    323             }
    324             for (var i = 0; i < breakpoints.length; ++i) {
    325                 var breakpoint = breakpoints[i];
    326                 var newLine = breakpoint.line;
    327                 if (success && breakpoint.line >= editData.line)
    328                     newLine += editData.linesCountToShift;
    329                 WebInspector.debuggerModel.setBreakpoint(editData.sourceID, newLine, breakpoint.enabled, breakpoint.condition);
    330             }
    331         };
    332         InspectorBackend.editScriptSource(editData.sourceID, editData.content, mycallback.bind(this));
    333309    },
    334310
  • trunk/Source/WebCore/inspector/front-end/SourceFrame.js

    r76132 r76341  
    2929 */
    3030
    31 WebInspector.SourceFrame = function(parentElement, contentProvider, url, canEditScripts)
     31WebInspector.SourceFrame = function(parentElement, contentProvider, url, isScript)
    3232{
    3333    this._parentElement = parentElement;
    3434    this._contentProvider = contentProvider;
    3535    this._url = url;
    36     this._canEditScripts = canEditScripts;
     36    this._isScript = isScript;
     37
    3738
    3839    this._textModel = new WebInspector.TextEditorModel();
     
    164165        element.addEventListener("mousemove", this._mouseMove.bind(this), true);
    165166        element.addEventListener("scroll", this._scroll.bind(this), true);
     167        element.addEventListener("dblclick", this._doubleClick.bind(this), true);
    166168        this._parentElement.appendChild(element);
    167169
     
    803805    },
    804806
    805     _editLine: function(lineNumber, newContent, cancelEditingCallback)
    806     {
    807         var lines = [];
    808         var oldLines = this._content.split('\n');
    809         for (var i = 0; i < oldLines.length; ++i) {
    810             if (i === lineNumber)
    811                 lines.push(newContent);
    812             else
    813                 lines.push(oldLines[i]);
    814         }
    815 
    816         var editData = {};
    817         editData.sourceID = this._sourceIDForLine(lineNumber);
    818         editData.content = lines.join("\n");
    819         editData.line = lineNumber + 1;
    820         editData.linesCountToShift = newContent.split("\n").length - 1;
    821         this._doEditLine(editData, cancelEditingCallback);
    822     },
    823 
    824     _revertEditLine: function(editData, contentToRevertTo)
    825     {
    826         var newEditData = {};
    827         newEditData.sourceID = editData.sourceID;
    828         newEditData.content = contentToRevertTo;
    829         newEditData.line = editData.line;
    830         newEditData.linesCountToShift = -editData.linesCountToShift;
    831         this._doEditLine(newEditData);
    832     },
    833 
    834     _doEditLine: function(editData, cancelEditingCallback)
    835     {
    836         var revertEditingCallback = this._revertEditLine.bind(this, editData);
    837         WebInspector.panels.scripts.editScriptSource(editData, revertEditingCallback, cancelEditingCallback);
     807    _doubleClick: function(event)
     808    {
     809        if (!Preferences.canEditScriptSource || !this._isScript)
     810            return;
     811
     812        var target = event.target.enclosingNodeOrSelfWithNodeName("TD");
     813        if (!target || target.parentElement.firstChild === target)
     814            return;  // Do not trigger editing from line numbers.
     815
     816        var lineRow = target.parentElement;
     817        var lineNumber = lineRow.lineNumber;
     818        var sourceID = this._sourceIDForLine(lineNumber);
     819        if (!sourceID)
     820            return;
     821
     822        function didEditLine(newContent)
     823        {
     824            var lines = [];
     825            var oldLines = this._content.split('\n');
     826            for (var i = 0; i < oldLines.length; ++i) {
     827                if (i === lineNumber)
     828                    lines.push(newContent);
     829                else
     830                    lines.push(oldLines[i]);
     831            }
     832            WebInspector.debuggerModel.editScriptSource(sourceID, lines.join("\n"));
     833        }
     834        this._textViewer.editLine(lineRow, didEditLine.bind(this));
    838835    },
    839836
  • trunk/Source/WebCore/inspector/front-end/SourceView.js

    r75937 r76341  
    3434
    3535    var contentProvider = new WebInspector.SourceFrameContentProviderForResource(resource);
    36     var canEditScripts = WebInspector.panels.scripts.canEditScripts() && resource.type === WebInspector.Resource.Type.Script;
    37     this.sourceFrame = new WebInspector.SourceFrame(this.element, contentProvider, resource.url, canEditScripts);
     36    var isScript = resource.type === WebInspector.Resource.Type.Script;
     37    this.sourceFrame = new WebInspector.SourceFrame(this.element, contentProvider, resource.url, isScript);
    3838}
    3939
  • trunk/Source/WebCore/inspector/front-end/TextViewer.js

    r73913 r76341  
    4444    this.element.addEventListener("beforecopy", this._beforeCopy.bind(this), false);
    4545    this.element.addEventListener("copy", this._copy.bind(this), false);
    46     this.element.addEventListener("dblclick", this._handleDoubleClick.bind(this), false);
    4746
    4847    this._url = url;
     
    7978        var chunk = this._makeLineAChunk(lineNumber);
    8079        chunk.element.scrollIntoViewIfNeeded();
    81     },
    82 
    83     set editCallback(editCallback)
    84     {
    85         this._editCallback = editCallback;
    8680    },
    8781
     
    232226        else if (event.keyCode == WebInspector.KeyboardShortcut.Keys.Down.code)
    233227            scrollValue = 1;
    234        
     228
    235229        if (scrollValue) {
    236230            event.preventDefault();
     
    239233            return;
    240234        }
    241        
     235
    242236        scrollValue = 0;
    243237        if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Left.code)
     
    245239        else if (event.keyCode == WebInspector.KeyboardShortcut.Keys.Right.code)
    246240            scrollValue = 40;
    247        
     241
    248242        if (scrollValue) {
    249243            event.preventDefault();
     
    253247    },
    254248
    255     _handleDoubleClick: function(e)
    256     {
    257         if (!this._editCallback)
    258             return;
    259 
    260         var cell = e.target.enclosingNodeOrSelfWithNodeName("TD");
    261         if (!cell)
    262             return;
    263 
    264         var lineRow = cell.parentElement;
    265         if (lineRow.firstChild === cell)
    266             return;  // Do not trigger editing from line numbers.
    267 
    268         var oldContent = lineRow.lastChild.innerHTML;
    269         var cancelEditingCallback = this._cancelEditingLine.bind(this, lineRow.lastChild, oldContent);
    270         var commitEditingCallback = this._commitEditingLine.bind(this, lineRow.lineNumber, lineRow.lastChild, cancelEditingCallback);
    271         this._editingLine = WebInspector.startEditing(lineRow.lastChild, {
     249    editLine: function(lineRow, callback)
     250    {
     251        var element = lineRow.lastChild;
     252        var oldContent = element.innerHTML;
     253        function finishEditing(committed, e, newContent)
     254        {
     255            if (committed)
     256                callback(newContent);
     257            element.innerHTML = oldContent;
     258            delete this._editingLine;
     259        }
     260        this._editingLine = WebInspector.startEditing(element, {
    272261            context: null,
    273             commitHandler: commitEditingCallback,
    274             cancelHandler: cancelEditingCallback,
     262            commitHandler: finishEditing.bind(this, true),
     263            cancelHandler: finishEditing.bind(this, false),
    275264            multiline: true
    276265        });
    277     },
    278 
    279     _commitEditingLine: function(lineNumber, element, cancelEditingCallback)
    280     {
    281         this._editCallback(lineNumber, element.textContent, cancelEditingCallback);
    282         delete this._editingLine;
    283     },
    284 
    285     _cancelEditingLine: function(element, oldContent, e)
    286     {
    287         element.innerHTML = oldContent;
    288         delete this._editingLine;
    289266    },
    290267
     
    787764            var lineContentElement = document.createElement("td");
    788765            lineContentElement.className = "webkit-line-content";
    789             lineRow.appendChild(lineContentElement);       
     766            lineRow.appendChild(lineContentElement);
    790767        }
    791768        lineRow.lineNumber = lineNumber;
Note: See TracChangeset for help on using the changeset viewer.