| /* |
| * 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.SourcesPanel} 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.classList.add("source-frame-debugger-script"); |
| |
| this._popoverHelper = new WebInspector.ObjectPopoverHelper(scriptsPanel.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.CodeMirrorTextEditor.Events.GutterClick, this._handleGutterClick.bind(this), this); |
| |
| this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this); |
| this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this); |
| |
| WebInspector.presentationConsoleMessageHelper.addConsoleMessageEventListener(WebInspector.PresentationConsoleMessageHelper.Events.ConsoleMessageAdded, this._uiSourceCode, this._consoleMessageAdded, this); |
| WebInspector.presentationConsoleMessageHelper.addConsoleMessageEventListener(WebInspector.PresentationConsoleMessageHelper.Events.ConsoleMessageRemoved, this._uiSourceCode, this._consoleMessageRemoved, this); |
| WebInspector.presentationConsoleMessageHelper.addConsoleMessageEventListener(WebInspector.PresentationConsoleMessageHelper.Events.ConsoleMessagesCleared, this._uiSourceCode, 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._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.TitleChanged, this._showBlackboxInfobarIfNeeded, this); |
| |
| /** @type {!Map.<!WebInspector.Target, !WebInspector.ResourceScriptFile>}*/ |
| this._scriptFileForTarget = new Map(); |
| this._registerShortcuts(); |
| var targets = WebInspector.targetManager.targets(); |
| for (var i = 0; i < targets.length; ++i) { |
| var scriptFile = WebInspector.debuggerWorkspaceBinding.scriptFile(uiSourceCode, targets[i]); |
| if (scriptFile) |
| this._updateScriptFile(targets[i]); |
| } |
| |
| if (this._scriptFileForTarget.size || uiSourceCode.extension() === "js") |
| this._compiler = new WebInspector.JavaScriptCompiler(this); |
| |
| WebInspector.moduleSetting("skipStackFramesPattern").addChangeListener(this._showBlackboxInfobarIfNeeded, this); |
| WebInspector.moduleSetting("skipContentScripts").addChangeListener(this._showBlackboxInfobarIfNeeded, this); |
| this._showBlackboxInfobarIfNeeded(); |
| /** @type {!Map.<number, !Element>} */ |
| this._valueWidgets = new Map(); |
| } |
| |
| WebInspector.JavaScriptSourceFrame.prototype = { |
| _updateInfobars: function() |
| { |
| this.attachInfobars([this._blackboxInfobar, this._divergedInfobar]); |
| }, |
| |
| _showDivergedInfobar: function() |
| { |
| if (this._uiSourceCode.contentType() !== WebInspector.resourceTypes.Script) |
| return; |
| |
| if (this._divergedInfobar) |
| this._divergedInfobar.dispose(); |
| |
| var infobar = new WebInspector.UISourceCodeFrame.Infobar(WebInspector.Infobar.Type.Warning, WebInspector.UIString("Workspace mapping mismatch")); |
| this._divergedInfobar = infobar; |
| |
| var fileURL = this._uiSourceCode.originURL(); |
| infobar.createDetailsRowMessage(WebInspector.UIString("The content of this file on the file system:\u00a0")).appendChild( |
| WebInspector.linkifyURLAsNode(fileURL, fileURL, "source-frame-infobar-details-url", true)); |
| |
| var scriptURL = WebInspector.networkMapping.networkURL(this._uiSourceCode); |
| infobar.createDetailsRowMessage(WebInspector.UIString("does not match the loaded script:\u00a0")).appendChild( |
| WebInspector.linkifyURLAsNode(scriptURL, scriptURL, "source-frame-infobar-details-url", true)); |
| |
| infobar.createDetailsRowMessage(); |
| infobar.createDetailsRowMessage(WebInspector.UIString("Possible solutions are:")); |
| |
| if (WebInspector.moduleSetting("cacheDisabled").get()) |
| infobar.createDetailsRowMessage(" - ").createTextChild(WebInspector.UIString("Reload inspected page")); |
| else |
| infobar.createDetailsRowMessage(" - ").createTextChild(WebInspector.UIString("Check \"Disable cache\" in settings and reload inspected page (recommended setup for authoring and debugging)")); |
| infobar.createDetailsRowMessage(" - ").createTextChild(WebInspector.UIString("Check that your file and script are both loaded from the correct source and their contents match")); |
| |
| this._updateInfobars(); |
| }, |
| |
| _hideDivergedInfobar: function() |
| { |
| if (!this._divergedInfobar) |
| return; |
| this._divergedInfobar.dispose(); |
| delete this._divergedInfobar; |
| }, |
| |
| _showBlackboxInfobarIfNeeded: function() |
| { |
| var contentType = this._uiSourceCode.contentType(); |
| if (contentType !== WebInspector.resourceTypes.Script && contentType !== WebInspector.resourceTypes.Document) |
| return; |
| var projectType = this._uiSourceCode.project().type(); |
| if (projectType === WebInspector.projectTypes.Snippets) |
| return; |
| var networkURL = WebInspector.networkMapping.networkURL(this._uiSourceCode); |
| var url = projectType === WebInspector.projectTypes.Formatter ? this._uiSourceCode.originURL() : networkURL; |
| var isContentScript = projectType === WebInspector.projectTypes.ContentScripts; |
| if (!WebInspector.BlackboxSupport.isBlackboxed(url, isContentScript)) { |
| this._hideBlackboxInfobar(); |
| return; |
| } |
| |
| if (this._blackboxInfobar) |
| this._blackboxInfobar.dispose(); |
| |
| var infobar = new WebInspector.UISourceCodeFrame.Infobar(WebInspector.Infobar.Type.Warning, WebInspector.UIString("This script is blackboxed in debugger")); |
| this._blackboxInfobar = infobar; |
| |
| infobar.createDetailsRowMessage(WebInspector.UIString("Debugger will skip stepping through this script, and will not stop on exceptions")); |
| infobar.createDetailsRowMessage(); |
| infobar.createDetailsRowMessage(WebInspector.UIString("Possible ways to cancel this behavior are:")); |
| |
| infobar.createDetailsRowMessage(" - ").createTextChild(WebInspector.UIString("Press \"%s\" button in settings", WebInspector.manageBlackboxingButtonLabel())); |
| var unblackboxLink = infobar.createDetailsRowMessage(" - ").createChild("span", "link"); |
| unblackboxLink.textContent = WebInspector.UIString("Unblackbox this script"); |
| unblackboxLink.addEventListener("click", unblackbox, false); |
| |
| function unblackbox() |
| { |
| WebInspector.BlackboxSupport.unblackbox(url, isContentScript); |
| } |
| |
| this._updateInfobars(); |
| }, |
| |
| _hideBlackboxInfobar: function() |
| { |
| if (!this._blackboxInfobar) |
| return; |
| this._blackboxInfobar.dispose(); |
| delete this._blackboxInfobar; |
| }, |
| |
| _registerShortcuts: function() |
| { |
| var shortcutKeys = WebInspector.ShortcutsScreen.SourcesPanelShortcuts; |
| for (var i = 0; i < shortcutKeys.EvaluateSelectionInConsole.length; ++i) { |
| var keyDescriptor = shortcutKeys.EvaluateSelectionInConsole[i]; |
| this.addShortcut(keyDescriptor.key, this._evaluateSelectionInConsole.bind(this)); |
| } |
| for (var i = 0; i < shortcutKeys.AddSelectionToWatch.length; ++i) { |
| var keyDescriptor = shortcutKeys.AddSelectionToWatch[i]; |
| this.addShortcut(keyDescriptor.key, this._addCurrentSelectionToWatch.bind(this)); |
| } |
| }, |
| |
| _addCurrentSelectionToWatch: function() |
| { |
| var textSelection = this.textEditor.selection(); |
| if (textSelection && !textSelection.isEmpty()) |
| this._innerAddToWatch(this.textEditor.copyRange(textSelection)); |
| return true; |
| }, |
| |
| /** |
| * @param {string} expression |
| */ |
| _innerAddToWatch: function(expression) |
| { |
| this._scriptsPanel.addToWatch(expression); |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| _evaluateSelectionInConsole: function() |
| { |
| var selection = this.textEditor.selection(); |
| if (!selection || selection.isEmpty()) |
| return true; |
| this._evaluateInConsole(this.textEditor.copyRange(selection)); |
| return true; |
| }, |
| |
| /** |
| * @param {string} expression |
| */ |
| _evaluateInConsole: function(expression) |
| { |
| var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext); |
| if (currentExecutionContext) |
| WebInspector.ConsoleModel.evaluateCommandInConsole(currentExecutionContext, expression); |
| }, |
| |
| /** |
| * @override |
| */ |
| wasShown: function() |
| { |
| WebInspector.UISourceCodeFrame.prototype.wasShown.call(this); |
| if (this._executionLocation && this.loaded) { |
| // We need CodeMirrorTextEditor to be initialized prior to this call. @see crbug.com/499889 |
| setImmediate(this._generateValuesInSource.bind(this)); |
| } |
| }, |
| |
| /** |
| * @override |
| */ |
| willHide: function() |
| { |
| WebInspector.UISourceCodeFrame.prototype.willHide.call(this); |
| this._popoverHelper.hidePopover(); |
| }, |
| |
| onUISourceCodeContentChanged: function() |
| { |
| this._removeAllBreakpoints(); |
| WebInspector.UISourceCodeFrame.prototype.onUISourceCodeContentChanged.call(this); |
| }, |
| |
| onTextChanged: function(oldRange, newRange) |
| { |
| this._scriptsPanel.setIgnoreExecutionLineEvents(true); |
| WebInspector.UISourceCodeFrame.prototype.onTextChanged.call(this, oldRange, newRange); |
| this._scriptsPanel.setIgnoreExecutionLineEvents(false); |
| if (this._compiler) |
| this._compiler.scheduleCompile(); |
| }, |
| |
| populateLineGutterContextMenu: function(contextMenu, lineNumber) |
| { |
| var uiLocation = new WebInspector.UILocation(this._uiSourceCode, lineNumber, 0); |
| this._scriptsPanel.appendUILocationItems(contextMenu, uiLocation); |
| var breakpoint = this._breakpointManager.findBreakpointOnLine(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.capitalize("Add ^breakpoint"), this._createNewBreakpoint.bind(this, lineNumber, 0, "", true)); |
| contextMenu.appendItem(WebInspector.UIString.capitalize("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.capitalize("Remove ^breakpoint"), breakpoint.remove.bind(breakpoint)); |
| contextMenu.appendItem(WebInspector.UIString.capitalize("Edit ^breakpoint…"), this._editBreakpointCondition.bind(this, lineNumber, breakpoint)); |
| if (breakpoint.enabled()) |
| contextMenu.appendItem(WebInspector.UIString.capitalize("Disable ^breakpoint"), breakpoint.setEnabled.bind(breakpoint, false)); |
| else |
| contextMenu.appendItem(WebInspector.UIString.capitalize("Enable ^breakpoint"), breakpoint.setEnabled.bind(breakpoint, true)); |
| } |
| }, |
| |
| populateTextAreaContextMenu: function(contextMenu, lineNumber, columnNumber) |
| { |
| var textSelection = this.textEditor.selection(); |
| if (textSelection && !textSelection.isEmpty()) { |
| var selection = this.textEditor.copyRange(textSelection); |
| var addToWatchLabel = WebInspector.UIString.capitalize("Add to ^watch"); |
| contextMenu.appendItem(addToWatchLabel, this._innerAddToWatch.bind(this, selection)); |
| var evaluateLabel = WebInspector.UIString.capitalize("Evaluate in ^console"); |
| contextMenu.appendItem(evaluateLabel, this._evaluateInConsole.bind(this, selection)); |
| contextMenu.appendSeparator(); |
| } |
| |
| /** |
| * @param {!WebInspector.ResourceScriptFile} scriptFile |
| */ |
| function addSourceMapURL(scriptFile) |
| { |
| WebInspector.AddSourceMapURLDialog.show(addSourceMapURLDialogCallback.bind(null, scriptFile)); |
| } |
| |
| /** |
| * @param {!WebInspector.ResourceScriptFile} scriptFile |
| * @param {string} url |
| */ |
| function addSourceMapURLDialogCallback(scriptFile, url) |
| { |
| if (!url) |
| return; |
| scriptFile.addSourceMapURL(url); |
| } |
| |
| WebInspector.UISourceCodeFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber, columnNumber); |
| |
| if (this._uiSourceCode.project().type() === WebInspector.projectTypes.Network && WebInspector.moduleSetting("jsSourceMapsEnabled").get()) { |
| if (this._scriptFileForTarget.size) { |
| var scriptFile = this._scriptFileForTarget.valuesArray()[0]; |
| var addSourceMapURLLabel = WebInspector.UIString.capitalize("Add ^source ^map\u2026"); |
| contextMenu.appendItem(addSourceMapURLLabel, addSourceMapURL.bind(null, scriptFile)); |
| contextMenu.appendSeparator(); |
| } |
| } |
| }, |
| |
| _workingCopyChanged: function(event) |
| { |
| if (this._supportsEnabledBreakpointsWhileEditing() || this._scriptFileForTarget.size) |
| return; |
| |
| if (this._uiSourceCode.isDirty()) |
| this._muteBreakpointsWhileEditing(); |
| else |
| this._restoreBreakpointsAfterEditing(); |
| }, |
| |
| _workingCopyCommitted: function(event) |
| { |
| if (this._supportsEnabledBreakpointsWhileEditing()) |
| return; |
| |
| if (!this._scriptFileForTarget.size) { |
| this._restoreBreakpointsAfterEditing(); |
| return; |
| } |
| |
| var liveEditError; |
| var liveEditErrorData; |
| var contextScript; |
| var succeededEdits = 0; |
| var failedEdits = 0; |
| |
| /** |
| * @this {WebInspector.JavaScriptSourceFrame} |
| * @param {?string} error |
| * @param {!DebuggerAgent.SetScriptSourceError=} errorData |
| * @param {!WebInspector.Script=} script |
| */ |
| function liveEditCallback(error, errorData, script) |
| { |
| this._scriptsPanel.setIgnoreExecutionLineEvents(false); |
| if (error) { |
| liveEditError = error; |
| liveEditErrorData = errorData; |
| contextScript = script; |
| ++failedEdits; |
| } else { |
| ++succeededEdits; |
| } |
| |
| if (succeededEdits + failedEdits !== scriptFiles.length) |
| return; |
| |
| if (failedEdits) |
| logLiveEditError.call(this, liveEditError, liveEditErrorData, contextScript); |
| } |
| |
| /** |
| * @param {?string} error |
| * @param {!DebuggerAgent.SetScriptSourceError=} errorData |
| * @param {!WebInspector.Script=} contextScript |
| * @this {WebInspector.JavaScriptSourceFrame} |
| */ |
| function logLiveEditError(error, errorData, contextScript) |
| { |
| var warningLevel = WebInspector.Console.MessageLevel.Warning; |
| if (!errorData) { |
| if (error) |
| WebInspector.console.addMessage(WebInspector.UIString("LiveEdit failed: %s", error), warningLevel); |
| return; |
| } |
| var compileError = errorData.compileError; |
| if (compileError) { |
| var messageText = WebInspector.UIString("LiveEdit compile failed: %s", compileError.message); |
| var message = new WebInspector.SourceFrameMessage(messageText, WebInspector.SourceFrameMessage.Level.Error, compileError.lineNumber - 1, compileError.columnNumber + 1); |
| this.addMessageToSource(message); |
| } else { |
| WebInspector.console.addMessage(WebInspector.UIString("Unknown LiveEdit error: %s; %s", JSON.stringify(errorData), error), warningLevel); |
| } |
| } |
| |
| this._scriptsPanel.setIgnoreExecutionLineEvents(true); |
| this._hasCommittedLiveEdit = true; |
| var scriptFiles = this._scriptFileForTarget.valuesArray(); |
| for (var i = 0; i < scriptFiles.length; ++i) |
| scriptFiles[i].commitLiveEdit(liveEditCallback.bind(this)); |
| }, |
| |
| _didMergeToVM: function() |
| { |
| if (this._supportsEnabledBreakpointsWhileEditing()) |
| return; |
| this._updateDivergedInfobar(); |
| this._restoreBreakpointsIfConsistentScripts(); |
| }, |
| |
| _didDivergeFromVM: function() |
| { |
| if (this._supportsEnabledBreakpointsWhileEditing()) |
| return; |
| this._updateDivergedInfobar(); |
| 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.columnNumber, breakpointDecoration.condition, breakpointDecoration.enabled, true); |
| } |
| this._muted = true; |
| }, |
| |
| _updateDivergedInfobar: function() |
| { |
| if (this._uiSourceCode.project().type() !== WebInspector.projectTypes.FileSystem) { |
| this._hideDivergedInfobar(); |
| return; |
| } |
| |
| var scriptFiles = this._scriptFileForTarget.valuesArray(); |
| var hasDivergedScript = false; |
| for (var i = 0; i < scriptFiles.length; ++i) |
| hasDivergedScript = hasDivergedScript || scriptFiles[i].hasDivergedFromVM(); |
| |
| if (this._divergedInfobar) { |
| if (!hasDivergedScript || this._hasCommittedLiveEdit) |
| this._hideDivergedInfobar(); |
| } else { |
| if (hasDivergedScript && !this._uiSourceCode.isDirty() && !this._hasCommittedLiveEdit) |
| this._showDivergedInfobar(); |
| } |
| }, |
| |
| _supportsEnabledBreakpointsWhileEditing: function() |
| { |
| return this._uiSourceCode.project().type() === WebInspector.projectTypes.Snippets; |
| }, |
| |
| _restoreBreakpointsIfConsistentScripts: function() |
| { |
| var scriptFiles = this._scriptFileForTarget.valuesArray(); |
| for (var i = 0; i < scriptFiles.length; ++i) |
| if (scriptFiles[i].hasDivergedFromVM() || scriptFiles[i].isMergingToVM()) |
| return; |
| |
| this._restoreBreakpointsAfterEditing(); |
| }, |
| |
| _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.columnNumber, breakpointDecoration.condition, breakpointDecoration.enabled); |
| } |
| }, |
| |
| _removeAllBreakpoints: function() |
| { |
| var breakpoints = this._breakpointManager.breakpointsForUISourceCode(this._uiSourceCode); |
| for (var i = 0; i < breakpoints.length; ++i) |
| breakpoints[i].remove(); |
| }, |
| |
| /** |
| * @param {string} tokenType |
| * @return {boolean} |
| */ |
| _isIdentifier: function(tokenType) |
| { |
| return tokenType.startsWith("js-variable") || tokenType.startsWith("js-property") || tokenType == "js-def"; |
| }, |
| |
| _getPopoverAnchor: function(element, event) |
| { |
| var target = WebInspector.context.flavor(WebInspector.Target); |
| var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); |
| if (!debuggerModel || !debuggerModel.isPaused()) |
| return; |
| |
| var textPosition = this.textEditor.coordinatesToCursorPosition(event.x, event.y); |
| if (!textPosition) |
| return; |
| 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; |
| |
| 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 || !token.type) |
| return; |
| var lineNumber = textPosition.startLine; |
| var line = this.textEditor.line(lineNumber); |
| var tokenContent = line.substring(token.startColumn, token.endColumn); |
| |
| var isIdentifier = this._isIdentifier(token.type); |
| if (!isIdentifier && (token.type !== "js-keyword" || tokenContent !== "this")) |
| return; |
| |
| 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 - 1 |
| }; |
| |
| return anchorBox; |
| }, |
| |
| _resolveObjectForPopover: function(anchorBox, showCallback, objectGroupName) |
| { |
| var target = WebInspector.context.flavor(WebInspector.Target); |
| var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); |
| if (!debuggerModel || !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) === '.') { |
| var token = this.textEditor.tokenAtTextPosition(lineNumber, startHighlight - 2); |
| if (!token || !token.type) { |
| this._popoverHelper.hidePopover(); |
| return; |
| } |
| startHighlight = token.startColumn; |
| } |
| } |
| var evaluationText = line.substring(startHighlight, endHighlight + 1); |
| var selectedCallFrame = debuggerModel.selectedCallFrame(); |
| selectedCallFrame.evaluate(evaluationText, objectGroupName, false, true, false, false, showObjectPopover.bind(this)); |
| |
| /** |
| * @param {?RuntimeAgent.RemoteObject} result |
| * @param {boolean=} wasThrown |
| * @this {WebInspector.JavaScriptSourceFrame} |
| */ |
| function showObjectPopover(result, wasThrown) |
| { |
| var target = WebInspector.context.flavor(WebInspector.Target); |
| if (selectedCallFrame.target() != target || !debuggerModel.isPaused() || !result) { |
| this._popoverHelper.hidePopover(); |
| return; |
| } |
| this._popoverAnchorBox = anchorBox; |
| showCallback(target.runtimeModel.createRemoteObject(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"); |
| } |
| } |
| }, |
| |
| _onHidePopover: function() |
| { |
| if (!this._popoverAnchorBox) |
| return; |
| if (this._popoverAnchorBox._highlightDescriptor) |
| this.textEditor.removeHighlight(this._popoverAnchorBox._highlightDescriptor); |
| delete this._popoverAnchorBox; |
| }, |
| |
| /** |
| * @param {number} lineNumber |
| * @param {number} columnNumber |
| * @param {string} condition |
| * @param {boolean} enabled |
| * @param {boolean} mutedWhileEditing |
| */ |
| _addBreakpointDecoration: function(lineNumber, columnNumber, condition, enabled, mutedWhileEditing) |
| { |
| var breakpoint = { |
| condition: condition, |
| enabled: enabled, |
| columnNumber: columnNumber |
| }; |
| |
| 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(); |
| } |
| } |
| }, |
| |
| /** |
| * @param {number} lineNumber |
| * @param {!WebInspector.BreakpointManager.Breakpoint=} breakpoint |
| */ |
| _editBreakpointCondition: function(lineNumber, breakpoint) |
| { |
| this._conditionElement = this._createConditionElement(lineNumber); |
| this.textEditor.addDecoration(lineNumber, this._conditionElement); |
| |
| /** |
| * @this {WebInspector.JavaScriptSourceFrame} |
| */ |
| 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._createNewBreakpoint(lineNumber, 0, newText, true); |
| } |
| |
| var config = new WebInspector.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false)); |
| WebInspector.InplaceEditor.startEditing(this._conditionEditorElement, config); |
| this._conditionEditorElement.value = breakpoint ? breakpoint.condition() : ""; |
| this._conditionEditorElement.select(); |
| }, |
| |
| _createConditionElement: function(lineNumber) |
| { |
| var conditionElement = createElementWithClass("div", "source-frame-breakpoint-condition"); |
| |
| var labelElement = conditionElement.createChild("label", "source-frame-breakpoint-message"); |
| labelElement.htmlFor = "source-frame-breakpoint-condition"; |
| labelElement.createTextChild(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber + 1)); |
| |
| var editorElement = conditionElement.createChild("input", "monospace"); |
| editorElement.id = "source-frame-breakpoint-condition"; |
| editorElement.type = "text"; |
| this._conditionEditorElement = editorElement; |
| |
| return conditionElement; |
| }, |
| |
| /** |
| * @param {!WebInspector.UILocation} uiLocation |
| */ |
| setExecutionLocation: function(uiLocation) |
| { |
| this._executionLocation = uiLocation; |
| if (!this.loaded) |
| return; |
| |
| this.textEditor.setExecutionLocation(uiLocation.lineNumber, uiLocation.columnNumber); |
| if (this.isShowing()) { |
| // We need CodeMirrorTextEditor to be initialized prior to this call. @see crbug.com/506566 |
| setImmediate(this._generateValuesInSource.bind(this)); |
| } |
| }, |
| |
| _generateValuesInSource: function() |
| { |
| if (!WebInspector.moduleSetting("inlineVariableValues").get()) |
| return; |
| var executionContext = WebInspector.context.flavor(WebInspector.ExecutionContext); |
| if (!executionContext) |
| return; |
| var callFrame = executionContext.debuggerModel.selectedCallFrame(); |
| if (!callFrame) |
| return; |
| |
| var localScope = callFrame.localScope(); |
| var functionLocation = callFrame.functionLocation(); |
| if (localScope && functionLocation) |
| localScope.object().getAllProperties(false, this._prepareScopeVariables.bind(this, callFrame)); |
| |
| if (this._clearValueWidgetsTimer) { |
| clearTimeout(this._clearValueWidgetsTimer); |
| delete this._clearValueWidgetsTimer; |
| } |
| }, |
| |
| /** |
| * @param {!WebInspector.DebuggerModel.CallFrame} callFrame |
| * @param {?Array.<!WebInspector.RemoteObjectProperty>} properties |
| * @param {?Array.<!WebInspector.RemoteObjectProperty>} internalProperties |
| */ |
| _prepareScopeVariables: function(callFrame, properties, internalProperties) |
| { |
| if (!properties || !properties.length || properties.length > 500) { |
| this._clearValueWidgets(); |
| return; |
| } |
| |
| var functionUILocation = WebInspector.debuggerWorkspaceBinding.rawLocationToUILocation(/**@type {!WebInspector.DebuggerModel.Location} */ (callFrame.functionLocation())); |
| var executionUILocation = WebInspector.debuggerWorkspaceBinding.rawLocationToUILocation(callFrame.location()); |
| if (functionUILocation.uiSourceCode !== this._uiSourceCode || executionUILocation.uiSourceCode !== this._uiSourceCode) { |
| this._clearValueWidgets(); |
| return; |
| } |
| |
| var fromLine = functionUILocation.lineNumber; |
| var fromColumn = functionUILocation.columnNumber; |
| var toLine = executionUILocation.lineNumber; |
| |
| // Make sure we have a chance to update all existing widgets. |
| if (this._valueWidgets) { |
| for (var line of this._valueWidgets.keys()) |
| toLine = Math.max(toLine, line + 1); |
| } |
| if (fromLine >= toLine || toLine - fromLine > 500) { |
| this._clearValueWidgets(); |
| return; |
| } |
| |
| var valuesMap = new Map(); |
| for (var property of properties) |
| valuesMap.set(property.name, property.value); |
| |
| /** @type {!Map.<number, !Set<string>>} */ |
| var namesPerLine = new Map(); |
| var tokenizer = new WebInspector.CodeMirrorUtils.TokenizerFactory().createTokenizer("text/javascript"); |
| tokenizer(this.textEditor.line(fromLine).substring(fromColumn), processToken.bind(this, fromLine)); |
| for (var i = fromLine + 1; i < toLine; ++i) |
| tokenizer(this.textEditor.line(i), processToken.bind(this, i)); |
| |
| /** |
| * @param {number} lineNumber |
| * @param {string} tokenValue |
| * @param {?string} tokenType |
| * @param {number} column |
| * @param {number} newColumn |
| * @this {WebInspector.JavaScriptSourceFrame} |
| */ |
| function processToken(lineNumber, tokenValue, tokenType, column, newColumn) |
| { |
| if (tokenType && this._isIdentifier(tokenType) && valuesMap.get(tokenValue)) { |
| var names = namesPerLine.get(lineNumber); |
| if (!names) { |
| names = new Set(); |
| namesPerLine.set(lineNumber, names); |
| } |
| names.add(tokenValue); |
| } |
| } |
| this.textEditor.operation(this._renderDecorations.bind(this, valuesMap, namesPerLine, fromLine, toLine)); |
| }, |
| |
| /** |
| * @param {!Map.<string,!WebInspector.RemoteObject>} valuesMap |
| * @param {!Map.<number, !Set<string>>} namesPerLine |
| * @param {number} fromLine |
| * @param {number} toLine |
| */ |
| _renderDecorations: function(valuesMap, namesPerLine, fromLine, toLine) |
| { |
| var formatter = new WebInspector.RemoteObjectPreviewFormatter(); |
| for (var i = fromLine; i < toLine; ++i) { |
| var names = namesPerLine.get(i); |
| var oldWidget = this._valueWidgets.get(i); |
| if (!names) { |
| if (oldWidget) { |
| this._valueWidgets.delete(i); |
| this.textEditor.removeDecoration(i, oldWidget); |
| } |
| continue; |
| } |
| |
| var widget = createElementWithClass("div", "text-editor-value-decoration"); |
| var base = this.textEditor.cursorPositionToCoordinates(i, 0); |
| var offset = this.textEditor.cursorPositionToCoordinates(i, this.textEditor.line(i).length); |
| var codeMirrorLinesLeftPadding = 4; |
| var left = offset.x - base.x + codeMirrorLinesLeftPadding; |
| widget.style.left = left + "px"; |
| widget.__nameToToken = new Map(); |
| widget.__lineNumber = i; |
| |
| var renderedNameCount = 0; |
| for (var name of names) { |
| if (renderedNameCount > 10) |
| break; |
| if (namesPerLine.get(i - 1) && namesPerLine.get(i - 1).has(name)) |
| continue; // Only render name once in the given continuous block. |
| if (renderedNameCount) |
| widget.createTextChild(", "); |
| var nameValuePair = widget.createChild("span"); |
| widget.__nameToToken.set(name, nameValuePair); |
| nameValuePair.createTextChild(name + " = "); |
| var value = valuesMap.get(name); |
| var propertyCount = value.preview ? value.preview.properties.length : 0; |
| var entryCount = value.preview && value.preview.entries ? value.preview.entries.length : 0; |
| if (value.preview && propertyCount + entryCount < 10) |
| formatter.appendObjectPreview(nameValuePair, value.preview); |
| else |
| nameValuePair.appendChild(WebInspector.ObjectPropertiesSection.createValueElement(value, false)); |
| ++renderedNameCount; |
| } |
| |
| var widgetChanged = true; |
| if (oldWidget) { |
| widgetChanged = false; |
| for (var name of widget.__nameToToken.keys()) { |
| var oldText = oldWidget.__nameToToken.get(name) ? oldWidget.__nameToToken.get(name).textContent : ""; |
| var newText = widget.__nameToToken.get(name) ? widget.__nameToToken.get(name).textContent : ""; |
| if (newText !== oldText) { |
| widgetChanged = true; |
| // value has changed, update it. |
| WebInspector.runCSSAnimationOnce(/** @type {!Element} */ (widget.__nameToToken.get(name)), "source-frame-value-update-highlight"); |
| } |
| } |
| if (widgetChanged) { |
| this._valueWidgets.delete(i); |
| this.textEditor.removeDecoration(i, oldWidget); |
| } |
| } |
| if (widgetChanged) { |
| this._valueWidgets.set(i, widget); |
| this.textEditor.addDecoration(i, widget); |
| } |
| } |
| }, |
| |
| clearExecutionLine: function() |
| { |
| if (this.loaded && this._executionLocation) |
| this.textEditor.clearExecutionLine(); |
| delete this._executionLocation; |
| this._clearValueWidgetsTimer = setTimeout(this._clearValueWidgets.bind(this), 1000); |
| }, |
| |
| _clearValueWidgets: function() |
| { |
| delete this._clearValueWidgetsTimer; |
| for (var line of this._valueWidgets.keys()) |
| this.textEditor.removeDecoration(line, this._valueWidgets.get(line)); |
| this._valueWidgets.clear(); |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| _shouldIgnoreExternalBreakpointEvents: function() |
| { |
| if (this._supportsEnabledBreakpointsWhileEditing()) |
| return false; |
| if (this._muted) |
| return true; |
| var scriptFiles = this._scriptFileForTarget.valuesArray(); |
| for (var i = 0; i < scriptFiles.length; ++i) { |
| if (scriptFiles[i].isDivergingFromVM() || scriptFiles[i].isMergingToVM()) |
| return true; |
| } |
| return false; |
| }, |
| |
| _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, uiLocation.columnNumber, 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 remainingBreakpoint = this._breakpointManager.findBreakpointOnLine(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(this._sourceFrameMessage(message)); |
| }, |
| |
| _consoleMessageRemoved: function(event) |
| { |
| var message = /** @type {!WebInspector.PresentationConsoleMessage} */ (event.data); |
| if (this.loaded) |
| this.removeMessageFromSource(this._sourceFrameMessage(message)); |
| }, |
| |
| /** |
| * @param {!WebInspector.PresentationConsoleMessage} message |
| * @return {!WebInspector.SourceFrameMessage} |
| */ |
| _sourceFrameMessage: function(message) |
| { |
| return WebInspector.SourceFrameMessage.fromConsoleMessage(message.originalMessage, message.lineNumber(), message.columnNumber()); |
| }, |
| |
| _consoleMessagesCleared: function(event) |
| { |
| this.clearMessages(); |
| }, |
| |
| /** |
| * @param {!WebInspector.Event} event |
| */ |
| _onSourceMappingChanged: function(event) |
| { |
| var data = /** @type {{target: !WebInspector.Target}} */ (event.data); |
| this._updateScriptFile(data.target); |
| this._updateLinesWithoutMappingHighlight(); |
| }, |
| |
| _updateLinesWithoutMappingHighlight: function() |
| { |
| var linesCount = this.textEditor.linesCount; |
| for (var i = 0; i < linesCount; ++i) { |
| var lineHasMapping = WebInspector.debuggerWorkspaceBinding.uiLineHasMapping(this._uiSourceCode, i); |
| if (!lineHasMapping) |
| this._hasLineWithoutMapping = true; |
| if (this._hasLineWithoutMapping) |
| this.textEditor.toggleLineClass(i, "cm-line-without-source-mapping", !lineHasMapping); |
| } |
| }, |
| |
| /** |
| * @param {!WebInspector.Target} target |
| */ |
| _updateScriptFile: function(target) |
| { |
| var oldScriptFile = this._scriptFileForTarget.get(target); |
| var newScriptFile = WebInspector.debuggerWorkspaceBinding.scriptFile(this._uiSourceCode, target); |
| this._scriptFileForTarget.remove(target); |
| if (oldScriptFile) { |
| oldScriptFile.removeEventListener(WebInspector.ResourceScriptFile.Events.DidMergeToVM, this._didMergeToVM, this); |
| oldScriptFile.removeEventListener(WebInspector.ResourceScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this); |
| if (this._muted && !this._uiSourceCode.isDirty()) |
| this._restoreBreakpointsIfConsistentScripts(); |
| } |
| if (newScriptFile) |
| this._scriptFileForTarget.set(target, newScriptFile); |
| |
| delete this._hasCommittedLiveEdit; |
| this._updateDivergedInfobar(); |
| |
| if (newScriptFile) { |
| newScriptFile.addEventListener(WebInspector.ResourceScriptFile.Events.DidMergeToVM, this._didMergeToVM, this); |
| newScriptFile.addEventListener(WebInspector.ResourceScriptFile.Events.DidDivergeFromVM, this._didDivergeFromVM, this); |
| if (this.loaded) |
| newScriptFile.checkMapping(); |
| } |
| }, |
| |
| onTextEditorContentLoaded: function() |
| { |
| if (this._executionLocation) |
| this.setExecutionLocation(this._executionLocation); |
| |
| var breakpointLocations = this._breakpointManager.breakpointLocationsForUISourceCode(this._uiSourceCode); |
| for (var i = 0; i < breakpointLocations.length; ++i) |
| this._breakpointAdded({data:breakpointLocations[i]}); |
| |
| var messages = WebInspector.presentationConsoleMessageHelper.consoleMessages(this._uiSourceCode); |
| for (var message of messages) |
| this.addMessageToSource(this._sourceFrameMessage(message)); |
| |
| var scriptFiles = this._scriptFileForTarget.valuesArray(); |
| for (var i = 0; i < scriptFiles.length; ++i) |
| scriptFiles[i].checkMapping(); |
| |
| this._updateLinesWithoutMappingHighlight(); |
| }, |
| |
| /** |
| * @param {!WebInspector.Event} event |
| */ |
| _handleGutterClick: function(event) |
| { |
| if (this._muted) |
| return; |
| |
| var eventData = /** @type {!WebInspector.CodeMirrorTextEditor.GutterClickEventData} */ (event.data); |
| var lineNumber = eventData.lineNumber; |
| var eventObject = 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.findBreakpointOnLine(this._uiSourceCode, lineNumber); |
| if (breakpoint) { |
| if (onlyDisable) |
| breakpoint.setEnabled(!breakpoint.enabled()); |
| else |
| breakpoint.remove(); |
| } else |
| this._createNewBreakpoint(lineNumber, 0, "", true); |
| }, |
| |
| /** |
| * @param {number} lineNumber |
| * @param {number} columnNumber |
| * @param {string} condition |
| * @param {boolean} enabled |
| */ |
| _createNewBreakpoint: function(lineNumber, columnNumber, condition, enabled) |
| { |
| this._setBreakpoint(lineNumber, columnNumber, condition, enabled); |
| WebInspector.userMetrics.ScriptsBreakpointSet.record(); |
| }, |
| |
| toggleBreakpointOnCurrentLine: function() |
| { |
| if (this._muted) |
| return; |
| |
| var selection = this.textEditor.selection(); |
| if (!selection) |
| return; |
| this._toggleBreakpoint(selection.startLine, false); |
| }, |
| |
| /** |
| * @param {number} lineNumber |
| * @param {number} columnNumber |
| * @param {string} condition |
| * @param {boolean} enabled |
| */ |
| _setBreakpoint: function(lineNumber, columnNumber, condition, enabled) |
| { |
| this._breakpointManager.setBreakpoint(this._uiSourceCode, lineNumber, columnNumber, condition, enabled); |
| }, |
| |
| dispose: function() |
| { |
| this._breakpointManager.removeEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this); |
| this._breakpointManager.removeEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this); |
| WebInspector.presentationConsoleMessageHelper.removeConsoleMessageEventListener(WebInspector.PresentationConsoleMessageHelper.Events.ConsoleMessageAdded, this._uiSourceCode, this._consoleMessageAdded, this); |
| WebInspector.presentationConsoleMessageHelper.removeConsoleMessageEventListener(WebInspector.PresentationConsoleMessageHelper.Events.ConsoleMessageRemoved, this._uiSourceCode, this._consoleMessageRemoved, this); |
| WebInspector.presentationConsoleMessageHelper.removeConsoleMessageEventListener(WebInspector.PresentationConsoleMessageHelper.Events.ConsoleMessagesCleared, this._uiSourceCode, 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); |
| this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.TitleChanged, this._showBlackboxInfobarIfNeeded, this); |
| WebInspector.moduleSetting("skipStackFramesPattern").removeChangeListener(this._showBlackboxInfobarIfNeeded, this); |
| WebInspector.moduleSetting("skipContentScripts").removeChangeListener(this._showBlackboxInfobarIfNeeded, this); |
| WebInspector.UISourceCodeFrame.prototype.dispose.call(this); |
| }, |
| |
| __proto__: WebInspector.UISourceCodeFrame.prototype |
| } |