/*
 * 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);

        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(WI.ConsoleManager.Event.IssueAdded, this._issueWasAdded, this);

        if (this._sourceCode instanceof WI.SourceMapResource || this._sourceCode.sourceMaps.length > 0)
            WI.notifications.removeEventListener(WI.Notification.GlobalModifierKeysDidChange, this._updateTokenTrackingControllerState, this);
        else
            this._sourceCode.removeEventListener(WI.SourceCode.Event.SourceMapAdded, this._sourceCodeSourceMapAdded, 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;

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

        if (this._sourceCode instanceof WI.Resource)
            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;

        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;
    }

    _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)
            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.settings.experimentalEnableSourcesTab.value) {
                if (!WI.isShowingSourcesTab()) {
                    contextMenu.appendSeparator();
                    contextMenu.appendItem(WI.UIString("Reveal in Sources Tab"), () => {
                        WI.showSourcesTab({breakpointToSelect: breakpoints[0]});
                    });
                }
            } else {
                if (!WI.isShowingDebuggerTab()) {
                    contextMenu.appendSeparator();
                    contextMenu.appendItem(WI.UIString("Reveal in Debugger Tab"), () => {
                        WI.showDebuggerTab({breakpointToSelect: breakpoints[0]});
                    });
                }
            }

            return;
        }

        // Multiple breakpoints.
        let removeBreakpoints = () => {
            for (let breakpoint of breakpoints) {
                if (WI.debuggerManager.isBreakpointRemovable(breakpoint))
                    WI.debuggerManager.removeBreakpoint(breakpoint);
            }
        };

        let shouldDisable = breakpoints.some((breakpoint) => !breakpoint.disabled);
        let toggleBreakpoints = (shouldDisable) => {
            for (let breakpoint of breakpoints)
                breakpoint.disabled = shouldDisable;
        };

        if (shouldDisable)
            contextMenu.appendItem(WI.UIString("Disable Breakpoints"), toggleBreakpoints);
        else
            contextMenu.appendItem(WI.UIString("Enable Breakpoints"), toggleBreakpoints);
        contextMenu.appendItem(WI.UIString("Delete Breakpoints"), removeBreakpoints);
    }

    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;
        }

        // 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();
    }

    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();
    }

    _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 "undefined":
            case "symbol":
                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), target.DebuggerAgent);
            return;
        }

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

    _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.RuntimeAgent.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.RuntimeAgent.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"
};
