/*
 * Copyright (C) 2013-2018 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
 */

WI.SourceCodeTextEditor = class SourceCodeTextEditor extends WI.TextEditor
{
    constructor(sourceCode)
    {
        console.assert(sourceCode instanceof WI.SourceCode);

        super();

        this.delegate = this;

        this._sourceCode = sourceCode;
        this._breakpointMap = {};
        this._issuesLineNumberMap = new Map;
        this._widgetMap = new Map;
        this._contentPopulated = false;
        this._invalidLineNumbers = {0: true};
        this._requestingScriptContent = false;
        this._activeCallFrameSourceCodeLocation = null;

        this._threadLineNumberMap = new Map; // line -> [targets]
        this._threadWidgetMap = new Map; // line -> widget
        this._threadTargetMap = new Map; // target -> line

        this._typeTokenScrollHandler = null;
        this._typeTokenAnnotator = null;
        this._basicBlockAnnotator = null;
        this._editingController = null;

        this._autoFormat = false;
        this._isProbablyMinified = false;

        this._ignoreContentDidChange = 0;
        this._ignoreLocationUpdateBreakpoint = null;
        this._ignoreBreakpointAddedBreakpoint = null;
        this._ignoreBreakpointRemovedBreakpoint = null;
        this._ignoreAllBreakpointLocationUpdates = false;

        // FIXME: Currently this just jumps between resources and related source map resources. It doesn't "jump to symbol" yet.
        this._updateTokenTrackingControllerState();

        this.element.classList.add("source-code");

        if (this._supportsDebugging) {
            WI.Breakpoint.addEventListener(WI.Breakpoint.Event.DisabledStateDidChange, this._breakpointStatusDidChange, this);
            WI.Breakpoint.addEventListener(WI.Breakpoint.Event.AutoContinueDidChange, this._breakpointStatusDidChange, this);
            WI.Breakpoint.addEventListener(WI.Breakpoint.Event.ResolvedStateDidChange, this._breakpointStatusDidChange, this);
            WI.Breakpoint.addEventListener(WI.Breakpoint.Event.LocationDidChange, this._updateBreakpointLocation, this);

            WI.targetManager.addEventListener(WI.TargetManager.Event.TargetAdded, this._targetAdded, this);
            WI.targetManager.addEventListener(WI.TargetManager.Event.TargetRemoved, this._targetRemoved, this);

            WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointsEnabledDidChange, this._breakpointsEnabledDidChange, this);
            WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointAdded, this._breakpointAdded, this);
            WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointRemoved, this._breakpointRemoved, this);
            WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.CallFramesDidChange, this._callFramesDidChange, this);
            WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, this._activeCallFrameDidChange, this);

            WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, this._debuggerDidPause, this);
            WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Resumed, this._debuggerDidResume, this);
            if (WI.debuggerManager.activeCallFrame)
                this._debuggerDidPause();

            this._activeCallFrameDidChange();
        }

        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.IssueAdded, this._issueWasAdded, this);

        this._sourceCode.addEventListener(WI.SourceCode.Event.FormatterDidChange, this._handleFormatterDidChange, this);
        if (this._sourceCode instanceof WI.SourceMapResource || this._sourceCode.sourceMaps.length > 0)
            WI.notifications.addEventListener(WI.Notification.GlobalModifierKeysDidChange, this._updateTokenTrackingControllerState, this);
        else
            this._sourceCode.addEventListener(WI.SourceCode.Event.SourceMapAdded, this._sourceCodeSourceMapAdded, this);

        sourceCode.requestContent().then(this._contentAvailable.bind(this));

        new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.Control, "G", this.showGoToLineDialog.bind(this), this.element);

        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.Cleared, this._logCleared, this);
    }

    // Public

    get sourceCode()
    {
        return this._sourceCode;
    }

    get target()
    {
        if (this._sourceCode instanceof WI.SourceMapResource) {
            if (this._sourceCode.sourceMap.originalSourceCode instanceof WI.Script)
                return this._sourceCode.sourceMap.originalSourceCode.target;
        }

        if (this._sourceCode instanceof WI.Script)
            return this._sourceCode.target;

        return WI.mainTarget;
    }

    shown()
    {
        super.shown();

        if (WI.settings.showJavaScriptTypeInformation.value) {
            if (this._typeTokenAnnotator)
                this._typeTokenAnnotator.resume();
            if (!this._typeTokenScrollHandler && this._typeTokenAnnotator)
                this._enableScrollEventsForTypeTokenAnnotator();
        } else {
            if (this._typeTokenAnnotator)
                this._setTypeTokenAnnotatorEnabledState(false);
        }

        if (WI.settings.enableControlFlowProfiler.value) {
            if (this._basicBlockAnnotator)
                this._basicBlockAnnotator.resume();

            if (!this._controlFlowScrollHandler && this._basicBlockAnnotator)
                this._enableScrollEventsForControlFlowAnnotator();
        } else {
            this._basicBlockAnnotatorEnabled = false;
        }
    }

    hidden()
    {
        super.hidden();

        this.tokenTrackingController.removeHighlightedRange();

        this._dismissPopover();

        this._dismissEditingController(true);

        if (this._typeTokenAnnotator)
            this._typeTokenAnnotator.pause();
        if (this._basicBlockAnnotator)
            this._basicBlockAnnotator.pause();
    }

    close()
    {
        if (this._supportsDebugging) {
            WI.Breakpoint.removeEventListener(null, null, this);
            WI.debuggerManager.removeEventListener(null, null, this);
            WI.targetManager.removeEventListener(null, null, this);

            if (this._activeCallFrameSourceCodeLocation) {
                this._activeCallFrameSourceCodeLocation.removeEventListener(WI.SourceCodeLocation.Event.LocationChanged, this._activeCallFrameSourceCodeLocationChanged, this);
                this._activeCallFrameSourceCodeLocation = null;
            }
        }

        WI.consoleManager.removeEventListener(null, null, this);
        WI.notifications.removeEventListener(null, null, this);
        this._sourceCode.removeEventListener(null, null, this);
    }

    canBeFormatted()
    {
        // Currently we assume that source map resources are formatted how the author wants it.
        // We could allow source map resources to be formatted, we would then need to make
        // SourceCodeLocation watch listen for mappedResource's formatting changes, and keep
        // a formatted location alongside the regular mapped location.
        if (this._sourceCode instanceof WI.SourceMapResource)
            return false;

        return super.canBeFormatted();
    }

    canShowTypeAnnotations()
    {
        // Type annotations for modified scripts are currently unsupported.
        return !!this._getAssociatedScript() && !this.hasModified;
    }

    canShowCoverageHints()
    {
        // Code coverage hints for modified scripts are currently unsupported.
        return !!this._getAssociatedScript() && !this.hasModified;
    }

    customPerformSearch(query)
    {
        function searchResultCallback(error, matches)
        {
            // Bail if the query changed since we started.
            if (this.currentSearchQuery !== query)
                return;

            if (error || !matches || !matches.length) {
                // Report zero matches.
                this.dispatchEventToListeners(WI.TextEditor.Event.NumberOfSearchResultsDidChange);
                return;
            }

            let queryRegex = WI.SearchUtilities.regExpForString(query, WI.SearchUtilities.defaultSettings);
            var searchResults = [];

            for (var i = 0; i < matches.length; ++i) {
                var matchLineNumber = matches[i].lineNumber;
                var line = this.line(matchLineNumber);
                if (!line)
                    return;

                // Reset the last index to reuse the regex on a new line.
                queryRegex.lastIndex = 0;

                // Search the line and mark the ranges.
                var lineMatch = null;
                while (queryRegex.lastIndex + query.length <= line.length && (lineMatch = queryRegex.exec(line))) {
                    var resultTextRange = new WI.TextRange(matchLineNumber, lineMatch.index, matchLineNumber, queryRegex.lastIndex);
                    searchResults.push(resultTextRange);
                }
            }

            this.addSearchResults(searchResults);

            this.dispatchEventToListeners(WI.TextEditor.Event.NumberOfSearchResultsDidChange);
        }

        if (this.hasEdits())
            return false;

        if (this._sourceCode instanceof WI.SourceMapResource)
            return false;
        if (this._sourceCode instanceof WI.LocalResource)
            return false;

        let caseSensitive = WI.SearchUtilities.defaultSettings.caseSensitive.value;
        let isRegex = WI.SearchUtilities.defaultSettings.regularExpression.value;

        if (this._sourceCode instanceof WI.Resource)
            this._sourceCode.target.PageAgent.searchInResource(this._sourceCode.parentFrame.id, this._sourceCode.url, query, caseSensitive, isRegex, searchResultCallback.bind(this));
        else if (this._sourceCode instanceof WI.Script)
            this._sourceCode.target.DebuggerAgent.searchInContent(this._sourceCode.id, query, caseSensitive, isRegex, searchResultCallback.bind(this));
        return true;
    }

    showGoToLineDialog()
    {
        if (!this._goToLineDialog)
            this._goToLineDialog = new WI.GoToLineDialog(this);

        this._goToLineDialog.present(this.element);
    }

    isDialogRepresentedObjectValid(goToLineDialog, lineNumber)
    {
        return !isNaN(lineNumber) && lineNumber > 0 && lineNumber <= this.lineCount;
    }

    dialogWasDismissedWithRepresentedObject(goToLineDialog, lineNumber)
    {
        let position = new WI.SourceCodePosition(lineNumber - 1, 0);
        let range = new WI.TextRange(lineNumber - 1, 0, lineNumber, 0);
        this.revealPosition(position, range, false, true);
    }

    contentDidChange(replacedRanges, newRanges)
    {
        super.contentDidChange(replacedRanges, newRanges);

        if (this._ignoreContentDidChange > 0)
            return;

        for (var range of newRanges)
            this._updateEditableMarkers(range);

        if (this._basicBlockAnnotator) {
            this._basicBlockAnnotatorEnabled = false;
            this._basicBlockAnnotator = null;
        }

        if (this._typeTokenAnnotator) {
            this._setTypeTokenAnnotatorEnabledState(false);
            this._typeTokenAnnotator = null;
        }
    }

    toggleTypeAnnotations()
    {
        if (!this._typeTokenAnnotator)
            return Promise.reject(new Error("TypeTokenAnnotator is not initialized."));

        var newActivatedState = !this._typeTokenAnnotator.isActive();
        if (newActivatedState && this._isProbablyMinified && !this.formatted) {
            return this.updateFormattedState(true).then(() => {
                this._setTypeTokenAnnotatorEnabledState(newActivatedState);
            });
        }

        this._setTypeTokenAnnotatorEnabledState(newActivatedState);
        return Promise.resolve();
    }

    toggleUnexecutedCodeHighlights()
    {
        if (!this._basicBlockAnnotator)
            return Promise.reject(new Error("BasicBlockAnnotator is not initialized."));

        let newActivatedState = !this._basicBlockAnnotator.isActive();
        if (newActivatedState && this._isProbablyMinified && !this.formatted) {
            return this.updateFormattedState(true).then(() => {
                this._basicBlockAnnotatorEnabled = newActivatedState;
            });
        }

        this._basicBlockAnnotatorEnabled = newActivatedState;
        return Promise.resolve();
    }

    showPopoverForTypes(typeDescription, bounds, title)
    {
        var content = document.createElement("div");
        content.className = "object expandable";

        var titleElement = document.createElement("div");
        titleElement.className = "title";
        titleElement.textContent = title;
        content.appendChild(titleElement);

        var bodyElement = content.appendChild(document.createElement("div"));
        bodyElement.className = "body";

        var typeTreeView = new WI.TypeTreeView(typeDescription);
        bodyElement.appendChild(typeTreeView.element);

        this._showPopover(content, bounds);
    }

    // Protected

    prettyPrint(pretty)
    {
        // The annotators must be cleared before pretty printing takes place and resumed
        // after so that they clear their annotations in a known state and insert new annotations
        // in the new state.

        var shouldResumeBasicBlockAnnotator = this._basicBlockAnnotator && this._basicBlockAnnotator.isActive();
        if (shouldResumeBasicBlockAnnotator)
            this._basicBlockAnnotatorEnabled = false;

        let shouldResumeTypeTokenAnnotator = this._typeTokenAnnotator && this._typeTokenAnnotator.isActive();
        if (shouldResumeTypeTokenAnnotator)
            this._setTypeTokenAnnotatorEnabledState(false);

        return super.prettyPrint(pretty).then(() => {
            if (pretty || !this._isProbablyMinified) {
                if (shouldResumeBasicBlockAnnotator)
                    this._basicBlockAnnotatorEnabled = true;

                if (shouldResumeTypeTokenAnnotator)
                    this._setTypeTokenAnnotatorEnabledState(true);
            } else {
                console.assert(!pretty && this._isProbablyMinified);
                if (this._basicBlockAnnotator)
                    this._basicBlockAnnotatorEnabled = false;

                this._setTypeTokenAnnotatorEnabledState(false);
            }
        });
    }

    // Private

    _unformattedLineInfoForEditorLineInfo(lineInfo)
    {
        if (this.formatterSourceMap)
            return this.formatterSourceMap.formattedToOriginal(lineInfo.lineNumber, lineInfo.columnNumber);
        return lineInfo;
    }

    _sourceCodeLocationForEditorPosition(position)
    {
        var lineInfo = {lineNumber: position.line, columnNumber: position.ch};
        var unformattedLineInfo = this._unformattedLineInfoForEditorLineInfo(lineInfo);
        return this.sourceCode.createSourceCodeLocation(unformattedLineInfo.lineNumber, unformattedLineInfo.columnNumber);
    }

    _editorLineInfoForSourceCodeLocation(sourceCodeLocation)
    {
        if (this._sourceCode instanceof WI.SourceMapResource)
            return {lineNumber: sourceCodeLocation.displayLineNumber, columnNumber: sourceCodeLocation.displayColumnNumber};
        return {lineNumber: sourceCodeLocation.formattedLineNumber, columnNumber: sourceCodeLocation.formattedColumnNumber};
    }

    _breakpointForEditorLineInfo(lineInfo)
    {
        if (!this._breakpointMap[lineInfo.lineNumber])
            return null;
        return this._breakpointMap[lineInfo.lineNumber][lineInfo.columnNumber];
    }

    _addBreakpointWithEditorLineInfo(breakpoint, lineInfo)
    {
        if (!this._breakpointMap[lineInfo.lineNumber])
            this._breakpointMap[lineInfo.lineNumber] = {};

        this._breakpointMap[lineInfo.lineNumber][lineInfo.columnNumber] = breakpoint;
    }

    _removeBreakpointWithEditorLineInfo(breakpoint, lineInfo)
    {
        console.assert(breakpoint === this._breakpointMap[lineInfo.lineNumber][lineInfo.columnNumber]);

        delete this._breakpointMap[lineInfo.lineNumber][lineInfo.columnNumber];

        if (isEmptyObject(this._breakpointMap[lineInfo.lineNumber]))
            delete this._breakpointMap[lineInfo.lineNumber];
    }

    _populateWithContent(content)
    {
        content = content || "";

        this._prepareEditorForInitialContent(content);

        // If we can auto format, format the TextEditor before showing it.
        if (this._autoFormat) {
            console.assert(!this.formatted);
            this._autoFormat = false;
            this.deferReveal = true;
            this.string = content;
            this.deferReveal = false;
            this.updateFormattedState(true).then(() => {
                this._proceedPopulateWithContent(this.string);
            });
            return;
        }

        this._proceedPopulateWithContent(content);
    }

    _proceedPopulateWithContent(content)
    {
        this.dispatchEventToListeners(WI.SourceCodeTextEditor.Event.ContentWillPopulate);

        this.string = content;

        this._createBasicBlockAnnotator();
        if (WI.settings.enableControlFlowProfiler.value && this._basicBlockAnnotator)
            this._basicBlockAnnotatorEnabled = true;

        this._createTypeTokenAnnotator();
        if (WI.settings.showJavaScriptTypeInformation.value)
            this._setTypeTokenAnnotatorEnabledState(true);

        this._contentDidPopulate();
    }

    _contentDidPopulate()
    {
        this._contentPopulated = true;

        this.dispatchEventToListeners(WI.SourceCodeTextEditor.Event.ContentDidPopulate);

        // We add the issues each time content is populated. This is needed because lines might not exist
        // if we tried added them before when the full content wasn't available. (When populating with
        // partial script content this can be called multiple times.)

        this._reinsertAllIssues();
        this._reinsertAllThreadIndicators();

        this._updateEditableMarkers();
    }

    _prepareEditorForInitialContent(content)
    {
        // Only do this work before the first populate.
        if (this._contentPopulated)
            return;

        if (this._supportsDebugging) {
            this._breakpointMap = {};

            for (let breakpoint of WI.debuggerManager.breakpointsForSourceCode(this._sourceCode)) {
                console.assert(this._matchesBreakpoint(breakpoint));
                var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
                this._addBreakpointWithEditorLineInfo(breakpoint, lineInfo);
                this.setBreakpointInfoForLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber, this._breakpointInfoForBreakpoint(breakpoint));
            }
        }

        if (this._sourceCode instanceof WI.Resource)
            this.mimeType = this._sourceCode.syntheticMIMEType;
        else if (this._sourceCode instanceof WI.Script)
            this.mimeType = "text/javascript";
        else if (this._sourceCode instanceof WI.CSSStyleSheet)
            this.mimeType = "text/css";

        // Decide to automatically format the content if it looks minified and it can be formatted.
        console.assert(!this.formatted);
        if (this.canBeFormatted() && isTextLikelyMinified(content)) {
            this._autoFormat = true;
            this._isProbablyMinified = true;
        }
    }

    _contentAvailable(parameters)
    {
        // Return if resource is not available.
        if (parameters.error)
            return;

        if (parameters.message) {
            this._showMessage(parameters.message);
            return;
        }

        var sourceCode = parameters.sourceCode;
        var content = sourceCode.content;
        var base64Encoded = parameters.base64Encoded;

        console.assert(sourceCode === this._sourceCode);
        console.assert(!base64Encoded);

        // Abort if the full content populated while waiting for this async callback.
        if (this._fullContentPopulated)
            return;

        this._fullContentPopulated = true;
        this._invalidLineNumbers = {};

        // If we had partial content (such as inline script content) before we had full content, we
        // will want to re-restore the revealed position now that we are populating with full content.
        this.repeatReveal = !!this.string;

        this._populateWithContent(content);

        this.repeatReveal = false;
    }

    _showMessage(message)
    {
        this.element.removeChildren();
        this.element.appendChild(WI.createMessageTextView(message));
    }

    _breakpointStatusDidChange(event)
    {
        this._updateBreakpointStatus(event.target);
    }

    _breakpointsEnabledDidChange()
    {
        console.assert(this._supportsDebugging);

        for (let breakpoint of WI.debuggerManager.breakpointsForSourceCode(this._sourceCode))
            this._updateBreakpointStatus(breakpoint);
    }

    _updateBreakpointStatus(breakpoint)
    {
        console.assert(this._supportsDebugging);

        if (!this._contentPopulated)
            return;

        if (!this._matchesBreakpoint(breakpoint))
            return;

        var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
        this.setBreakpointInfoForLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber, this._breakpointInfoForBreakpoint(breakpoint));
    }

    _updateBreakpointLocation(event)
    {
        console.assert(this._supportsDebugging);

        if (!this._contentPopulated)
            return;

        var breakpoint = event.target;
        if (!this._matchesBreakpoint(breakpoint))
            return;

        if (this._ignoreAllBreakpointLocationUpdates)
            return;

        if (breakpoint === this._ignoreLocationUpdateBreakpoint)
            return;

        var sourceCodeLocation = breakpoint.sourceCodeLocation;

        if (this._sourceCode instanceof WI.SourceMapResource) {
            // Update our breakpoint location if the display location changed.
            if (sourceCodeLocation.displaySourceCode !== this._sourceCode)
                return;
            var oldLineInfo = {lineNumber: event.data.oldDisplayLineNumber, columnNumber: event.data.oldDisplayColumnNumber};
            var newLineInfo = {lineNumber: sourceCodeLocation.displayLineNumber, columnNumber: sourceCodeLocation.displayColumnNumber};
        } else {
            // Update our breakpoint location if the original location changed.
            if (sourceCodeLocation.sourceCode !== this._sourceCode)
                return;
            var oldLineInfo = {lineNumber: event.data.oldFormattedLineNumber, columnNumber: event.data.oldFormattedColumnNumber};
            var newLineInfo = {lineNumber: sourceCodeLocation.formattedLineNumber, columnNumber: sourceCodeLocation.formattedColumnNumber};
        }

        var existingBreakpoint = this._breakpointForEditorLineInfo(oldLineInfo);
        if (!existingBreakpoint)
            return;

        console.assert(breakpoint === existingBreakpoint);

        this.setBreakpointInfoForLineAndColumn(oldLineInfo.lineNumber, oldLineInfo.columnNumber, null);
        this.setBreakpointInfoForLineAndColumn(newLineInfo.lineNumber, newLineInfo.columnNumber, this._breakpointInfoForBreakpoint(breakpoint));

        this._removeBreakpointWithEditorLineInfo(breakpoint, oldLineInfo);
        this._addBreakpointWithEditorLineInfo(breakpoint, newLineInfo);
    }

    _breakpointAdded(event)
    {
        console.assert(this._supportsDebugging);

        if (!this._contentPopulated)
            return;

        var breakpoint = event.data.breakpoint;
        if (!this._matchesBreakpoint(breakpoint))
            return;

        if (breakpoint === this._ignoreBreakpointAddedBreakpoint)
            return;

        var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
        this._addBreakpointWithEditorLineInfo(breakpoint, lineInfo);
        this.setBreakpointInfoForLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber, this._breakpointInfoForBreakpoint(breakpoint));
    }

    _breakpointRemoved(event)
    {
        console.assert(this._supportsDebugging);

        if (!this._contentPopulated)
            return;

        var breakpoint = event.data.breakpoint;
        if (!this._matchesBreakpoint(breakpoint))
            return;

        if (breakpoint === this._ignoreBreakpointRemovedBreakpoint)
            return;

        var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
        this._removeBreakpointWithEditorLineInfo(breakpoint, lineInfo);
        this.setBreakpointInfoForLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber, null);
    }

    _targetAdded(event)
    {
        if (WI.targets.length === 2)
            this._reinsertAllThreadIndicators();
    }

    _targetRemoved(event)
    {
        if (WI.targets.length === 1) {
            // Back to one thread, remove thread indicators.
            this._reinsertAllThreadIndicators();
            return;
        }

        let target = event.data.target;
        this._removeThreadIndicatorForTarget(target);
    }

    _callFramesDidChange(event)
    {
        if (WI.targets.length === 1)
            return;

        let target = event.data.target;
        this._removeThreadIndicatorForTarget(target);
        this._addThreadIndicatorForTarget(target);
    }

    _addThreadIndicatorForTarget(target)
    {
        let targetData = WI.debuggerManager.dataForTarget(target);
        let topCallFrame = targetData.callFrames[0];
        if (!topCallFrame)
            return;

        let sourceCodeLocation = topCallFrame.sourceCodeLocation;
        console.assert(sourceCodeLocation, "Expected source code location to place thread indicator.");
        if (!sourceCodeLocation)
            return;

        if (!this._looselyMatchesSourceCodeLocation(sourceCodeLocation))
            return;

        let lineNumberWithIndicator = sourceCodeLocation.formattedLineNumber;
        this._threadTargetMap.set(target, lineNumberWithIndicator);

        let threads = this._threadLineNumberMap.get(lineNumberWithIndicator);
        if (!threads) {
            threads = [];
            this._threadLineNumberMap.set(lineNumberWithIndicator, threads);
        }
        threads.push(target);

        let widget = this._threadIndicatorWidgetForLine(target, lineNumberWithIndicator);
        this._updateThreadIndicatorWidget(widget, threads);

        this.addStyleClassToLine(lineNumberWithIndicator, "thread-indicator");
    }

    _removeThreadIndicatorForTarget(target)
    {
        let lineNumberWithIndicator = this._threadTargetMap.take(target);
        if (lineNumberWithIndicator === undefined)
            return;

        let threads = this._threadLineNumberMap.get(lineNumberWithIndicator);
        threads.remove(target);
        if (threads.length) {
            let widget = this._threadWidgetMap.get(lineNumberWithIndicator);
            this._updateThreadIndicatorWidget(widget, threads);
            return;
        }

        this._threadLineNumberMap.delete(lineNumberWithIndicator);

        let widget = this._threadWidgetMap.take(lineNumberWithIndicator);
        if (widget)
            widget.clear();

        this.removeStyleClassFromLine(lineNumberWithIndicator, "thread-indicator");
    }

    _threadIndicatorWidgetForLine(target, lineNumber)
    {
        let widget = this._threadWidgetMap.get(lineNumber);
        if (widget)
            return widget;

        widget = this.createWidgetForLine(lineNumber);
        if (!widget)
            return null;

        let widgetElement = widget.widgetElement;
        widgetElement.classList.add("line-indicator-widget", "thread-widget", "inline");
        widgetElement.addEventListener("click", this._handleThreadIndicatorWidgetClick.bind(this, widget, lineNumber));

        this._threadWidgetMap.set(lineNumber, widget);

        return widget;
    }

    _updateThreadIndicatorWidget(widget, threads)
    {
        if (!widget)
            return;

        console.assert(WI.targets.length > 1);

        let widgetElement = widget.widgetElement;
        widgetElement.removeChildren();

        widget[WI.SourceCodeTextEditor.WidgetContainsMultipleThreadsSymbol] = threads.length > 1;

        if (widgetElement.classList.contains("inline") || threads.length === 1) {
            let textElement = widgetElement.appendChild(document.createElement("span"));
            textElement.className = "text";
            textElement.textContent = threads.length === 1 ? threads[0].displayName : WI.UIString("%d Threads").format(threads.length);
        } else {
            for (let target of threads) {
                let textElement = widgetElement.appendChild(document.createElement("span"));
                textElement.className = "text";
                textElement.textContent = target.displayName;

                widgetElement.appendChild(document.createElement("br"));
            }
        }

        widget.update();
    }

    _handleThreadIndicatorWidgetClick(widget, lineNumber, event)
    {
        if (!this._isWidgetToggleable(widget))
            return;

        widget.widgetElement.classList.toggle("inline");

        let threads = this._threadLineNumberMap.get(lineNumber);
        this._updateThreadIndicatorWidget(widget, threads);
    }

    _activeCallFrameDidChange()
    {
        console.assert(this._supportsDebugging);

        if (this._activeCallFrameSourceCodeLocation) {
            this._activeCallFrameSourceCodeLocation.removeEventListener(WI.SourceCodeLocation.Event.LocationChanged, this._activeCallFrameSourceCodeLocationChanged, this);
            this._activeCallFrameSourceCodeLocation = null;
        }

        let activeCallFrame = WI.debuggerManager.activeCallFrame;
        if (!activeCallFrame || !this._matchesSourceCodeLocation(activeCallFrame.sourceCodeLocation)) {
            this.setExecutionLineAndColumn(NaN, NaN);
            return;
        }

        this._dismissPopover();

        this._activeCallFrameSourceCodeLocation = activeCallFrame.sourceCodeLocation;
        this._activeCallFrameSourceCodeLocation.addEventListener(WI.SourceCodeLocation.Event.LocationChanged, this._activeCallFrameSourceCodeLocationChanged, this);

        // Don't return early if the line number didn't change. The execution state still
        // could have changed (e.g. continuing in a loop with a breakpoint inside).

        let lineInfo = this._editorLineInfoForSourceCodeLocation(activeCallFrame.sourceCodeLocation);
        this.setExecutionLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber);

        // If we have full content or this source code isn't a Resource we can return early.
        // Script source code populates from the request started in the constructor.
        if (this._fullContentPopulated || !(this._sourceCode instanceof WI.Resource) || this._requestingScriptContent)
            return;

        // Since we are paused in the debugger we need to show some content, and since the Resource
        // content hasn't populated yet we need to populate with content from the Scripts by URL.
        // Document resources will attempt to populate the scripts as inline (in <script> tags.)
        // Other resources are assumed to be full scripts (JavaScript resources).
        if (this._sourceCode.type === WI.Resource.Type.Document)
            this._populateWithInlineScriptContent();
        else
            this._populateWithScriptContent();
    }

    _activeCallFrameSourceCodeLocationChanged(event)
    {
        console.assert(!isNaN(this.executionLineNumber));
        if (isNaN(this.executionLineNumber))
            return;

        console.assert(WI.debuggerManager.activeCallFrame);
        console.assert(this._activeCallFrameSourceCodeLocation === WI.debuggerManager.activeCallFrame.sourceCodeLocation);

        var lineInfo = this._editorLineInfoForSourceCodeLocation(this._activeCallFrameSourceCodeLocation);
        this.setExecutionLineAndColumn(lineInfo.lineNumber, lineInfo.columnNumber);
    }

    _populateWithInlineScriptContent()
    {
        console.assert(this._sourceCode instanceof WI.Resource);
        console.assert(!this._fullContentPopulated);
        console.assert(!this._requestingScriptContent);

        var scripts = this._sourceCode.scripts;
        console.assert(scripts.length);
        if (!scripts.length)
            return;

        var pendingRequestCount = scripts.length;

        // If the number of scripts hasn't change since the last populate, then there is nothing to do.
        if (this._inlineScriptContentPopulated === pendingRequestCount)
            return;

        this._inlineScriptContentPopulated = pendingRequestCount;

        function scriptContentAvailable(parameters)
        {
            // Return early if we are still waiting for content from other scripts.
            if (--pendingRequestCount)
                return;

            this._requestingScriptContent = false;

            // Abort if the full content populated while waiting for these async callbacks.
            if (this._fullContentPopulated)
                return;

            var scriptOpenTag = "<script>";
            var scriptCloseTag = "</script>";

            var content = "";
            var lineNumber = 0;
            var columnNumber = 0;

            this._invalidLineNumbers = {};

            for (var i = 0; i < scripts.length; ++i) {
                // Fill the line gap with newline characters.
                for (var newLinesCount = scripts[i].range.startLine - lineNumber; newLinesCount > 0; --newLinesCount) {
                    if (!columnNumber)
                        this._invalidLineNumbers[scripts[i].range.startLine - newLinesCount] = true;
                    columnNumber = 0;
                    content += "\n";
                }

                // Fill the column gap with space characters.
                for (var spacesCount = scripts[i].range.startColumn - columnNumber - scriptOpenTag.length; spacesCount > 0; --spacesCount)
                    content += " ";

                // Add script tags and content.
                content += scriptOpenTag;
                content += scripts[i].content;
                content += scriptCloseTag;

                lineNumber = scripts[i].range.endLine;
                columnNumber = scripts[i].range.endColumn + scriptCloseTag.length;
            }

            this._populateWithContent(content);
        }

        this._requestingScriptContent = true;

        var boundScriptContentAvailable = scriptContentAvailable.bind(this);
        for (var i = 0; i < scripts.length; ++i)
            scripts[i].requestContent().then(boundScriptContentAvailable);
    }

    _populateWithScriptContent()
    {
        console.assert(this._sourceCode instanceof WI.Resource);
        console.assert(!this._fullContentPopulated);
        console.assert(!this._requestingScriptContent);

        // We can assume this resource only has one script that starts at line/column 0.
        var scripts = this._sourceCode.scripts;
        console.assert(scripts.length === 1);
        if (!scripts.length)
            return;

        console.assert(scripts[0].range.startLine === 0);
        console.assert(scripts[0].range.startColumn === 0);

        function scriptContentAvailable(parameters)
        {
            var content = parameters.content;
            this._requestingScriptContent = false;

            // Abort if the full content populated while waiting for this async callback.
            if (this._fullContentPopulated)
                return;

            // This is the full content.
            this._fullContentPopulated = true;

            this._populateWithContent(content);
        }

        this._requestingScriptContent = true;

        scripts[0].requestContent().then(scriptContentAvailable.bind(this));
    }

    _looselyMatchesSourceCodeLocation(sourceCodeLocation)
    {
        if (this._sourceCode instanceof WI.SourceMapResource)
            return sourceCodeLocation.displaySourceCode === this._sourceCode;
        if (this._sourceCode instanceof WI.Resource || this._sourceCode instanceof WI.Script || this._sourceCode instanceof WI.CSSStyleSheet)
            return sourceCodeLocation.sourceCode.url === this._sourceCode.url;
        return false;
    }

    _matchesSourceCodeLocation(sourceCodeLocation)
    {
        if (this._sourceCode instanceof WI.SourceMapResource)
            return sourceCodeLocation.displaySourceCode === this._sourceCode;
        if (this._sourceCode instanceof WI.Resource || this._sourceCode instanceof WI.CSSStyleSheet)
            return sourceCodeLocation.sourceCode.url === this._sourceCode.url;
        if (this._sourceCode instanceof WI.Script)
            return sourceCodeLocation.sourceCode === this._sourceCode;
        return false;
    }

    _matchesBreakpoint(breakpoint)
    {
        console.assert(this._supportsDebugging);
        if (this._sourceCode instanceof WI.SourceMapResource)
            return breakpoint.sourceCodeLocation.displaySourceCode === this._sourceCode;
        if (this._sourceCode instanceof WI.Resource)
            return breakpoint.contentIdentifier === this._sourceCode.contentIdentifier;
        if (this._sourceCode instanceof WI.Script)
            return breakpoint.contentIdentifier === this._sourceCode.contentIdentifier || breakpoint.scriptIdentifier === this._sourceCode.id;
        return false;
    }

    _issueWasAdded(event)
    {
        var issue = event.data.issue;
        if (!WI.ConsoleManager.issueMatchSourceCode(issue, this._sourceCode))
            return;

        this._addIssue(issue);
    }

    _addIssue(issue)
    {
        var sourceCodeLocation = issue.sourceCodeLocation;
        console.assert(sourceCodeLocation, "Expected source code location to place issue.");
        if (!sourceCodeLocation)
            return;

        var lineNumber = sourceCodeLocation.formattedLineNumber;

        var lineNumberIssues = this._issuesLineNumberMap.get(lineNumber);
        if (!lineNumberIssues) {
            lineNumberIssues = [];
            this._issuesLineNumberMap.set(lineNumber, lineNumberIssues);
        }

        // Avoid displaying duplicate issues on the same line.
        for (var existingIssue of lineNumberIssues) {
            if (existingIssue.sourceCodeLocation.columnNumber === sourceCodeLocation.columnNumber && existingIssue.text === issue.text)
                return;
        }

        lineNumberIssues.push(issue);

        if (issue.level === WI.IssueMessage.Level.Error)
            this.addStyleClassToLine(lineNumber, WI.SourceCodeTextEditor.LineErrorStyleClassName);
        else if (issue.level === WI.IssueMessage.Level.Warning)
            this.addStyleClassToLine(lineNumber, WI.SourceCodeTextEditor.LineWarningStyleClassName);
        else
            console.error("Unknown issue level");

        var widget = this._issueWidgetForLine(lineNumber);
        if (widget) {
            if (issue.level === WI.IssueMessage.Level.Error)
                widget.widgetElement.classList.add(WI.SourceCodeTextEditor.LineErrorStyleClassName);
            else if (issue.level === WI.IssueMessage.Level.Warning)
                widget.widgetElement.classList.add(WI.SourceCodeTextEditor.LineWarningStyleClassName);

            this._updateIssueWidgetForIssues(widget, lineNumberIssues);
        }
    }

    _issueWidgetForLine(lineNumber)
    {
        var widget = this._widgetMap.get(lineNumber);
        if (widget)
            return widget;

        widget = this.createWidgetForLine(lineNumber);
        if (!widget)
            return null;

        var widgetElement = widget.widgetElement;
        widgetElement.classList.add("line-indicator-widget", "issue-widget", "inline");
        widgetElement.addEventListener("click", this._handleWidgetClick.bind(this, widget, lineNumber));

        this._widgetMap.set(lineNumber, widget);

        return widget;
    }

    _iconClassNameForIssueLevel(level)
    {
        if (level === WI.IssueMessage.Level.Warning)
            return "icon-warning";

        console.assert(level === WI.IssueMessage.Level.Error);
        return "icon-error";
    }

    _updateIssueWidgetForIssues(widget, issues)
    {
        var widgetElement = widget.widgetElement;
        widgetElement.removeChildren();

        if (widgetElement.classList.contains("inline") || issues.length === 1) {
            var iconElement = widgetElement.appendChild(document.createElement("span"));
            iconElement.className = "icon";

            var textElement = widgetElement.appendChild(document.createElement("span"));
            textElement.className = "text";

            if (issues.length === 1) {
                iconElement.classList.add(this._iconClassNameForIssueLevel(issues[0].level));
                textElement.textContent = issues[0].text;
            } else {
                var errorsCount = 0;
                var warningsCount = 0;
                for (var issue of issues) {
                    if (issue.level === WI.IssueMessage.Level.Error)
                        ++errorsCount;
                    else if (issue.level === WI.IssueMessage.Level.Warning)
                        ++warningsCount;
                }

                if (warningsCount && errorsCount) {
                    iconElement.classList.add(this._iconClassNameForIssueLevel(issue.level));
                    textElement.textContent = WI.UIString("%d Errors, %d Warnings").format(errorsCount, warningsCount);
                } else if (errorsCount) {
                    iconElement.classList.add(this._iconClassNameForIssueLevel(issue.level));
                    textElement.textContent = WI.UIString("%d Errors").format(errorsCount);
                } else if (warningsCount) {
                    iconElement.classList.add(this._iconClassNameForIssueLevel(issue.level));
                    textElement.textContent = WI.UIString("%d Warnings").format(warningsCount);
                }

                widget[WI.SourceCodeTextEditor.WidgetContainsMultipleIssuesSymbol] = true;
            }
        } else {
            for (var issue of issues) {
                var iconElement = widgetElement.appendChild(document.createElement("span"));
                iconElement.className = "icon";
                iconElement.classList.add(this._iconClassNameForIssueLevel(issue.level));

                var textElement = widgetElement.appendChild(document.createElement("span"));
                textElement.className = "text";
                textElement.textContent = issue.text;

                widgetElement.appendChild(document.createElement("br"));
            }
        }

        widget.update();
    }

    _isWidgetToggleable(widget)
    {
        if (widget[WI.SourceCodeTextEditor.WidgetContainsMultipleIssuesSymbol])
            return true;

        if (widget[WI.SourceCodeTextEditor.WidgetContainsMultipleThreadsSymbol])
            return true;

        if (!widget.widgetElement.classList.contains("inline"))
            return true;

        var textElement = widget.widgetElement.lastChild;
        if (textElement.offsetWidth !== textElement.scrollWidth)
            return true;

        return false;
    }

    _handleWidgetClick(widget, lineNumber, event)
    {
        if (!this._isWidgetToggleable(widget))
            return;

        widget.widgetElement.classList.toggle("inline");

        var lineNumberIssues = this._issuesLineNumberMap.get(lineNumber);
        this._updateIssueWidgetForIssues(widget, lineNumberIssues);
    }

    _breakpointInfoForBreakpoint(breakpoint)
    {
        return {resolved: breakpoint.resolved, disabled: breakpoint.disabled, autoContinue: breakpoint.autoContinue};
    }

    get _supportsDebugging()
    {
        if (this._sourceCode instanceof WI.Resource) {
            if (this._sourceCode.isLocalResourceOverride)
                return false;
            return this._sourceCode.type === WI.Resource.Type.Document || this._sourceCode.type === WI.Resource.Type.Script;
        }
        if (this._sourceCode instanceof WI.Script)
            return !(this._sourceCode instanceof WI.LocalScript);
        return false;
    }

    // TextEditor Delegate

    textEditorBaseURL(textEditor)
    {
        return this._sourceCode.url;
    }

    textEditorScriptSourceType(textEditor)
    {
        let script = this._getAssociatedScript();
        return script ? script.sourceType : WI.Script.SourceType.Program;
    }

    textEditorShouldHideLineNumber(textEditor, lineNumber)
    {
        return lineNumber in this._invalidLineNumbers;
    }

    textEditorGutterContextMenu(textEditor, lineNumber, columnNumber, editorBreakpoints, event)
    {
        if (!this._supportsDebugging)
            return;

        event.preventDefault();

        let addBreakpoint = () => {
            let data = this.textEditorBreakpointAdded(this, lineNumber, columnNumber);
            this.setBreakpointInfoForLineAndColumn(data.lineNumber, data.columnNumber, data.breakpointInfo);
        };

        let contextMenu = WI.ContextMenu.createFromEvent(event);

        // Paused. Add Continue to Here option only if we have a script identifier for the location.
        if (WI.debuggerManager.paused) {
            let editorLineInfo = {lineNumber, columnNumber};
            let unformattedLineInfo = this._unformattedLineInfoForEditorLineInfo(editorLineInfo);
            let sourceCodeLocation = this._sourceCode.createSourceCodeLocation(unformattedLineInfo.lineNumber, unformattedLineInfo.columnNumber);

            let script;
            if (sourceCodeLocation.sourceCode instanceof WI.Script)
                script = sourceCodeLocation.sourceCode;
            else if (sourceCodeLocation.sourceCode instanceof WI.Resource)
                script = sourceCodeLocation.sourceCode.scriptForLocation(sourceCodeLocation);

            if (script) {
                contextMenu.appendItem(WI.UIString("Continue to Here"), () => {
                    WI.debuggerManager.continueToLocation(script, sourceCodeLocation.lineNumber, sourceCodeLocation.columnNumber);
                });
                contextMenu.appendSeparator();
            }
        }

        let breakpoints = [];
        for (let lineInfo of editorBreakpoints) {
            let breakpoint = this._breakpointForEditorLineInfo(lineInfo);
            console.assert(breakpoint);
            if (breakpoint)
                breakpoints.push(breakpoint);
        }

        // No breakpoints.
        if (!breakpoints.length) {
            contextMenu.appendItem(WI.UIString("Add Breakpoint"), addBreakpoint.bind(this));
            return;
        }

        // Single breakpoint.
        if (breakpoints.length === 1) {
            WI.breakpointPopoverController.appendContextMenuItems(contextMenu, breakpoints[0], event.target);

            if (!WI.isShowingSourcesTab()) {
                contextMenu.appendSeparator();
                contextMenu.appendItem(WI.UIString("Reveal in Sources Tab"), () => {
                    WI.showSourcesTab({breakpointToSelect: breakpoints[0]});
                });
            }

            return;
        }

        let shouldDisable = breakpoints.some((breakpoint) => !breakpoint.disabled);
        contextMenu.appendItem(shouldDisable ? WI.UIString("Disable Breakpoints") : WI.UIString("Enable Breakpoints"), () => {
            for (let breakpoint of breakpoints)
                breakpoint.disabled = shouldDisable;
        });

        contextMenu.appendItem(WI.UIString("Delete Breakpoints"), () => {
            for (let breakpoint of breakpoints)
                WI.debuggerManager.removeBreakpoint(breakpoint);
        });
    }

    textEditorBreakpointAdded(textEditor, lineNumber, columnNumber)
    {
        if (!this._supportsDebugging)
            return null;

        var editorLineInfo = {lineNumber, columnNumber};
        var unformattedLineInfo = this._unformattedLineInfoForEditorLineInfo(editorLineInfo);
        var sourceCodeLocation = this._sourceCode.createSourceCodeLocation(unformattedLineInfo.lineNumber, unformattedLineInfo.columnNumber);
        var breakpoint = new WI.Breakpoint(sourceCodeLocation);

        var lineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
        this._addBreakpointWithEditorLineInfo(breakpoint, lineInfo);

        this._ignoreBreakpointAddedBreakpoint = breakpoint;
        WI.debuggerManager.addBreakpoint(breakpoint);
        this._ignoreBreakpointAddedBreakpoint = null;

        // Return the more accurate location and breakpoint info.
        return {
            breakpointInfo: this._breakpointInfoForBreakpoint(breakpoint),
            lineNumber: lineInfo.lineNumber,
            columnNumber: lineInfo.columnNumber
        };
    }

    textEditorBreakpointRemoved(textEditor, lineNumber, columnNumber)
    {
        console.assert(this._supportsDebugging);
        if (!this._supportsDebugging)
            return;

        var lineInfo = {lineNumber, columnNumber};
        var breakpoint = this._breakpointForEditorLineInfo(lineInfo);
        console.assert(breakpoint);
        if (!breakpoint)
            return;

        this._removeBreakpointWithEditorLineInfo(breakpoint, lineInfo);

        this._ignoreBreakpointRemovedBreakpoint = breakpoint;
        WI.debuggerManager.removeBreakpoint(breakpoint);
        this._ignoreBreakpointRemovedBreakpoint = null;
    }

    textEditorBreakpointMoved(textEditor, oldLineNumber, oldColumnNumber, newLineNumber, newColumnNumber)
    {
        console.assert(this._supportsDebugging);
        if (!this._supportsDebugging)
            return;

        var oldLineInfo = {lineNumber: oldLineNumber, columnNumber: oldColumnNumber};
        var breakpoint = this._breakpointForEditorLineInfo(oldLineInfo);
        console.assert(breakpoint);
        if (!breakpoint)
            return;

        this._removeBreakpointWithEditorLineInfo(breakpoint, oldLineInfo);

        var newLineInfo = {lineNumber: newLineNumber, columnNumber: newColumnNumber};
        var unformattedNewLineInfo = this._unformattedLineInfoForEditorLineInfo(newLineInfo);
        this._ignoreLocationUpdateBreakpoint = breakpoint;
        breakpoint.sourceCodeLocation.update(this._sourceCode, unformattedNewLineInfo.lineNumber, unformattedNewLineInfo.columnNumber);
        this._ignoreLocationUpdateBreakpoint = null;

        var accurateNewLineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
        this._addBreakpointWithEditorLineInfo(breakpoint, accurateNewLineInfo);

        if (accurateNewLineInfo.lineNumber !== newLineInfo.lineNumber || accurateNewLineInfo.columnNumber !== newLineInfo.columnNumber)
            this.updateBreakpointLineAndColumn(newLineInfo.lineNumber, newLineInfo.columnNumber, accurateNewLineInfo.lineNumber, accurateNewLineInfo.columnNumber);
    }

    textEditorBreakpointClicked(textEditor, lineNumber, columnNumber)
    {
        console.assert(this._supportsDebugging);
        if (!this._supportsDebugging)
            return;

        var breakpoint = this._breakpointForEditorLineInfo({lineNumber, columnNumber});
        console.assert(breakpoint);
        if (!breakpoint)
            return;

        breakpoint.cycleToNextMode();
    }

    textEditorUpdatedFormatting(textEditor)
    {
        this._ignoreAllBreakpointLocationUpdates = true;
        this._sourceCode.formatterSourceMap = this.formatterSourceMap;
        this._ignoreAllBreakpointLocationUpdates = false;

        // Always put the source map on both the Script and Resource if both exist. For example,
        // if this SourceCode is a Resource, then there might also be a Script. In the debugger,
        // the backend identifies call frames with Script line and column information, and the
        // Script needs the formatter source map to produce the proper display line and column.
        if (this._sourceCode instanceof WI.Resource && !(this._sourceCode instanceof WI.SourceMapResource)) {
            var scripts = this._sourceCode.scripts;
            for (var i = 0; i < scripts.length; ++i)
                scripts[i].formatterSourceMap = this.formatterSourceMap;
        } else if (this._sourceCode instanceof WI.Script) {
            if (this._sourceCode.resource)
                this._sourceCode.resource.formatterSourceMap = this.formatterSourceMap;
        }

        this._handleFormatterDidChange();
    }

    textEditorExecutionHighlightRange(currentPosition, callback)
    {
        let position = this.currentPositionToOriginalPosition(currentPosition);

        let script = this._getAssociatedScript(position);
        if (!script) {
            callback(null);
            return;
        }

        let {startLine, startColumn} = script.range;

        function toInlineScriptPosition(position) {
            let columnNumber = position.lineNumber === startLine ? position.columnNumber - startColumn : position.columnNumber;
            return new WI.SourceCodePosition(position.lineNumber - startLine, columnNumber);
        }

        function fromInlineScriptPosition(position) {
            let columnNumber = position.lineNumber ? position.columnNumber : position.columnNumber + startColumn;
            return new WI.SourceCodePosition(position.lineNumber + startLine, columnNumber);
        }

        // When returning positions, convert to positions relative to the TextEditor content.
        let highlightSourceCodeRange = (startPosition, endPosition) => {
            startPosition = this.originalPositionToCurrentPosition(fromInlineScriptPosition(startPosition));
            endPosition = this.originalPositionToCurrentPosition(fromInlineScriptPosition(endPosition));
            callback({startPosition, endPosition});
        };

        script.requestScriptSyntaxTree((syntaxTree) => {
            // After requesting the tree, we still might get a null tree from a parse error.
            if (!syntaxTree) {
                callback(null);
                return;
            }

            // Convert to the position within the inline script before querying the AST.
            position = toInlineScriptPosition(position);
            let nodes = syntaxTree.containersOfPosition(position);
            if (!nodes.length) {
                callback(null);
                return;
            }

            // Find a node starting at this offset.
            // Avoid highlighting the entire program if this is the start of the first statement.
            // Special case the assignment expression inside of a for..of and for..in to highlight a larger range.
            for (let node of nodes) {
                if (node.startPosition.equals(position) && node.type !== WI.ScriptSyntaxTree.NodeType.Program) {
                    highlightSourceCodeRange(node.startPosition, node.endPosition);
                    return;
                }
                if (node.type === WI.ScriptSyntaxTree.NodeType.ForInStatement || node.type === WI.ScriptSyntaxTree.NodeType.ForOfStatement) {
                    if (node.left.startPosition.equals(position)) {
                        highlightSourceCodeRange(node.left.startPosition, node.right.endPosition);
                        return;
                    }
                }
                if (node.startPosition.isAfter(position))
                    break;
            }

            // Find a node ending at this offset. (Leaving a block).
            // We check this after ensuring nothing starts with this offset,
            // as that would be more important.
            for (let node of nodes) {
                if (node.endPosition.equals(position)) {
                    if (node.type === WI.ScriptSyntaxTree.NodeType.BlockStatement) {
                        // Closing brace of a block, only highlight the closing brace character.
                        highlightSourceCodeRange(position.offsetColumn(-1), position);
                        return;
                    }
                }
                if (node.startPosition.isAfter(position))
                    break;
            }

            // Find the best container node for this expression.
            // Sort by the tightest bounds so we can walk from specific to general nodes.
            nodes.sort((a, b) => {
                let aLength = a.range[1] - a.range[0];
                let bLength = b.range[1] - b.range[0];
                return aLength - bLength;
            });

            let characterAtPosition = this.getTextInRange(currentPosition, currentPosition.offsetColumn(1));
            let characterAtPositionIsDotOrBracket = characterAtPosition === "." || characterAtPosition === "[";

            for (let i = 0; i < nodes.length; ++i) {
                let node = nodes[i];

                // In a function call.
                if (node.type === WI.ScriptSyntaxTree.NodeType.CallExpression
                    || node.type === WI.ScriptSyntaxTree.NodeType.NewExpression
                    || node.type === WI.ScriptSyntaxTree.NodeType.ThrowStatement) {
                    highlightSourceCodeRange(node.startPosition, node.endPosition);
                    return;
                }

                // In the middle of a member expression we want to highlight the best
                // member expression range. We can end up in the middle when we are
                // paused inside of a getter and select the parent call frame. For
                // these cases we may be at a '.' or '[' and we can find the best member
                // expression from there.
                //
                // Examples:
                //
                //     foo*.x.y.z => inside x looking at parent call frame => |foo.x|.y.z
                //     foo.x*.y.z => inside y looking at parent call frame => |foo.x.y|.z
                //
                //     foo*["x"]["y"]["z"] => inside x looking at parent call frame => |foo["x"]|["y"]["z"]
                //     foo["x"]*["y"]["z"] => inside y looking at parent call frame => |foo["x"]["y"]|["z"]
                //
                if (node.type === WI.ScriptSyntaxTree.NodeType.ThisExpression
                    || (characterAtPositionIsDotOrBracket && (node.type === WI.ScriptSyntaxTree.NodeType.Identifier || node.type === WI.ScriptSyntaxTree.NodeType.MemberExpression))) {
                    let memberExpressionNode = null;
                    for (let j = i + 1; j < nodes.length; ++j) {
                        let nextNode = nodes[j];
                        if (nextNode.type === WI.ScriptSyntaxTree.NodeType.MemberExpression) {
                            memberExpressionNode = nextNode;
                            if (position.equals(memberExpressionNode.endPosition))
                                continue;
                        }
                        break;
                    }

                    if (memberExpressionNode) {
                        highlightSourceCodeRange(memberExpressionNode.startPosition, memberExpressionNode.endPosition);
                        return;
                    }

                    highlightSourceCodeRange(node.startPosition, node.endPosition);
                    return;
                }
            }

            // No matches, just highlight the line.
            callback(null);
        });
    }

    _clearIssueWidgets()
    {
        for (var widget of this._widgetMap.values())
            widget.clear();

        this._widgetMap.clear();
    }

    _reinsertAllIssues()
    {
        this._issuesLineNumberMap.clear();
        this._clearIssueWidgets();

        let issues = WI.consoleManager.issuesForSourceCode(this._sourceCode);
        for (let issue of issues)
            this._addIssue(issue);
    }

    _reinsertAllThreadIndicators()
    {
        // Clear line styles.
        for (let lineNumber of this._threadLineNumberMap.keys())
            this.removeStyleClassFromLine(lineNumber, "thread-indicator");
        this._threadLineNumberMap.clear();

        // Clear widgets.
        for (let widget of this._threadWidgetMap.values())
            widget.clear();
        this._threadWidgetMap.clear();

        // Clear other maps.
        this._threadTargetMap.clear();

        let debuggableTargets = WI.targets;
        if (debuggableTargets.length > 1) {
            for (let target of debuggableTargets)
                this._addThreadIndicatorForTarget(target);
        }
    }

    _debuggerDidPause(event)
    {
        this._updateTokenTrackingControllerState();
        if (this._typeTokenAnnotator && this._typeTokenAnnotator.isActive())
            this._typeTokenAnnotator.refresh();
        if (this._basicBlockAnnotator && this._basicBlockAnnotator.isActive())
            this._basicBlockAnnotator.refresh();
    }

    _debuggerDidResume(event)
    {
        this._updateTokenTrackingControllerState();
        this._dismissPopover();
        if (this._typeTokenAnnotator && this._typeTokenAnnotator.isActive())
            this._typeTokenAnnotator.refresh();
        if (this._basicBlockAnnotator && this._basicBlockAnnotator.isActive())
            this._basicBlockAnnotator.refresh();
    }

    _handleFormatterDidChange(event)
    {
        if (this._ignoreAllBreakpointLocationUpdates)
            return;

        // Some breakpoints / issues may have moved, some might not have. Just go through
        // and remove and reinsert all the breakpoints / issues.

        var oldBreakpointMap = this._breakpointMap;
        this._breakpointMap = {};

        for (var lineNumber in oldBreakpointMap) {
            for (var columnNumber in oldBreakpointMap[lineNumber]) {
                var breakpoint = oldBreakpointMap[lineNumber][columnNumber];
                var newLineInfo = this._editorLineInfoForSourceCodeLocation(breakpoint.sourceCodeLocation);
                this._addBreakpointWithEditorLineInfo(breakpoint, newLineInfo);
                this.setBreakpointInfoForLineAndColumn(lineNumber, columnNumber, null);
                this.setBreakpointInfoForLineAndColumn(newLineInfo.lineNumber, newLineInfo.columnNumber, this._breakpointInfoForBreakpoint(breakpoint));
            }
        }

        this._reinsertAllIssues();
        this._reinsertAllThreadIndicators();
    }

    _sourceCodeSourceMapAdded(event)
    {
        WI.notifications.addEventListener(WI.Notification.GlobalModifierKeysDidChange, this._updateTokenTrackingControllerState, this);
        this._sourceCode.removeEventListener(WI.SourceCode.Event.SourceMapAdded, this._sourceCodeSourceMapAdded, this);

        this._updateTokenTrackingControllerState();
    }

    _updateTokenTrackingControllerState()
    {
        var mode = WI.CodeMirrorTokenTrackingController.Mode.None;
        if (WI.debuggerManager.paused)
            mode = WI.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression;
        else if (this._typeTokenAnnotator && this._typeTokenAnnotator.isActive())
            mode = WI.CodeMirrorTokenTrackingController.Mode.JavaScriptTypeInformation;
        else if (this._hasColorMarkers())
            mode = WI.CodeMirrorTokenTrackingController.Mode.MarkedTokens;
        else if ((this._sourceCode instanceof WI.SourceMapResource || this._sourceCode.sourceMaps.length !== 0) && WI.modifierKeys.metaKey && !WI.modifierKeys.altKey && !WI.modifierKeys.shiftKey)
            mode = WI.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens;

        this.tokenTrackingController.enabled = mode !== WI.CodeMirrorTokenTrackingController.Mode.None;

        if (mode === this.tokenTrackingController.mode)
            return;

        switch (mode) {
        case WI.CodeMirrorTokenTrackingController.Mode.MarkedTokens:
            this.tokenTrackingController.mouseOverDelayDuration = 0;
            this.tokenTrackingController.mouseOutReleaseDelayDuration = 0;
            break;
        case WI.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens:
            this.tokenTrackingController.mouseOverDelayDuration = 0;
            this.tokenTrackingController.mouseOutReleaseDelayDuration = 0;
            this.tokenTrackingController.classNameForHighlightedRange = WI.CodeMirrorTokenTrackingController.JumpToSymbolHighlightStyleClassName;
            this._dismissPopover();
            break;
        case WI.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression:
        case WI.CodeMirrorTokenTrackingController.Mode.JavaScriptTypeInformation:
            this.tokenTrackingController.mouseOverDelayDuration = WI.SourceCodeTextEditor.DurationToMouseOverTokenToMakeHoveredToken;
            this.tokenTrackingController.mouseOutReleaseDelayDuration = WI.SourceCodeTextEditor.DurationToMouseOutOfHoveredTokenToRelease;
            this.tokenTrackingController.classNameForHighlightedRange = WI.SourceCodeTextEditor.HoveredExpressionHighlightStyleClassName;
            break;
        }

        this.tokenTrackingController.mode = mode;
    }

    _hasColorMarkers()
    {
        for (var marker of this.markers) {
            if (marker.type === WI.TextMarker.Type.Color)
                return true;
        }
        return false;
    }

    // CodeMirrorTokenTrackingController Delegate

    tokenTrackingControllerCanReleaseHighlightedRange(tokenTrackingController, element)
    {
        if (!this._popover)
            return true;

        if (!window.getSelection().isCollapsed && this._popover.element.contains(window.getSelection().anchorNode))
            return false;

        return true;
    }

    tokenTrackingControllerHighlightedRangeReleased(tokenTrackingController, forceHide = false)
    {
        if (forceHide || !this._mouseIsOverPopover)
            this._dismissPopover();
    }

    tokenTrackingControllerHighlightedRangeWasClicked(tokenTrackingController)
    {
        if (this.tokenTrackingController.mode !== WI.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens)
            return;

        // Links are handled by TextEditor.
        if (/\blink\b/.test(this.tokenTrackingController.candidate.hoveredToken.type))
            return;

        const options = {
            ignoreNetworkTab: true,
            ignoreSearchTab: true,
        };

        var sourceCodeLocation = this._sourceCodeLocationForEditorPosition(this.tokenTrackingController.candidate.hoveredTokenRange.start);
        if (this.sourceCode instanceof WI.SourceMapResource)
            WI.showOriginalOrFormattedSourceCodeLocation(sourceCodeLocation, options);
        else
            WI.showSourceCodeLocation(sourceCodeLocation, options);
    }

    tokenTrackingControllerNewHighlightCandidate(tokenTrackingController, candidate)
    {
        if (this.tokenTrackingController.mode === WI.CodeMirrorTokenTrackingController.Mode.NonSymbolTokens) {
            this.tokenTrackingController.highlightRange(candidate.hoveredTokenRange);
            return;
        }

        if (this.tokenTrackingController.mode === WI.CodeMirrorTokenTrackingController.Mode.JavaScriptExpression) {
            this._tokenTrackingControllerHighlightedJavaScriptExpression(candidate);
            return;
        }

        if (this.tokenTrackingController.mode === WI.CodeMirrorTokenTrackingController.Mode.JavaScriptTypeInformation) {
            this._tokenTrackingControllerHighlightedJavaScriptTypeInformation(candidate);
            return;
        }

        if (this.tokenTrackingController.mode === WI.CodeMirrorTokenTrackingController.Mode.MarkedTokens) {
            var markers = this.markersAtPosition(candidate.hoveredTokenRange.start);
            if (markers.length > 0)
                this._tokenTrackingControllerHighlightedMarkedExpression(candidate, markers);
            else
                this._dismissEditingController();
        }
    }

    tokenTrackingControllerMouseOutOfHoveredMarker(tokenTrackingController, hoveredMarker)
    {
        this._dismissEditingController();
    }

    _tokenTrackingControllerHighlightedJavaScriptExpression(candidate)
    {
        console.assert(candidate.expression);

        let target = WI.debuggerManager.activeCallFrame ? WI.debuggerManager.activeCallFrame.target : this.target;
        let expression = appendWebInspectorSourceURL(candidate.expression);

        function populate(error, result, wasThrown)
        {
            if (error || wasThrown)
                return;

            if (candidate !== this.tokenTrackingController.candidate)
                return;

            let data = WI.RemoteObject.fromPayload(result, target);
            switch (data.type) {
            case "function":
                this._showPopoverForFunction(data);
                break;
            case "object":
                if (data.subtype === "null" || data.subtype === "regexp")
                    this._showPopoverWithFormattedValue(data);
                else
                    this._showPopoverForObject(data);
                break;
            case "string":
            case "number":
            case "boolean":
            case "symbol":
            case "bigint":
            case "undefined":
                this._showPopoverWithFormattedValue(data);
                break;
            }
        }


        if (WI.debuggerManager.activeCallFrame) {
            target.DebuggerAgent.evaluateOnCallFrame.invoke({callFrameId: WI.debuggerManager.activeCallFrame.id, expression, objectGroup: "popover", doNotPauseOnExceptionsAndMuteConsole: true}, populate.bind(this));
            return;
        }

        // No call frame available. Use the SourceCode's page's context.
        target.RuntimeAgent.evaluate.invoke({expression, objectGroup: "popover", doNotPauseOnExceptionsAndMuteConsole: true}, populate.bind(this));
    }

    _tokenTrackingControllerHighlightedJavaScriptTypeInformation(candidate)
    {
        console.assert(candidate.expression);

        var sourceCode = this._sourceCode;
        var sourceID = sourceCode instanceof WI.Script ? sourceCode.id : sourceCode.scripts[0].id;
        var range = candidate.hoveredTokenRange;
        var offset = this.currentPositionToOriginalOffset(range.start);

        var allRequests = [{
            typeInformationDescriptor: WI.ScriptSyntaxTree.TypeProfilerSearchDescriptor.NormalExpression,
            sourceID,
            divot: offset
        }];

        function handler(error, allTypes) {
            if (error)
                return;

            if (candidate !== this.tokenTrackingController.candidate)
                return;

            console.assert(allTypes.length === 1);
            if (!allTypes.length)
                return;

            var typeDescription = WI.TypeDescription.fromPayload(allTypes[0]);
            if (typeDescription.valid) {
                var popoverTitle = WI.TypeTokenView.titleForPopover(WI.TypeTokenView.TitleType.Variable, candidate.expression);
                this.showPopoverForTypes(typeDescription, null, popoverTitle);
            }
        }

        this.target.RuntimeAgent.getRuntimeTypesForVariablesAtOffsets(allRequests, handler.bind(this));
    }

    _showPopover(content, bounds)
    {
        console.assert(this.tokenTrackingController.candidate || bounds);

        var shouldHighlightRange = false;
        var candidate = this.tokenTrackingController.candidate;
        // If bounds is falsey, this is a popover introduced from a hover event.
        // Otherwise, this is called from TypeTokenAnnotator.
        if (!bounds) {
            if (!candidate)
                return;

            var rects = this.rectsForRange(candidate.hoveredTokenRange);
            bounds = WI.Rect.unionOfRects(rects);

            if (this._popover && this._popover.visible) {
                let intersection = bounds.intersectionWithRect(this._popover.frame);
                if (intersection.size.width && intersection.size.height)
                    return;
            }

            shouldHighlightRange = true;
        }

        content.classList.add(WI.SourceCodeTextEditor.PopoverDebuggerContentStyleClassName);

        this._popover = this._popover || new WI.Popover(this);
        this._popover.presentNewContentWithFrame(content, bounds.pad(5), [WI.RectEdge.MIN_Y, WI.RectEdge.MAX_Y, WI.RectEdge.MAX_X]);
        if (shouldHighlightRange)
            this.tokenTrackingController.highlightRange(candidate.expressionRange);

        this._trackPopoverEvents();
    }

    _showPopoverForFunction(data)
    {
        let candidate = this.tokenTrackingController.candidate;

        function didGetDetails(error, response)
        {
            if (error) {
                console.error(error);
                this._dismissPopover();
                return;
            }

            // Nothing to do if the token has changed since the time we
            // asked for the function details from the backend.
            if (candidate !== this.tokenTrackingController.candidate)
                return;

            let content = document.createElement("div");
            content.classList.add("function");

            let title = document.createElement("div");
            title.classList.add("title");
            title.textContent = response.name || response.displayName || WI.UIString("(anonymous function)");
            content.appendChild(title);

            let location = response.location;
            let sourceCode = WI.debuggerManager.scriptForIdentifier(location.scriptId, this.target);
            let sourceCodeLocation = sourceCode.createSourceCodeLocation(location.lineNumber, location.columnNumber);
            let functionSourceCodeLink = WI.createSourceCodeLocationLink(sourceCodeLocation);
            title.appendChild(functionSourceCodeLink);

            let wrapper = document.createElement("div");
            wrapper.classList.add("body");
            content.appendChild(wrapper);

            let codeMirror = WI.CodeMirrorEditor.create(wrapper, {
                mode: "text/javascript",
                readOnly: "nocursor",
            });

            const isModule = false;
            const indentString = WI.indentString();
            const includeSourceMapData = false;
            let workerProxy = WI.FormatterWorkerProxy.singleton();
            workerProxy.formatJavaScript(data.description, isModule, indentString, includeSourceMapData, ({formattedText}) => {
                if (candidate !== this.tokenTrackingController.candidate)
                    return;

                this._showPopover(content);
                codeMirror.setValue(formattedText || data.description);
                this._popover.update();
            });
        }

        data.target.DebuggerAgent.getFunctionDetails(data.objectId, didGetDetails.bind(this));
    }

    _showPopoverForObject(data)
    {
        var content = document.createElement("div");
        content.className = "object expandable";

        var titleElement = document.createElement("div");
        titleElement.className = "title";
        titleElement.textContent = data.description;
        content.appendChild(titleElement);

        if (data.subtype === "node") {
            data.pushNodeToFrontend(function(nodeId) {
                if (!nodeId)
                    return;

                var domNode = WI.domManager.nodeForId(nodeId);
                if (!domNode.ownerDocument)
                    return;

                var goToButton = titleElement.appendChild(WI.createGoToArrowButton());
                goToButton.addEventListener("click", function() {
                    WI.domManager.inspectElement(nodeId);
                });
            });
        }

        // FIXME: If this is a variable, it would be nice to put the variable name in the PropertyPath.
        var objectTree = new WI.ObjectTreeView(data);
        objectTree.showOnlyProperties();
        objectTree.expand();

        var bodyElement = content.appendChild(document.createElement("div"));
        bodyElement.className = "body";
        bodyElement.appendChild(objectTree.element);

        // Show the popover once we have the first set of properties for the object.
        var candidate = this.tokenTrackingController.candidate;
        objectTree.addEventListener(WI.ObjectTreeView.Event.Updated, function() {
            if (candidate === this.tokenTrackingController.candidate)
                this._showPopover(content);
            objectTree.removeEventListener(null, null, this);
        }, this);
    }

    _showPopoverWithFormattedValue(remoteObject)
    {
        var content = WI.FormattedValue.createElementForRemoteObject(remoteObject);
        this._showPopover(content);
    }

    willDismissPopover(popover)
    {
        this.tokenTrackingController.removeHighlightedRange();

        this.target.RuntimeAgent.releaseObjectGroup("popover");
    }

    _dismissPopover()
    {
        if (!this._popover)
            return;

        this._popover.dismiss();

        if (this._popoverEventListeners && this._popoverEventListenersAreRegistered) {
            this._popoverEventListenersAreRegistered = false;
            this._popoverEventListeners.unregister();
        }
    }

    _trackPopoverEvents()
    {
        if (!this._popoverEventListeners)
            this._popoverEventListeners = new WI.EventListenerSet(this, "Popover listeners");
        if (!this._popoverEventListenersAreRegistered) {
            this._popoverEventListenersAreRegistered = true;
            this._popoverEventListeners.register(this._popover.element, "mouseover", this._popoverMouseover);
            this._popoverEventListeners.register(this._popover.element, "mouseout", this._popoverMouseout);
            this._popoverEventListeners.install();
        }
    }

    _popoverMouseover(event)
    {
        this._mouseIsOverPopover = true;
    }

    _popoverMouseout(event)
    {
        this._mouseIsOverPopover = this._popover.element.contains(event.relatedTarget);
    }

    _hasStyleSheetContents()
    {
        let mimeType = this.mimeType;
        return mimeType === "text/css"
            || mimeType === "text/x-less"
            || mimeType === "text/x-sass"
            || mimeType === "text/x-scss";
    }

    _updateEditableMarkers(range)
    {
        if (this._hasStyleSheetContents()) {
            this.createColorMarkers(range);
            this.createGradientMarkers(range);
            this.createCubicBezierMarkers(range);
            this.createSpringMarkers(range);
        }

        this._updateTokenTrackingControllerState();
    }

    _tokenTrackingControllerHighlightedMarkedExpression(candidate, markers)
    {
        // Look for the outermost editable marker.
        var editableMarker;
        for (var marker of markers) {
            if (!marker.range || !Object.values(WI.TextMarker.Type).includes(marker.type))
                continue;

            if (!editableMarker || (marker.range.startLine < editableMarker.range.startLine || (marker.range.startLine === editableMarker.range.startLine && marker.range.startColumn < editableMarker.range.startColumn)))
                editableMarker = marker;
        }

        if (!editableMarker) {
            this.tokenTrackingController.hoveredMarker = null;
            return;
        }

        if (this.tokenTrackingController.hoveredMarker === editableMarker)
            return;

        this._dismissEditingController();

        this.tokenTrackingController.hoveredMarker = editableMarker;

        this._editingController = this.editingControllerForMarker(editableMarker);

        if (marker.type === WI.TextMarker.Type.Color) {
            var color = this._editingController.value;
            if (!color || !color.valid) {
                editableMarker.clear();
                this._editingController = null;
                return;
            }
        }

        this._editingController.delegate = this;
        this._editingController.presentHoverMenu();
    }

    _dismissEditingController(discrete)
    {
        if (this._editingController)
            this._editingController.dismissHoverMenu(discrete);

        this.tokenTrackingController.hoveredMarker = null;
        this._editingController = null;
    }

    // CodeMirrorEditingController Delegate

    editingControllerDidStartEditing(editingController)
    {
        // We can pause the token tracking controller during editing, it will be reset
        // to the expected state by calling _updateEditableMarkers() in the
        // editingControllerDidFinishEditing delegate.
        this.tokenTrackingController.enabled = false;

        // We clear the marker since we'll reset it after editing.
        editingController.marker.clear();

        // We ignore content changes made as a result of color editing.
        this._ignoreContentDidChange++;
    }

    editingControllerDidFinishEditing(editingController)
    {
        this._updateEditableMarkers(editingController.range);

        this._ignoreContentDidChange--;

        this._editingController = null;
    }

    _setTypeTokenAnnotatorEnabledState(shouldActivate)
    {
        if (!this._typeTokenAnnotator)
            return;

        if (shouldActivate) {
            console.assert(this.visible, "Annotators should not be enabled if the TextEditor is not visible");

            this._typeTokenAnnotator.reset();

            if (!this._typeTokenScrollHandler)
                this._enableScrollEventsForTypeTokenAnnotator();
        } else {
            this._typeTokenAnnotator.clear();

            if (this._typeTokenScrollHandler)
                this._disableScrollEventsForTypeTokenAnnotator();
        }

        WI.settings.showJavaScriptTypeInformation.value = shouldActivate;

        this._updateTokenTrackingControllerState();
    }

    set _basicBlockAnnotatorEnabled(shouldActivate)
    {
        if (!this._basicBlockAnnotator)
            return;

        if (shouldActivate) {
            console.assert(this.visible, "Annotators should not be enabled if the TextEditor is not visible");

            console.assert(!this._basicBlockAnnotator.isActive());
            this._basicBlockAnnotator.reset();

            if (!this._controlFlowScrollHandler)
                this._enableScrollEventsForControlFlowAnnotator();
        } else {
            this._basicBlockAnnotator.clear();

            if (this._controlFlowScrollHandler)
                this._disableScrollEventsForControlFlowAnnotator();
        }

        WI.settings.enableControlFlowProfiler.value = shouldActivate;
    }

    _getAssociatedScript(position)
    {
        let script = null;

        if (this._sourceCode instanceof WI.Script)
            script = this._sourceCode;
        else if (this._sourceCode instanceof WI.Resource && this._sourceCode.scripts.length) {
            if (this._sourceCode.type === WI.Resource.Type.Script)
                script = this._sourceCode.scripts[0];
            else if (this._sourceCode.type === WI.Resource.Type.Document && position) {
                for (let inlineScript of this._sourceCode.scripts) {
                    if (inlineScript.range.contains(position.lineNumber, position.columnNumber)) {
                        if (isNaN(inlineScript.range.startOffset))
                            inlineScript.range.resolveOffsets(this._sourceCode.content);
                        script = inlineScript;
                        break;
                    }
                }
            }
        }

        return script;
    }

    _createTypeTokenAnnotator()
    {
        // COMPATIBILITY (iOS 8): Runtime.getRuntimeTypesForVariablesAtOffsets did not exist yet.
        if (!this.target.hasCommand("Runtime.getRuntimeTypesForVariablesAtOffsets"))
            return;

        var script = this._getAssociatedScript();
        if (!script)
            return;

        this._typeTokenAnnotator = new WI.TypeTokenAnnotator(this, script);
    }

    _createBasicBlockAnnotator()
    {
        // COMPATIBILITY (iOS 8): Runtime.getBasicBlocks did not exist yet.
        if (!this.target.hasCommand("Runtime.getBasicBlocks"))
            return;

        var script = this._getAssociatedScript();
        if (!script)
            return;

        this._basicBlockAnnotator = new WI.BasicBlockAnnotator(this, script);
    }

    _enableScrollEventsForTypeTokenAnnotator()
    {
        // Pause updating type tokens while scrolling to prevent frame loss.
        console.assert(!this._typeTokenScrollHandler);
        this._typeTokenScrollHandler = this._createTypeTokenScrollEventHandler();
        this.addScrollHandler(this._typeTokenScrollHandler);
    }

    _enableScrollEventsForControlFlowAnnotator()
    {
        console.assert(!this._controlFlowScrollHandler);
        this._controlFlowScrollHandler = this._createControlFlowScrollEventHandler();
        this.addScrollHandler(this._controlFlowScrollHandler);
    }

    _disableScrollEventsForTypeTokenAnnotator()
    {
        console.assert(this._typeTokenScrollHandler);
        this.removeScrollHandler(this._typeTokenScrollHandler);
        this._typeTokenScrollHandler = null;
    }

    _disableScrollEventsForControlFlowAnnotator()
    {
        console.assert(this._controlFlowScrollHandler);
        this.removeScrollHandler(this._controlFlowScrollHandler);
        this._controlFlowScrollHandler = null;
    }

    _createTypeTokenScrollEventHandler()
    {
        let timeoutIdentifier = null;
        let scrollHandler = () => {
            if (timeoutIdentifier)
                clearTimeout(timeoutIdentifier);
            else {
                if (this._typeTokenAnnotator)
                    this._typeTokenAnnotator.pause();
            }

            timeoutIdentifier = setTimeout(() => {
                timeoutIdentifier = null;
                if (this._typeTokenAnnotator)
                    this._typeTokenAnnotator.resume();
            }, WI.SourceCodeTextEditor.DurationToUpdateTypeTokensAfterScrolling);
        };

        return scrollHandler;
    }

    _createControlFlowScrollEventHandler()
    {
        let timeoutIdentifier = null;
        let scrollHandler = () => {
            if (timeoutIdentifier)
                clearTimeout(timeoutIdentifier);
            else if (this._basicBlockAnnotator)
                this._basicBlockAnnotator.pause();

            timeoutIdentifier = setTimeout(() => {
                timeoutIdentifier = null;
                if (this._basicBlockAnnotator)
                    this._basicBlockAnnotator.resume();
            }, WI.SourceCodeTextEditor.DurationToUpdateTypeTokensAfterScrolling);
        };

        return scrollHandler;
    }

    _logCleared(event)
    {
        for (let lineNumber of this._issuesLineNumberMap.keys()) {
            this.removeStyleClassFromLine(lineNumber, WI.SourceCodeTextEditor.LineErrorStyleClassName);
            this.removeStyleClassFromLine(lineNumber, WI.SourceCodeTextEditor.LineWarningStyleClassName);
        }

        this._issuesLineNumberMap.clear();
        this._clearIssueWidgets();
    }
};

WI.SourceCodeTextEditor.LineErrorStyleClassName = "error";
WI.SourceCodeTextEditor.LineWarningStyleClassName = "warning";
WI.SourceCodeTextEditor.PopoverDebuggerContentStyleClassName = "debugger-popover-content";
WI.SourceCodeTextEditor.HoveredExpressionHighlightStyleClassName = "hovered-expression-highlight";
WI.SourceCodeTextEditor.DurationToMouseOverTokenToMakeHoveredToken = 500;
WI.SourceCodeTextEditor.DurationToMouseOutOfHoveredTokenToRelease = 1000;
WI.SourceCodeTextEditor.DurationToUpdateTypeTokensAfterScrolling = 100;
WI.SourceCodeTextEditor.WidgetContainsMultipleIssuesSymbol = Symbol("source-code-widget-contains-multiple-issues");
WI.SourceCodeTextEditor.WidgetContainsMultipleThreadsSymbol = Symbol("source-code-widget-contains-multiple-threads");

WI.SourceCodeTextEditor.Event = {
    ContentWillPopulate: "source-code-text-editor-content-will-populate",
    ContentDidPopulate: "source-code-text-editor-content-did-populate"
};
