123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900 |
- /*
- * Copyright (C) 2011 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.
- */
- /**
- * @constructor
- * @extends {WebInspector.UISourceCodeFrame}
- * @param {WebInspector.ScriptsPanel} scriptsPanel
- * @param {WebInspector.UISourceCode} uiSourceCode
- */
- WebInspector.JavaScriptSourceFrame = function(scriptsPanel, uiSourceCode)
- {
- this._scriptsPanel = scriptsPanel;
- this._breakpointManager = WebInspector.breakpointManager;
- this._uiSourceCode = uiSourceCode;
- WebInspector.UISourceCodeFrame.call(this, uiSourceCode);
- if (uiSourceCode.project().type() === WebInspector.projectTypes.Debugger)
- this.element.addStyleClass("source-frame-debugger-script");
- this._popoverHelper = new WebInspector.ObjectPopoverHelper(this.textEditor.element,
- this._getPopoverAnchor.bind(this), this._resolveObjectForPopover.bind(this), this._onHidePopover.bind(this), true);
- this.textEditor.element.addEventListener("keydown", this._onKeyDown.bind(this), true);
- this.textEditor.addEventListener(WebInspector.TextEditor.Events.GutterClick, this._handleGutterClick.bind(this), this);
- this.textEditor.element.addEventListener("mousedown", this._onMouseDownAndClick.bind(this, true), true);
- this.textEditor.element.addEventListener("click", this._onMouseDownAndClick.bind(this, false), true);
- this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
- this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);
- this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ConsoleMessageAdded, this._consoleMessageAdded, this);
- this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ConsoleMessageRemoved, this._consoleMessageRemoved, this);
- this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ConsoleMessagesCleared, this._consoleMessagesCleared, this);
- this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.SourceMappingChanged, this._onSourceMappingChanged, this);
- this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
- this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);
- this._registerShortcuts();
- this._updateScriptFile();
- }
- WebInspector.JavaScriptSourceFrame.prototype = {
- _registerShortcuts: function()
- {
- var modifiers = WebInspector.KeyboardShortcut.Modifiers;
- this.addShortcut(WebInspector.KeyboardShortcut.makeKey("e", modifiers.Shift | modifiers.Ctrl), this._evaluateSelectionInConsole.bind(this));
- },
- /**
- * @param {Event=} event
- * @return {boolean}
- */
- _evaluateSelectionInConsole: function(event)
- {
- var selection = this.textEditor.selection();
- if (!selection || selection.isEmpty())
- return false;
- WebInspector.evaluateInConsole(this.textEditor.copyRange(selection));
- return true;
- },
- // View events
- wasShown: function()
- {
- WebInspector.UISourceCodeFrame.prototype.wasShown.call(this);
- },
- willHide: function()
- {
- WebInspector.UISourceCodeFrame.prototype.willHide.call(this);
- this._popoverHelper.hidePopover();
- },
- onUISourceCodeContentChanged: function()
- {
- this._removeAllBreakpoints();
- WebInspector.UISourceCodeFrame.prototype.onUISourceCodeContentChanged.call(this);
- },
- populateLineGutterContextMenu: function(contextMenu, lineNumber)
- {
- contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Continue to here" : "Continue to Here"), this._continueToLine.bind(this, lineNumber));
- var breakpoint = this._breakpointManager.findBreakpoint(this._uiSourceCode, 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(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._setBreakpoint.bind(this, lineNumber, "", true));
- contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add conditional breakpoint…" : "Add Conditional Breakpoint…"), this._editBreakpointCondition.bind(this, lineNumber));
- } else {
- // This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable.
- contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), breakpoint.remove.bind(breakpoint));
- contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit breakpoint…" : "Edit Breakpoint…"), this._editBreakpointCondition.bind(this, lineNumber, breakpoint));
- if (breakpoint.enabled())
- contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Disable breakpoint" : "Disable Breakpoint"), breakpoint.setEnabled.bind(breakpoint, false));
- else
- contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Enable breakpoint" : "Enable Breakpoint"), breakpoint.setEnabled.bind(breakpoint, true));
- }
- },
- populateTextAreaContextMenu: function(contextMenu, lineNumber)
- {
- var textSelection = this.textEditor.selection();
- if (textSelection && !textSelection.isEmpty()) {
- var selection = this.textEditor.copyRange(textSelection);
- var addToWatchLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add to watch" : "Add to Watch");
- contextMenu.appendItem(addToWatchLabel, this._scriptsPanel.addToWatch.bind(this._scriptsPanel, selection));
- var evaluateLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Evaluate in console" : "Evaluate in Console");
- contextMenu.appendItem(evaluateLabel, WebInspector.evaluateInConsole.bind(WebInspector, selection));
- contextMenu.appendSeparator();
- } else if (!this._uiSourceCode.isEditable() && this._uiSourceCode.contentType() === WebInspector.resourceTypes.Script) {
- function liveEdit(event)
- {
- var liveEditUISourceCode = WebInspector.liveEditSupport.uiSourceCodeForLiveEdit(this._uiSourceCode);
- this._scriptsPanel.showUISourceCode(liveEditUISourceCode, lineNumber)
- }
- // FIXME: Change condition above to explicitly check that current uiSourceCode is created by default debugger mapping
- // and move the code adding this menu item to generic context menu provider for UISourceCode.
- var liveEditLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Live edit" : "Live Edit");
- contextMenu.appendItem(liveEditLabel, liveEdit.bind(this));
- contextMenu.appendSeparator();
- }
- WebInspector.UISourceCodeFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber);
- },
- _workingCopyChanged: function(event)
- {
- if (this._supportsEnabledBreakpointsWhileEditing() || this._scriptFile)
- return;
- if (this._uiSourceCode.isDirty())
- this._muteBreakpointsWhileEditing();
- else
- this._restoreBreakpointsAfterEditing();
- },
- _workingCopyCommitted: function(event)
- {
- if (this._supportsEnabledBreakpointsWhileEditing() || this._scriptFile)
- return;
- this._restoreBreakpointsAfterEditing();
- },
- _didMergeToVM: function()
- {
- if (this._supportsEnabledBreakpointsWhileEditing())
- return;
- this._restoreBreakpointsAfterEditing();
- },
- _didDivergeFromVM: function()
- {
- if (this._supportsEnabledBreakpointsWhileEditing())
- return;
- this._muteBreakpointsWhileEditing();
- },
- _muteBreakpointsWhileEditing: function()
- {
- if (this._muted)
- return;
- for (var lineNumber = 0; lineNumber < this._textEditor.linesCount; ++lineNumber) {
- var breakpointDecoration = this._textEditor.getAttribute(lineNumber, "breakpoint");
- if (!breakpointDecoration)
- continue;
- this._removeBreakpointDecoration(lineNumber);
- this._addBreakpointDecoration(lineNumber, breakpointDecoration.condition, breakpointDecoration.enabled, true);
- }
- this._muted = true;
- },
- _supportsEnabledBreakpointsWhileEditing: function()
- {
- return this._uiSourceCode.project().type() === WebInspector.projectTypes.Snippets;
- },
- _restoreBreakpointsAfterEditing: function()
- {
- delete this._muted;
- var breakpoints = {};
- // Save and remove muted breakpoint decorations.
- for (var lineNumber = 0; lineNumber < this._textEditor.linesCount; ++lineNumber) {
- var breakpointDecoration = this._textEditor.getAttribute(lineNumber, "breakpoint");
- if (breakpointDecoration) {
- breakpoints[lineNumber] = breakpointDecoration;
- this._removeBreakpointDecoration(lineNumber);
- }
- }
- // Remove all breakpoints.
- this._removeAllBreakpoints();
- // Restore all breakpoints from saved decorations.
- for (var lineNumberString in breakpoints) {
- var lineNumber = parseInt(lineNumberString, 10);
- if (isNaN(lineNumber))
- continue;
- var breakpointDecoration = breakpoints[lineNumberString];
- this._setBreakpoint(lineNumber, breakpointDecoration.condition, breakpointDecoration.enabled);
- }
- },
- _removeAllBreakpoints: function()
- {
- var breakpoints = this._breakpointManager.breakpointsForUISourceCode(this._uiSourceCode);
- for (var i = 0; i < breakpoints.length; ++i)
- breakpoints[i].remove();
- },
- _getPopoverAnchor: function(element, event)
- {
- if (!WebInspector.debuggerModel.isPaused())
- return null;
- var textPosition = this.textEditor.coordinatesToCursorPosition(event.x, event.y);
- if (!textPosition)
- return null;
- var mouseLine = textPosition.startLine;
- var mouseColumn = textPosition.startColumn;
- var textSelection = this.textEditor.selection().normalize();
- if (textSelection && !textSelection.isEmpty()) {
- if (textSelection.startLine !== textSelection.endLine || textSelection.startLine !== mouseLine || mouseColumn < textSelection.startColumn || mouseColumn > textSelection.endColumn)
- return null;
- var leftCorner = this.textEditor.cursorPositionToCoordinates(textSelection.startLine, textSelection.startColumn);
- var rightCorner = this.textEditor.cursorPositionToCoordinates(textSelection.endLine, textSelection.endColumn);
- var anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height);
- anchorBox.highlight = {
- lineNumber: textSelection.startLine,
- startColumn: textSelection.startColumn,
- endColumn: textSelection.endColumn - 1
- };
- anchorBox.forSelection = true;
- return anchorBox;
- }
- var token = this.textEditor.tokenAtTextPosition(textPosition.startLine, textPosition.startColumn);
- if (!token)
- return null;
- var lineNumber = textPosition.startLine;
- var line = this.textEditor.line(lineNumber);
- var tokenContent = line.substring(token.startColumn, token.endColumn + 1);
- if (token.type !== "javascript-ident" && (token.type !== "javascript-keyword" || tokenContent !== "this"))
- return null;
- var leftCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, token.startColumn);
- var rightCorner = this.textEditor.cursorPositionToCoordinates(lineNumber, token.endColumn + 1);
- var anchorBox = new AnchorBox(leftCorner.x, leftCorner.y, rightCorner.x - leftCorner.x, leftCorner.height);
- anchorBox.highlight = {
- lineNumber: lineNumber,
- startColumn: token.startColumn,
- endColumn: token.endColumn
- };
- return anchorBox;
- },
- _resolveObjectForPopover: function(anchorBox, showCallback, objectGroupName)
- {
- /**
- * @param {?RuntimeAgent.RemoteObject} result
- * @param {boolean=} wasThrown
- */
- function showObjectPopover(result, wasThrown)
- {
- if (!WebInspector.debuggerModel.isPaused()) {
- this._popoverHelper.hidePopover();
- return;
- }
- this._popoverAnchorBox = anchorBox;
- showCallback(WebInspector.RemoteObject.fromPayload(result), wasThrown, this._popoverAnchorBox);
- // Popover may have been removed by showCallback().
- if (this._popoverAnchorBox) {
- var highlightRange = new WebInspector.TextRange(lineNumber, startHighlight, lineNumber, endHighlight);
- this._popoverAnchorBox._highlightDescriptor = this.textEditor.highlightRange(highlightRange, "source-frame-eval-expression");
- }
- }
- if (!WebInspector.debuggerModel.isPaused()) {
- this._popoverHelper.hidePopover();
- return;
- }
- var lineNumber = anchorBox.highlight.lineNumber;
- var startHighlight = anchorBox.highlight.startColumn;
- var endHighlight = anchorBox.highlight.endColumn;
- var line = this.textEditor.line(lineNumber);
- if (!anchorBox.forSelection) {
- while (startHighlight > 1 && line.charAt(startHighlight - 1) === '.')
- startHighlight = this.textEditor.tokenAtTextPosition(lineNumber, startHighlight - 2).startColumn;
- }
- var evaluationText = line.substring(startHighlight, endHighlight + 1);
- var selectedCallFrame = WebInspector.debuggerModel.selectedCallFrame();
- selectedCallFrame.evaluate(evaluationText, objectGroupName, false, true, false, false, showObjectPopover.bind(this));
- },
- _onHidePopover: function()
- {
- if (!this._popoverAnchorBox)
- return;
- if (this._popoverAnchorBox._highlightDescriptor)
- this.textEditor.removeHighlight(this._popoverAnchorBox._highlightDescriptor);
- delete this._popoverAnchorBox;
- },
- /**
- * @param {number} lineNumber
- * @param {string} condition
- * @param {boolean} enabled
- * @param {boolean} mutedWhileEditing
- */
- _addBreakpointDecoration: function(lineNumber, condition, enabled, mutedWhileEditing)
- {
- var breakpoint = {
- condition: condition,
- enabled: enabled
- };
- this.textEditor.setAttribute(lineNumber, "breakpoint", breakpoint);
- var disabled = !enabled || mutedWhileEditing;
- this.textEditor.addBreakpoint(lineNumber, disabled, !!condition);
- },
- _removeBreakpointDecoration: function(lineNumber)
- {
- this.textEditor.removeAttribute(lineNumber, "breakpoint");
- this.textEditor.removeBreakpoint(lineNumber);
- },
- _onKeyDown: function(event)
- {
- if (event.keyIdentifier === "U+001B") { // Escape key
- if (this._popoverHelper.isPopoverVisible()) {
- this._popoverHelper.hidePopover();
- event.consume();
- return;
- }
- if (this._stepIntoMarkup && WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)) {
- this._stepIntoMarkup.stoptIteratingSelection();
- event.consume();
- return;
- }
- }
- },
- /**
- * @param {number} lineNumber
- * @param {WebInspector.BreakpointManager.Breakpoint=} breakpoint
- */
- _editBreakpointCondition: function(lineNumber, breakpoint)
- {
- this._conditionElement = this._createConditionElement(lineNumber);
- this.textEditor.addDecoration(lineNumber, this._conditionElement);
- function finishEditing(committed, element, newText)
- {
- this.textEditor.removeDecoration(lineNumber, this._conditionElement);
- delete this._conditionEditorElement;
- delete this._conditionElement;
- if (!committed)
- return;
- if (breakpoint)
- breakpoint.setCondition(newText);
- else
- this._setBreakpoint(lineNumber, newText, true);
- }
- var config = new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false));
- WebInspector.startEditing(this._conditionEditorElement, config);
- this._conditionEditorElement.value = breakpoint ? breakpoint.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;
- },
- /**
- * @param {number} lineNumber
- * @param {WebInspector.DebuggerModel.CallFrame} callFrame
- */
- setExecutionLine: function(lineNumber, callFrame)
- {
- this._executionLineNumber = lineNumber;
- this._executionCallFrame = callFrame;
- if (this.loaded) {
- this.textEditor.setExecutionLine(lineNumber);
- if (WebInspector.experimentsSettings.stepIntoSelection.isEnabled()) {
- /**
- * @param {Array.<DebuggerAgent.Location>} locations
- */
- function locationsCallback(locations)
- {
- if (this._executionCallFrame !== callFrame || this._stepIntoMarkup)
- return;
- this._stepIntoMarkup = WebInspector.JavaScriptSourceFrame.StepIntoMarkup.create(this, locations);
- if (this._stepIntoMarkup)
- this._stepIntoMarkup.show();
- }
- callFrame.getStepIntoLocations(locationsCallback.bind(this));
- }
- }
- },
- clearExecutionLine: function()
- {
- if (this._stepIntoMarkup) {
- this._stepIntoMarkup.dispose();
- delete this._stepIntoMarkup;
- }
- if (this.loaded && typeof this._executionLineNumber === "number")
- this.textEditor.clearExecutionLine();
- delete this._executionLineNumber;
- delete this._executionCallFrame;
- },
- _lineNumberAfterEditing: function(lineNumber, oldRange, newRange)
- {
- var shiftOffset = lineNumber <= oldRange.startLine ? 0 : newRange.linesCount - oldRange.linesCount;
- // Special case of editing the line itself. We should decide whether the line number should move below or not.
- if (lineNumber === oldRange.startLine) {
- var whiteSpacesRegex = /^[\s\xA0]*$/;
- for (var i = 0; lineNumber + i <= newRange.endLine; ++i) {
- if (!whiteSpacesRegex.test(this.textEditor.line(lineNumber + i))) {
- shiftOffset = i;
- break;
- }
- }
- }
- var newLineNumber = Math.max(0, lineNumber + shiftOffset);
- if (oldRange.startLine < lineNumber && lineNumber < oldRange.endLine)
- newLineNumber = oldRange.startLine;
- return newLineNumber;
- },
- _onMouseDownAndClick: function(isMouseDown, event)
- {
- var markup = this._stepIntoMarkup;
- if (!markup)
- return;
- var index = markup.findItemByCoordinates(event.x, event.y);
- if (typeof index === "undefined")
- return;
- if (isMouseDown) {
- // Do not let text editor to spoil 'click' event that is coming for us.
- event.consume();
- } else {
- var rawLocation = markup.getRawPosition(index);
- this._scriptsPanel.doStepIntoSelection(rawLocation);
- }
- },
- /**
- * @return {boolean}
- */
- _shouldIgnoreExternalBreakpointEvents: function()
- {
- if (this._supportsEnabledBreakpointsWhileEditing())
- return false;
- if (this._muted)
- return true;
- return this._scriptFile && (this._scriptFile.isDivergingFromVM() || this._scriptFile.isMergingToVM());
- },
- _breakpointAdded: function(event)
- {
- var uiLocation = /** @type {WebInspector.UILocation} */ (event.data.uiLocation);
- if (uiLocation.uiSourceCode !== this._uiSourceCode)
- return;
- if (this._shouldIgnoreExternalBreakpointEvents())
- return;
- var breakpoint = /** @type {WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
- if (this.loaded)
- this._addBreakpointDecoration(uiLocation.lineNumber, breakpoint.condition(), breakpoint.enabled(), false);
- },
- _breakpointRemoved: function(event)
- {
- var uiLocation = /** @type {WebInspector.UILocation} */ (event.data.uiLocation);
- if (uiLocation.uiSourceCode !== this._uiSourceCode)
- return;
- if (this._shouldIgnoreExternalBreakpointEvents())
- return;
- var breakpoint = /** @type {WebInspector.BreakpointManager.Breakpoint} */ (event.data.breakpoint);
- var remainingBreakpoint = this._breakpointManager.findBreakpoint(this._uiSourceCode, uiLocation.lineNumber);
- if (!remainingBreakpoint && this.loaded)
- this._removeBreakpointDecoration(uiLocation.lineNumber);
- },
- _consoleMessageAdded: function(event)
- {
- var message = /** @type {WebInspector.PresentationConsoleMessage} */ (event.data);
- if (this.loaded)
- this.addMessageToSource(message.lineNumber, message.originalMessage);
- },
- _consoleMessageRemoved: function(event)
- {
- var message = /** @type {WebInspector.PresentationConsoleMessage} */ (event.data);
- if (this.loaded)
- this.removeMessageFromSource(message.lineNumber, message.originalMessage);
- },
- _consoleMessagesCleared: function(event)
- {
- this.clearMessages();
- },
- /**
- * @param {WebInspector.Event} event
- */
- _onSourceMappingChanged: function(event)
- {
- this._updateScriptFile();
- },
- _updateScriptFile: function()
- {
- if (this._scriptFile) {
- this._scriptFile.removeEventListener(WebInspector.ScriptFile.Events.DidMergeToVM, this._didMergeToVM, this);
- this._scriptFile.removeEventListener(WebInspector.ScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this);
- if (this._muted && !this._uiSourceCode.isDirty())
- this._restoreBreakpointsAfterEditing();
- }
- this._scriptFile = this._uiSourceCode.scriptFile();
- if (this._scriptFile) {
- this._scriptFile.addEventListener(WebInspector.ScriptFile.Events.DidMergeToVM, this._didMergeToVM, this);
- this._scriptFile.addEventListener(WebInspector.ScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this);
- if (this.loaded)
- this._scriptFile.checkMapping();
- }
- },
- onTextEditorContentLoaded: function()
- {
- if (typeof this._executionLineNumber === "number")
- this.setExecutionLine(this._executionLineNumber, this._executionCallFrame);
- var breakpointLocations = this._breakpointManager.breakpointLocationsForUISourceCode(this._uiSourceCode);
- for (var i = 0; i < breakpointLocations.length; ++i)
- this._breakpointAdded({data:breakpointLocations[i]});
- var messages = this._uiSourceCode.consoleMessages();
- for (var i = 0; i < messages.length; ++i) {
- var message = messages[i];
- this.addMessageToSource(message.lineNumber, message.originalMessage);
- }
- if (this._scriptFile)
- this._scriptFile.checkMapping();
- },
- /**
- * @param {Event} event
- */
- _handleGutterClick: function(event)
- {
- if (this._muted)
- return;
- var eventData = /** @type {WebInspector.TextEditor.GutterClickEventData} */ (event.data);
- var lineNumber = eventData.lineNumber;
- var eventObject = /** @type {Event} */ (eventData.event);
- if (eventObject.button != 0 || eventObject.altKey || eventObject.ctrlKey || eventObject.metaKey)
- return;
- this._toggleBreakpoint(lineNumber, eventObject.shiftKey);
- eventObject.consume(true);
- },
- /**
- * @param {number} lineNumber
- * @param {boolean} onlyDisable
- */
- _toggleBreakpoint: function(lineNumber, onlyDisable)
- {
- var breakpoint = this._breakpointManager.findBreakpoint(this._uiSourceCode, lineNumber);
- if (breakpoint) {
- if (onlyDisable)
- breakpoint.setEnabled(!breakpoint.enabled());
- else
- breakpoint.remove();
- } else
- this._setBreakpoint(lineNumber, "", true);
- },
- toggleBreakpointOnCurrentLine: function()
- {
- if (this._muted)
- return;
- var selection = this.textEditor.selection();
- if (!selection)
- return;
- this._toggleBreakpoint(selection.startLine, false);
- },
- /**
- * @param {number} lineNumber
- * @param {string} condition
- * @param {boolean} enabled
- */
- _setBreakpoint: function(lineNumber, condition, enabled)
- {
- this._breakpointManager.setBreakpoint(this._uiSourceCode, lineNumber, condition, enabled);
- WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
- action: WebInspector.UserMetrics.UserActionNames.SetBreakpoint,
- url: this._uiSourceCode.originURL(),
- line: lineNumber,
- enabled: enabled
- });
- },
- /**
- * @param {number} lineNumber
- */
- _continueToLine: function(lineNumber)
- {
- var rawLocation = /** @type {WebInspector.DebuggerModel.Location} */ (this._uiSourceCode.uiLocationToRawLocation(lineNumber, 0));
- this._scriptsPanel.continueToLocation(rawLocation);
- },
- /**
- * @return {WebInspector.JavaScriptSourceFrame.StepIntoMarkup|undefined}
- */
- stepIntoMarkup: function()
- {
- return this._stepIntoMarkup;
- },
- dispose: function()
- {
- this._breakpointManager.removeEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
- this._breakpointManager.removeEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);
- this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.ConsoleMessageAdded, this._consoleMessageAdded, this);
- this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.ConsoleMessageRemoved, this._consoleMessageRemoved, this);
- this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.ConsoleMessagesCleared, this._consoleMessagesCleared, this);
- this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.SourceMappingChanged, this._onSourceMappingChanged, this);
- this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this);
- this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this);
- WebInspector.UISourceCodeFrame.prototype.dispose.call(this);
- },
- __proto__: WebInspector.UISourceCodeFrame.prototype
- }
- /**
- * @constructor
- * @param {Array.<DebuggerAgent.Location>} rawPositions
- * @param {Array.<WebInspector.TextRange>} editorRanges
- * @param {number} firstToExecute
- * @param {WebInspector.JavaScriptSourceFrame} sourceFrame
- */
- WebInspector.JavaScriptSourceFrame.StepIntoMarkup = function(rawPositions, editorRanges, firstToExecute, sourceFrame)
- {
- this._positions = rawPositions;
- this._editorRanges = editorRanges;
- this._highlightDescriptors = new Array(rawPositions.length);
- this._currentHighlight = undefined;
- this._firstToExecute = firstToExecute;
- this._currentSelection = undefined;
- this._sourceFrame = sourceFrame;
- };
- WebInspector.JavaScriptSourceFrame.StepIntoMarkup.prototype = {
- show: function()
- {
- var highlight = this._getVisibleHighlight();
- for (var i = 0; i < this._positions.length; ++i)
- this._highlightItem(i, i === highlight);
- this._shownVisibleHighlight = highlight;
- },
- startIteratingSelection: function()
- {
- this._currentSelection = this._positions.length
- this._redrawHighlight();
- },
- stopIteratingSelection: function()
- {
- this._currentSelection = undefined;
- this._redrawHighlight();
- },
- /**
- * @param {boolean} backward
- */
- iterateSelection: function(backward)
- {
- if (typeof this._currentSelection === "undefined")
- return;
- var nextSelection = backward ? this._currentSelection - 1 : this._currentSelection + 1;
- var modulo = this._positions.length + 1;
- nextSelection = (nextSelection + modulo) % modulo;
- this._currentSelection = nextSelection;
- this._redrawHighlight();
- },
- _redrawHighlight: function()
- {
- var visibleHighlight = this._getVisibleHighlight();
- if (this._shownVisibleHighlight === visibleHighlight)
- return;
- this._hideItemHighlight(this._shownVisibleHighlight);
- this._hideItemHighlight(visibleHighlight);
- this._highlightItem(this._shownVisibleHighlight, false);
- this._highlightItem(visibleHighlight, true);
- this._shownVisibleHighlight = visibleHighlight;
- },
- /**
- * @return {number}
- */
- _getVisibleHighlight: function()
- {
- return typeof this._currentSelection === "undefined" ? this._firstToExecute : this._currentSelection;
- },
- /**
- * @param {number} position
- * @param {boolean} selected
- */
- _highlightItem: function(position, selected)
- {
- if (position === this._positions.length)
- return;
- var styleName = selected ? "source-frame-stepin-mark-highlighted" : "source-frame-stepin-mark";
- var textEditor = this._sourceFrame.textEditor;
- var highlightDescriptor = textEditor.highlightRange(this._editorRanges[position], styleName);
- this._highlightDescriptors[position] = highlightDescriptor;
- },
- /**
- * @param {number} position
- */
- _hideItemHighlight: function(position)
- {
- if (position === this._positions.length)
- return;
- var highlightDescriptor = this._highlightDescriptors[position];
- console.assert(highlightDescriptor);
- var textEditor = this._sourceFrame.textEditor;
- textEditor.removeHighlight(highlightDescriptor);
- this._highlightDescriptors[position] = undefined;
- },
- dispose: function()
- {
- for (var i = 0; i < this._positions.length; ++i)
- this._hideItemHighlight(i);
- },
- /**
- * @param {number} x
- * @param {number} y
- * @return {number|undefined}
- */
- findItemByCoordinates: function(x, y)
- {
- var textPosition = this._sourceFrame.textEditor.coordinatesToCursorPosition(x, y);
- if (!textPosition)
- return;
- var ranges = this._editorRanges;
- for (var i = 0; i < ranges.length; ++i) {
- var nextRange = ranges[i];
- if (nextRange.startLine == textPosition.startLine && nextRange.startColumn <= textPosition.startColumn && nextRange.endColumn >= textPosition.startColumn)
- return i;
- }
- },
- /**
- * @return {number|undefined}
- */
- getSelectedItemIndex: function()
- {
- if (this._currentSelection === this._positions.length)
- return undefined;
- return this._currentSelection;
- },
- /**
- * @return {WebInspector.DebuggerModel.Location}
- */
- getRawPosition: function(position)
- {
- return /** @type {WebInspector.DebuggerModel.Location} */ (this._positions[position]);
- }
- };
- /**
- * @param {WebInspector.JavaScriptSourceFrame} sourceFrame
- * @param {Array.<DebuggerAgent.Location>} stepIntoRawLocations
- * @return {?WebInspector.JavaScriptSourceFrame.StepIntoMarkup}
- */
- WebInspector.JavaScriptSourceFrame.StepIntoMarkup.create = function(sourceFrame, stepIntoRawLocations)
- {
- if (!stepIntoRawLocations.length)
- return null;
- var firstToExecute = stepIntoRawLocations[0];
- stepIntoRawLocations.sort(WebInspector.JavaScriptSourceFrame.StepIntoMarkup._Comparator);
- var firstToExecuteIndex = stepIntoRawLocations.indexOf(firstToExecute);
- var textEditor = sourceFrame.textEditor;
- var uiRanges = [];
- for (var i = 0; i < stepIntoRawLocations.length; ++i) {
- var uiLocation = WebInspector.debuggerModel.rawLocationToUILocation(/** @type {WebInspector.DebuggerModel.Location} */ (stepIntoRawLocations[i]));
- var token = textEditor.tokenAtTextPosition(uiLocation.lineNumber, uiLocation.columnNumber);
- var startColumn;
- var endColumn;
- if (token) {
- startColumn = token.startColumn;
- endColumn = token.endColumn;
- } else {
- startColumn = uiLocation.columnNumber;
- endColumn = uiLocation.columnNumber;
- }
- var range = new WebInspector.TextRange(uiLocation.lineNumber, startColumn, uiLocation.lineNumber, endColumn);
- uiRanges.push(range);
- }
- return new WebInspector.JavaScriptSourceFrame.StepIntoMarkup(stepIntoRawLocations, uiRanges, firstToExecuteIndex, sourceFrame);
- };
- /**
- * @param {DebuggerAgent.Location} locationA
- * @param {DebuggerAgent.Location} locationB
- * @return {number}
- */
- WebInspector.JavaScriptSourceFrame.StepIntoMarkup._Comparator = function(locationA, locationB)
- {
- if (locationA.lineNumber === locationB.lineNumber)
- return locationA.columnNumber - locationB.columnNumber;
- else
- return locationA.lineNumber - locationB.lineNumber;
- };
|