diff options
Diffstat (limited to 'Source/WebCore/inspector/front-end/SourceFrame.js')
-rw-r--r-- | Source/WebCore/inspector/front-end/SourceFrame.js | 869 |
1 files changed, 869 insertions, 0 deletions
diff --git a/Source/WebCore/inspector/front-end/SourceFrame.js b/Source/WebCore/inspector/front-end/SourceFrame.js new file mode 100644 index 0000000..fa8441d --- /dev/null +++ b/Source/WebCore/inspector/front-end/SourceFrame.js @@ -0,0 +1,869 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.SourceFrame = function(parentElement, scripts, canEditScripts) +{ + this._parentElement = parentElement; + this._scripts = {}; + for (var i = 0; i < scripts.length; ++i) + this._scripts[scripts[i].sourceID] = scripts[i]; + this._canEditScripts = canEditScripts; + + this._textModel = new WebInspector.TextEditorModel(); + this._textModel.replaceTabsWithSpaces = true; + + this._messages = []; + this._rowMessages = {}; + this._messageBubbles = {}; + + this._loaded = false; + this._popoverObjectGroup = "popover"; +} + +WebInspector.SourceFrame.prototype = { + + set visible(visible) + { + this._visible = visible; + this._createViewerIfNeeded(); + + if (visible) { + if (this._textViewer && this._scrollTop) + this._textViewer.element.scrollTop = this._scrollTop; + if (this._textViewer && this._scrollLeft) + this._textViewer.element.scrollLeft = this._scrollLeft; + } else { + this._hidePopup(); + if (this._textViewer) { + this._scrollTop = this._textViewer.element.scrollTop; + this._scrollLeft = this._textViewer.element.scrollLeft; + this._textViewer.freeCachedElements(); + } + } + }, + + get executionLine() + { + return this._executionLine; + }, + + set executionLine(x) + { + if (this._executionLine === x) + return; + + var previousLine = this._executionLine; + this._executionLine = x; + + if (this._textViewer) + this._updateExecutionLine(previousLine); + }, + + markDiff: function(diffData) + { + if (this._diffLines && this._textViewer) + this._removeDiffDecorations(); + + this._diffLines = diffData; + if (this._textViewer) + this._updateDiffDecorations(); + }, + + revealLine: function(lineNumber) + { + if (this._textViewer) + this._textViewer.revealLine(lineNumber - 1, 0); + else + this._lineNumberToReveal = lineNumber; + }, + + addMessage: function(msg) + { + // Don't add the message if there is no message or valid line or if the msg isn't an error or warning. + if (!msg.message || msg.line <= 0 || !msg.isErrorOrWarning()) + return; + this._messages.push(msg) + if (this._textViewer) + this._addMessageToSource(msg); + }, + + addScript: function(script) + { + this._scripts[script.sourceID] = script; + }, + + clearMessages: function() + { + for (var line in this._messageBubbles) { + var bubble = this._messageBubbles[line]; + bubble.parentNode.removeChild(bubble); + } + + this._messages = []; + this._rowMessages = {}; + this._messageBubbles = {}; + if (this._textViewer) + this._textViewer.resize(); + }, + + sizeToFitContentHeight: function() + { + if (this._textViewer) + this._textViewer.revalidateDecorationsAndPaint(); + }, + + setContent: function(mimeType, content, url) + { + this._loaded = true; + this._textModel.setText(null, content); + this._mimeType = mimeType; + this._url = url; + this._createViewerIfNeeded(); + }, + + updateContent: function(content) + { + this._textModel.setText(null, content); + }, + + get textModel() + { + return this._textModel; + }, + + get scrollTop() + { + return this._textViewer ? this._textViewer.element.scrollTop : 0; + }, + + set scrollTop(scrollTop) + { + if (this._textViewer) + this._textViewer.element.scrollTop = scrollTop; + }, + + highlightLine: function(line) + { + if (this._textViewer) + this._textViewer.highlightLine(line - 1); + else + this._lineToHighlight = line; + }, + + clearLineHighlight: function() + { + if (this._textViewer) + this._textViewer.clearLineHighlight(); + else + delete this._lineToHighlight; + }, + + _createViewerIfNeeded: function() + { + if (!this._visible || !this._loaded || this._textViewer) + return; + + this._textViewer = new WebInspector.TextViewer(this._textModel, WebInspector.platform, this._url); + var element = this._textViewer.element; + element.addEventListener("contextmenu", this._contextMenu.bind(this), true); + element.addEventListener("mousedown", this._mouseDown.bind(this), true); + element.addEventListener("mousemove", this._mouseMove.bind(this), true); + element.addEventListener("scroll", this._scroll.bind(this), true); + this._parentElement.appendChild(element); + + this._textViewer.beginUpdates(); + + this._textViewer.mimeType = this._mimeType; + this._addExistingMessagesToSource(); + this._updateExecutionLine(); + this._updateDiffDecorations(); + this._textViewer.resize(); + + if (this._lineNumberToReveal) { + this.revealLine(this._lineNumberToReveal); + delete this._lineNumberToReveal; + } + + if (this._pendingMarkRange) { + var range = this._pendingMarkRange; + this.markAndRevealRange(range); + delete this._pendingMarkRange; + } + + if (this._lineToHighlight) { + this.highlightLine(this._lineToHighlight); + delete this._lineToHighlight; + } + + var breakpoints = this._breakpoints(); + for (var i = 0; i < breakpoints.length; ++i) + this._addBreakpoint(breakpoints[i]); + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointAdded, this._breakpointAdded, this); + + this._textViewer.endUpdates(); + + if (this._canEditScripts) + this._textViewer.editCallback = this._editLine.bind(this); + }, + + findSearchMatches: function(query) + { + var ranges = []; + + // First do case-insensitive search. + var regexObject = createSearchRegex(query); + this._collectRegexMatches(regexObject, ranges); + + // Then try regex search if user knows the / / hint. + try { + if (/^\/.*\/$/.test(query)) + this._collectRegexMatches(new RegExp(query.substring(1, query.length - 1)), ranges); + } catch (e) { + // Silent catch. + } + return ranges; + }, + + _collectRegexMatches: function(regexObject, ranges) + { + for (var i = 0; i < this._textModel.linesCount; ++i) { + var line = this._textModel.line(i); + var offset = 0; + do { + var match = regexObject.exec(line); + if (match) { + ranges.push(new WebInspector.TextRange(i, offset + match.index, i, offset + match.index + match[0].length)); + offset += match.index + 1; + line = line.substring(match.index + 1); + } + } while (match) + } + return ranges; + }, + + markAndRevealRange: function(range) + { + if (this._textViewer) + this._textViewer.markAndRevealRange(range); + else + this._pendingMarkRange = range; + }, + + clearMarkedRange: function() + { + if (this._textViewer) { + this._textViewer.markAndRevealRange(null); + } else + delete this._pendingMarkRange; + }, + + _incrementMessageRepeatCount: function(msg, repeatDelta) + { + if (!msg._resourceMessageLineElement) + return; + + if (!msg._resourceMessageRepeatCountElement) { + var repeatedElement = document.createElement("span"); + msg._resourceMessageLineElement.appendChild(repeatedElement); + msg._resourceMessageRepeatCountElement = repeatedElement; + } + + msg.repeatCount += repeatDelta; + msg._resourceMessageRepeatCountElement.textContent = WebInspector.UIString(" (repeated %d times)", msg.repeatCount); + }, + + _updateExecutionLine: function(previousLine) + { + if (previousLine) { + if (previousLine - 1 < this._textModel.linesCount) + this._textViewer.removeDecoration(previousLine - 1, "webkit-execution-line"); + } + + if (!this._executionLine) + return; + + if (this._executionLine < this._textModel.linesCount) + this._textViewer.addDecoration(this._executionLine - 1, "webkit-execution-line"); + }, + + _updateDiffDecorations: function() + { + if (!this._diffLines) + return; + + function addDecorations(textViewer, lines, className) + { + for (var i = 0; i < lines.length; ++i) + textViewer.addDecoration(lines[i], className); + } + addDecorations(this._textViewer, this._diffLines.added, "webkit-added-line"); + addDecorations(this._textViewer, this._diffLines.removed, "webkit-removed-line"); + addDecorations(this._textViewer, this._diffLines.changed, "webkit-changed-line"); + }, + + _removeDiffDecorations: function() + { + function removeDecorations(textViewer, lines, className) + { + for (var i = 0; i < lines.length; ++i) + textViewer.removeDecoration(lines[i], className); + } + removeDecorations(this._textViewer, this._diffLines.added, "webkit-added-line"); + removeDecorations(this._textViewer, this._diffLines.removed, "webkit-removed-line"); + removeDecorations(this._textViewer, this._diffLines.changed, "webkit-changed-line"); + }, + + _addExistingMessagesToSource: function() + { + var length = this._messages.length; + for (var i = 0; i < length; ++i) + this._addMessageToSource(this._messages[i]); + }, + + _addMessageToSource: function(msg) + { + if (msg.line >= this._textModel.linesCount) + return; + + var messageBubbleElement = this._messageBubbles[msg.line]; + if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEMENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) { + messageBubbleElement = document.createElement("div"); + messageBubbleElement.className = "webkit-html-message-bubble"; + this._messageBubbles[msg.line] = messageBubbleElement; + this._textViewer.addDecoration(msg.line - 1, messageBubbleElement); + } + + var rowMessages = this._rowMessages[msg.line]; + if (!rowMessages) { + rowMessages = []; + this._rowMessages[msg.line] = rowMessages; + } + + for (var i = 0; i < rowMessages.length; ++i) { + if (rowMessages[i].isEqual(msg)) { + this._incrementMessageRepeatCount(rowMessages[i], msg.repeatDelta); + return; + } + } + + rowMessages.push(msg); + + var imageURL; + switch (msg.level) { + case WebInspector.ConsoleMessage.MessageLevel.Error: + messageBubbleElement.addStyleClass("webkit-html-error-message"); + imageURL = "Images/errorIcon.png"; + break; + case WebInspector.ConsoleMessage.MessageLevel.Warning: + messageBubbleElement.addStyleClass("webkit-html-warning-message"); + imageURL = "Images/warningIcon.png"; + break; + } + + var messageLineElement = document.createElement("div"); + messageLineElement.className = "webkit-html-message-line"; + messageBubbleElement.appendChild(messageLineElement); + + // Create the image element in the Inspector's document so we can use relative image URLs. + var image = document.createElement("img"); + image.src = imageURL; + image.className = "webkit-html-message-icon"; + messageLineElement.appendChild(image); + messageLineElement.appendChild(document.createTextNode(msg.message)); + + msg._resourceMessageLineElement = messageLineElement; + }, + + _breakpointAdded: function(event) + { + var breakpoint = event.data; + + if (breakpoint.sourceID in this._scripts) + this._addBreakpoint(breakpoint); + }, + + _addBreakpoint: function(breakpoint) + { + if (breakpoint.line > this._textModel.linesCount) + return; + + breakpoint.addEventListener("enable-changed", this._breakpointChanged, this); + breakpoint.addEventListener("condition-changed", this._breakpointChanged, this); + breakpoint.addEventListener("removed", this._breakpointRemoved, this); + + breakpoint.sourceText = this._textModel.line(breakpoint.line - 1); + this._setBreakpointDecoration(breakpoint.line, breakpoint.enabled, !!breakpoint.condition); + }, + + _breakpointRemoved: function(event) + { + var breakpoint = event.target; + + breakpoint.removeEventListener("enable-changed", null, this); + breakpoint.removeEventListener("condition-changed", null, this); + breakpoint.removeEventListener("removed", null, this); + + this._removeBreakpointDecoration(breakpoint.line); + }, + + _breakpointChanged: function(event) + { + var breakpoint = event.target; + this._setBreakpointDecoration(breakpoint.line, breakpoint.enabled, !!breakpoint.condition); + }, + + _setBreakpointDecoration: function(lineNumber, enabled, hasCondition) + { + lineNumber -= 1; + this._textViewer.beginUpdates(); + this._textViewer.addDecoration(lineNumber, "webkit-breakpoint"); + if (enabled) + this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint-disabled"); + else + this._textViewer.addDecoration(lineNumber, "webkit-breakpoint-disabled"); + if (hasCondition) + this._textViewer.addDecoration(lineNumber, "webkit-breakpoint-conditional"); + else + this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint-conditional"); + this._textViewer.endUpdates(); + }, + + _removeBreakpointDecoration: function(lineNumber) + { + lineNumber -= 1; + this._textViewer.beginUpdates(); + this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint"); + this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint-disabled"); + this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint-conditional"); + this._textViewer.endUpdates(); + }, + + _contextMenu: function(event) + { + if (!WebInspector.panels.scripts) + return; + + var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number"); + if (!target) + return; + var lineNumber = target.parentElement.lineNumber + 1; + + var contextMenu = new WebInspector.ContextMenu(); + + contextMenu.appendItem(WebInspector.UIString("Continue to Here"), this._continueToLine.bind(this, lineNumber)); + + var breakpoint = this._findBreakpoint(lineNumber); + if (!breakpoint) { + // This row doesn't have a breakpoint: We want to show Add Breakpoint and Add and Edit Breakpoint. + contextMenu.appendItem(WebInspector.UIString("Add Breakpoint"), this._setBreakpoint.bind(this, lineNumber, "", true)); + + function addConditionalBreakpoint() + { + this._setBreakpointDecoration(lineNumber, true, true); + function didEditBreakpointCondition(committed, condition) + { + this._removeBreakpointDecoration(lineNumber); + if (committed) + this._setBreakpoint(lineNumber, true, condition); + } + this._editBreakpointCondition(lineNumber, "", didEditBreakpointCondition.bind(this)); + } + contextMenu.appendItem(WebInspector.UIString("Add Conditional Breakpoint…"), addConditionalBreakpoint.bind(this)); + } else { + // This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable. + contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), breakpoint.remove.bind(breakpoint)); + function editBreakpointCondition() + { + function didEditBreakpointCondition(committed, condition) + { + if (committed) { + breakpoint.remove(); + this._setBreakpoint(breakpoint.line, breakpoint.enabled, condition); + } + } + this._editBreakpointCondition(lineNumber, breakpoint.condition, didEditBreakpointCondition.bind(this)); + } + contextMenu.appendItem(WebInspector.UIString("Edit Breakpoint…"), editBreakpointCondition.bind(this)); + function setBreakpointEnabled(enabled) + { + breakpoint.remove(); + this._setBreakpoint(breakpoint.line, enabled, breakpoint.condition); + } + if (breakpoint.enabled) + contextMenu.appendItem(WebInspector.UIString("Disable Breakpoint"), setBreakpointEnabled.bind(this, false)); + else + contextMenu.appendItem(WebInspector.UIString("Enable Breakpoint"), setBreakpointEnabled.bind(this, true)); + } + contextMenu.show(event); + }, + + _scroll: function(event) + { + this._hidePopup(); + }, + + _mouseDown: function(event) + { + this._resetHoverTimer(); + this._hidePopup(); + if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey) + return; + var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number"); + if (!target) + return; + var lineNumber = target.parentElement.lineNumber + 1; + + var breakpoint = this._findBreakpoint(lineNumber); + if (breakpoint) { + breakpoint.remove(); + if (event.shiftKey) + this._setBreakpoint(breakpoint.line, !breakpoint.enabled, breakpoint.condition); + } else + this._setBreakpoint(lineNumber, true, ""); + event.preventDefault(); + }, + + _mouseMove: function(event) + { + // Pretend that nothing has happened. + if (this._hoverElement === event.target || event.target.hasStyleClass("source-frame-eval-expression")) + return; + + this._resetHoverTimer(); + // User has 500ms to reach the popup. + if (this._popup) { + var self = this; + function doHide() + { + self._hidePopup(); + delete self._hidePopupTimer; + } + if (!("_hidePopupTimer" in this)) + this._hidePopupTimer = setTimeout(doHide, 500); + } + + this._hoverElement = event.target; + + // Now that cleanup routines are set up above, leave this in case we are not on a break. + if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused) + return; + + // We are interested in identifiers and "this" keyword. + if (this._hoverElement.hasStyleClass("webkit-javascript-keyword")) { + if (this._hoverElement.textContent !== "this") + return; + } else if (!this._hoverElement.hasStyleClass("webkit-javascript-ident")) + return; + + const toolTipDelay = this._popup ? 600 : 1000; + this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement), toolTipDelay); + }, + + _resetHoverTimer: function() + { + if (this._hoverTimer) { + clearTimeout(this._hoverTimer); + delete this._hoverTimer; + } + }, + + _hidePopup: function() + { + if (!this._popup) + return; + + // Replace higlight element with its contents inplace. + var parentElement = this._popup.highlightElement.parentElement; + var child = this._popup.highlightElement.firstChild; + while (child) { + var nextSibling = child.nextSibling; + parentElement.insertBefore(child, this._popup.highlightElement); + child = nextSibling; + } + parentElement.removeChild(this._popup.highlightElement); + + this._popup.hide(); + delete this._popup; + InspectorBackend.releaseWrapperObjectGroup(0, this._popoverObjectGroup); + }, + + _mouseHover: function(element) + { + delete this._hoverTimer; + + if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused) + return; + + var lineRow = element.enclosingNodeOrSelfWithNodeName("tr"); + if (!lineRow) + return; + + // Collect tokens belonging to evaluated exression. + var tokens = [ element ]; + var token = element.previousSibling; + while (token && (token.className === "webkit-javascript-ident" || token.className === "webkit-javascript-keyword" || token.textContent.trim() === ".")) { + tokens.push(token); + token = token.previousSibling; + } + tokens.reverse(); + + // Wrap them with highlight element. + var parentElement = element.parentElement; + var nextElement = element.nextSibling; + var container = document.createElement("span"); + for (var i = 0; i < tokens.length; ++i) + container.appendChild(tokens[i]); + parentElement.insertBefore(container, nextElement); + this._showPopup(container); + }, + + _showPopup: function(element) + { + function killHidePopupTimer() + { + if (this._hidePopupTimer) { + clearTimeout(this._hidePopupTimer); + delete this._hidePopupTimer; + + // We know that we reached the popup, but we might have moved over other elements. + // Discard pending command. + this._resetHoverTimer(); + } + } + + function showObjectPopup(result) + { + if (!WebInspector.panels.scripts.paused) + return; + + var popupContentElement = null; + if (result.type !== "object" && result.type !== "node" && result.type !== "array") { + popupContentElement = document.createElement("span"); + popupContentElement.className = "monospace console-formatted-" + result.type; + popupContentElement.style.whiteSpace = "pre"; + popupContentElement.textContent = result.description; + if (result.type === "string") + popupContentElement.textContent = "\"" + popupContentElement.textContent + "\""; + this._popup = new WebInspector.Popover(popupContentElement); + this._popup.show(element); + } else { + var popupContentElement = document.createElement("div"); + + var titleElement = document.createElement("div"); + titleElement.className = "source-frame-popover-title monospace"; + titleElement.textContent = result.description; + popupContentElement.appendChild(titleElement); + + var section = new WebInspector.ObjectPropertiesSection(result, "", null, false); + section.expanded = true; + section.element.addStyleClass("source-frame-popover-tree"); + section.headerElement.addStyleClass("hidden"); + popupContentElement.appendChild(section.element); + + this._popup = new WebInspector.Popover(popupContentElement); + const popupWidth = 300; + const popupHeight = 250; + this._popup.show(element, popupWidth, popupHeight); + } + this._popup.highlightElement = element; + this._popup.highlightElement.addStyleClass("source-frame-eval-expression"); + popupContentElement.addEventListener("mousemove", killHidePopupTimer.bind(this), true); + } + + function evaluateCallback(result) + { + if (result.isError()) + return; + if (!WebInspector.panels.scripts.paused) + return; + showObjectPopup.call(this, result); + } + WebInspector.panels.scripts.evaluateInSelectedCallFrame(element.textContent, false, this._popoverObjectGroup, evaluateCallback.bind(this)); + }, + + _editBreakpointCondition: function(lineNumber, condition, callback) + { + lineNumber -= 1; + this._conditionElement = this._createConditionElement(lineNumber); + this._textViewer.addDecoration(lineNumber, this._conditionElement); + + function finishEditing(committed, element, newText) + { + this._textViewer.removeDecoration(lineNumber, this._conditionElement); + delete this._conditionEditorElement; + delete this._conditionElement; + callback(committed, newText); + } + + WebInspector.startEditing(this._conditionEditorElement, { + context: null, + commitHandler: finishEditing.bind(this, true), + cancelHandler: finishEditing.bind(this, false) + }); + this._conditionEditorElement.value = condition; + this._conditionEditorElement.select(); + }, + + _createConditionElement: function(lineNumber) + { + var conditionElement = document.createElement("div"); + conditionElement.className = "source-frame-breakpoint-condition"; + + var labelElement = document.createElement("label"); + labelElement.className = "source-frame-breakpoint-message"; + labelElement.htmlFor = "source-frame-breakpoint-condition"; + labelElement.appendChild(document.createTextNode(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber))); + conditionElement.appendChild(labelElement); + + var editorElement = document.createElement("input"); + editorElement.id = "source-frame-breakpoint-condition"; + editorElement.className = "monospace"; + editorElement.type = "text" + conditionElement.appendChild(editorElement); + this._conditionEditorElement = editorElement; + + return conditionElement; + }, + + _evalSelectionInCallFrame: function(event) + { + if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused) + return; + + var selection = this.element.contentWindow.getSelection(); + if (!selection.rangeCount) + return; + + var expression = selection.getRangeAt(0).toString().trim(); + WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, "console", function(result) { + WebInspector.showConsole(); + var commandMessage = new WebInspector.ConsoleCommand(expression); + WebInspector.console.addMessage(commandMessage); + WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(result, commandMessage)); + }); + }, + + resize: function() + { + if (this._textViewer) + this._textViewer.resize(); + }, + + _continueToLine: function(lineNumber) + { + var sourceID = this._sourceIDForLine(lineNumber); + if (!sourceID) + return; + WebInspector.debuggerModel.continueToLine(sourceID, lineNumber); + }, + + _editLine: function(lineNumber, newContent, cancelEditingCallback) + { + lineNumber += 1; + + var lines = []; + for (var i = 0; i < this._textModel.linesCount; ++i) { + if (i === lineNumber - 1) + lines.push(newContent); + else + lines.push(this._textModel.line(i)); + } + + var editData = {}; + editData.sourceID = this._sourceIDForLine(lineNumber); + editData.content = lines.join("\n"); + editData.line = lineNumber; + editData.linesCountToShift = newContent.split("\n").length - 1; + this._doEditLine(editData, cancelEditingCallback); + }, + + _revertEditLine: function(editData, contentToRevertTo) + { + var newEditData = {}; + newEditData.sourceID = editData.sourceID; + newEditData.content = contentToRevertTo; + newEditData.line = editData.line; + newEditData.linesCountToShift = -editData.linesCountToShift; + this._doEditLine(newEditData); + }, + + _doEditLine: function(editData, cancelEditingCallback) + { + var revertEditingCallback = this._revertEditLine.bind(this, editData); + var commitEditingCallback = this._commitEditLine.bind(this, editData, revertEditingCallback); + WebInspector.panels.scripts.editScriptSource(editData, commitEditingCallback, cancelEditingCallback); + }, + + _commitEditLine: function(editData, revertEditLineCallback, newContent) + { + var script = this._scripts[editData.sourceID]; + script.source = newContent; + if (script.resource) + script.resource.setContent(newContent, revertEditLineCallback); + }, + + _setBreakpoint: function(lineNumber, enabled, condition) + { + var sourceID = this._sourceIDForLine(lineNumber); + if (!sourceID) + return; + WebInspector.debuggerModel.setBreakpoint(sourceID, lineNumber, enabled, condition); + if (!WebInspector.panels.scripts.breakpointsActivated) + WebInspector.panels.scripts.toggleBreakpointsClicked(); + }, + + _breakpoints: function() + { + var scripts = this._scripts; + return WebInspector.debuggerModel.queryBreakpoints(function(b) { return b.sourceID in scripts; }); + }, + + _findBreakpoint: function(lineNumber) + { + var sourceID = this._sourceIDForLine(lineNumber); + return WebInspector.debuggerModel.findBreakpoint(sourceID, lineNumber); + }, + + _sourceIDForLine: function(lineNumber) + { + var sourceIDForLine = null; + var closestStartingLine = 0; + for (var sourceID in this._scripts) { + var script = this._scripts[sourceID]; + if (script.startingLine <= lineNumber && script.startingLine >= closestStartingLine) { + closestStartingLine = script.startingLine; + sourceIDForLine = sourceID; + } + } + return sourceIDForLine; + } +} + +WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype; |