/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @unrestricted
 */
export default class DebuggerModel extends SDK.SDKModel {
  /**
   * @param {!SDK.Target} target
   */
  constructor(target) {
    super(target);

    target.registerDebuggerDispatcher(new DebuggerDispatcher(this));
    this._agent = target.debuggerAgent();
    this._runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel));

    /** @type {!SDK.SourceMapManager<!SDK.Script>} */
    this._sourceMapManager = new SDK.SourceMapManager(target);
    /** @type {!Map<string, !SDK.Script>} */
    this._sourceMapIdToScript = new Map();

    /** @type {?DebuggerPausedDetails} */
    this._debuggerPausedDetails = null;
    /** @type {!Map<string, !SDK.Script>} */
    this._scripts = new Map();
    /** @type {!Map.<string, !Array.<!SDK.Script>>} */
    this._scriptsBySourceURL = new Map();
    /** @type {!Array.<!SDK.Script>} */
    this._discardableScripts = [];

    /** @type {!Common.Object} */
    this._breakpointResolvedEventTarget = new Common.Object();

    /** @type {boolean} */
    this._autoStepOver = false;

    this._isPausing = false;
    Common.moduleSetting('pauseOnExceptionEnabled').addChangeListener(this._pauseOnExceptionStateChanged, this);
    Common.moduleSetting('pauseOnCaughtException').addChangeListener(this._pauseOnExceptionStateChanged, this);
    Common.moduleSetting('disableAsyncStackTraces').addChangeListener(this._asyncStackTracesStateChanged, this);
    Common.moduleSetting('breakpointsActive').addChangeListener(this._breakpointsActiveChanged, this);

    if (!target.suspended()) {
      this._enableDebugger();
    }

    /** @type {!Map<string, string>} */
    this._stringMap = new Map();
    this._sourceMapManager.setEnabled(Common.moduleSetting('jsSourceMapsEnabled').get());
    Common.moduleSetting('jsSourceMapsEnabled')
        .addChangeListener(event => this._sourceMapManager.setEnabled(/** @type {boolean} */ (event.data)));
  }

  /**
   * @param {string} executionContextId
   * @param {string} sourceURL
   * @param {?string} sourceMapURL
   * @return {?string}
   */
  static _sourceMapId(executionContextId, sourceURL, sourceMapURL) {
    if (!sourceMapURL) {
      return null;
    }
    return executionContextId + ':' + sourceURL + ':' + sourceMapURL;
  }

  /**
   * @return {!SDK.SourceMapManager<!SDK.Script>}
   */
  sourceMapManager() {
    return this._sourceMapManager;
  }

  /**
   * @return {!SDK.RuntimeModel}
   */
  runtimeModel() {
    return this._runtimeModel;
  }

  /**
   * @return {boolean}
   */
  debuggerEnabled() {
    return !!this._debuggerEnabled;
  }

  /**
   * @return {!Promise}
   */
  _enableDebugger() {
    if (this._debuggerEnabled) {
      return Promise.resolve();
    }
    this._debuggerEnabled = true;

    // Set a limit for the total size of collected script sources retained by debugger.
    // 10MB for remote frontends, 100MB for others.
    const isRemoteFrontend = Root.Runtime.queryParam('remoteFrontend') || Root.Runtime.queryParam('ws');
    const maxScriptsCacheSize = isRemoteFrontend ? 10e6 : 100e6;
    const enablePromise = this._agent.enable(maxScriptsCacheSize);
    enablePromise.then(this._registerDebugger.bind(this));
    this._pauseOnExceptionStateChanged();
    this._asyncStackTracesStateChanged();
    if (!Common.moduleSetting('breakpointsActive').get()) {
      this._breakpointsActiveChanged();
    }
    if (SDK.DebuggerModel._scheduledPauseOnAsyncCall) {
      this._pauseOnAsyncCall(SDK.DebuggerModel._scheduledPauseOnAsyncCall);
    }
    this.dispatchEventToListeners(Events.DebuggerWasEnabled, this);
    return enablePromise;
  }

  /**
   * @param {string|null} debuggerId
   */
  _registerDebugger(debuggerId) {
    if (!debuggerId) {
      return;
    }
    SDK.DebuggerModel._debuggerIdToModel.set(debuggerId, this);
    this._debuggerId = debuggerId;
    this.dispatchEventToListeners(Events.DebuggerIsReadyToPause, this);
  }

  /**
   * @return {boolean}
   */
  isReadyToPause() {
    return !!this._debuggerId;
  }

  /**
   * @param {string} debuggerId
   * @return {?DebuggerModel}
   */
  static modelForDebuggerId(debuggerId) {
    return SDK.DebuggerModel._debuggerIdToModel.get(debuggerId) || null;
  }

  /**
   * @return {!Promise}
   */
  _disableDebugger() {
    if (!this._debuggerEnabled) {
      return Promise.resolve();
    }
    this._debuggerEnabled = false;

    const disablePromise = this._agent.disable();
    this._isPausing = false;
    this._asyncStackTracesStateChanged();
    this.globalObjectCleared();
    this.dispatchEventToListeners(Events.DebuggerWasDisabled);
    SDK.DebuggerModel._debuggerIdToModel.delete(this._debuggerId);
    return disablePromise;
  }

  /**
   * @param {boolean} skip
   */
  _skipAllPauses(skip) {
    if (this._skipAllPausesTimeout) {
      clearTimeout(this._skipAllPausesTimeout);
      delete this._skipAllPausesTimeout;
    }
    this._agent.setSkipAllPauses(skip);
  }

  /**
   * @param {number} timeout
   */
  skipAllPausesUntilReloadOrTimeout(timeout) {
    if (this._skipAllPausesTimeout) {
      clearTimeout(this._skipAllPausesTimeout);
    }
    this._agent.setSkipAllPauses(true);
    // If reload happens before the timeout, the flag will be already unset and the timeout callback won't change anything.
    this._skipAllPausesTimeout = setTimeout(this._skipAllPauses.bind(this, false), timeout);
  }

  _pauseOnExceptionStateChanged() {
    let state;
    if (!Common.moduleSetting('pauseOnExceptionEnabled').get()) {
      state = PauseOnExceptionsState.DontPauseOnExceptions;
    } else if (Common.moduleSetting('pauseOnCaughtException').get()) {
      state = PauseOnExceptionsState.PauseOnAllExceptions;
    } else {
      state = PauseOnExceptionsState.PauseOnUncaughtExceptions;
    }

    this._agent.setPauseOnExceptions(state);
  }

  _asyncStackTracesStateChanged() {
    const maxAsyncStackChainDepth = 32;
    const enabled = !Common.moduleSetting('disableAsyncStackTraces').get() && this._debuggerEnabled;
    this._agent.setAsyncCallStackDepth(enabled ? maxAsyncStackChainDepth : 0);
  }

  _breakpointsActiveChanged() {
    this._agent.setBreakpointsActive(Common.moduleSetting('breakpointsActive').get());
  }

  stepInto() {
    this._agent.stepInto();
  }

  stepOver() {
    // Mark that in case of auto-stepping, we should be doing
    // step-over instead of step-in.
    this._autoStepOver = true;
    this._agent.stepOver();
  }

  stepOut() {
    this._agent.stepOut();
  }

  scheduleStepIntoAsync() {
    this._agent.invoke_stepInto({breakOnAsyncCall: true});
  }

  resume() {
    this._agent.resume();
    this._isPausing = false;
  }

  pause() {
    this._isPausing = true;
    this._skipAllPauses(false);
    this._agent.pause();
  }

  /**
   * @param {!Protocol.Runtime.StackTraceId} parentStackTraceId
   * @return {!Promise}
   */
  _pauseOnAsyncCall(parentStackTraceId) {
    return this._agent.invoke_pauseOnAsyncCall({parentStackTraceId: parentStackTraceId});
  }

  /**
   * @param {string} url
   * @param {number} lineNumber
   * @param {number=} columnNumber
   * @param {string=} condition
   * @return {!Promise<!SDK.DebuggerModel.SetBreakpointResult>}
   */
  async setBreakpointByURL(url, lineNumber, columnNumber, condition) {
    // Convert file url to node-js path.
    let urlRegex;
    if (this.target().type() === SDK.Target.Type.Node) {
      const platformPath = Common.ParsedURL.urlToPlatformPath(url, Host.isWin());
      urlRegex = `${platformPath.escapeForRegExp()}|${url.escapeForRegExp()}`;
    }
    // Adjust column if needed.
    let minColumnNumber = 0;
    const scripts = this._scriptsBySourceURL.get(url) || [];
    for (let i = 0, l = scripts.length; i < l; ++i) {
      const script = scripts[i];
      if (lineNumber === script.lineOffset) {
        minColumnNumber = minColumnNumber ? Math.min(minColumnNumber, script.columnOffset) : script.columnOffset;
      }
    }
    columnNumber = Math.max(columnNumber, minColumnNumber);
    const response = await this._agent.invoke_setBreakpointByUrl({
      lineNumber: lineNumber,
      url: urlRegex ? undefined : url,
      urlRegex: urlRegex,
      columnNumber: columnNumber,
      condition: condition
    });
    if (response[Protocol.Error]) {
      return {locations: [], breakpointId: null};
    }
    let locations = [];
    if (response.locations) {
      locations = response.locations.map(payload => Location.fromPayload(this, payload));
    }
    return {locations: locations, breakpointId: response.breakpointId};
  }

  /**
   * @param {string} scriptId
   * @param {string} scriptHash
   * @param {number} lineNumber
   * @param {number=} columnNumber
   * @param {string=} condition
   * @return {!Promise<!SDK.DebuggerModel.SetBreakpointResult>}
   */
  async setBreakpointInAnonymousScript(scriptId, scriptHash, lineNumber, columnNumber, condition) {
    const response = await this._agent.invoke_setBreakpointByUrl(
        {lineNumber: lineNumber, scriptHash: scriptHash, columnNumber: columnNumber, condition: condition});
    const error = response[Protocol.Error];
    if (error) {
      // Old V8 backend doesn't support scriptHash argument.
      if (error !== 'Either url or urlRegex must be specified.') {
        return {locations: [], breakpointId: null};
      }
      return this._setBreakpointBySourceId(scriptId, lineNumber, columnNumber, condition);
    }
    let locations = [];
    if (response.locations) {
      locations = response.locations.map(payload => Location.fromPayload(this, payload));
    }
    return {locations: locations, breakpointId: response.breakpointId};
  }

  /**
   * @param {string} scriptId
   * @param {number} lineNumber
   * @param {number=} columnNumber
   * @param {string=} condition
   * @return {!Promise<!SDK.DebuggerModel.SetBreakpointResult>}
   */
  async _setBreakpointBySourceId(scriptId, lineNumber, columnNumber, condition) {
    // This method is required for backward compatibility with V8 before 6.3.275.
    const response = await this._agent.invoke_setBreakpoint(
        {location: {scriptId: scriptId, lineNumber: lineNumber, columnNumber: columnNumber}, condition: condition});
    if (response[Protocol.Error]) {
      return {breakpointId: null, locations: []};
    }
    let actualLocation = [];
    if (response.actualLocation) {
      actualLocation = [Location.fromPayload(this, response.actualLocation)];
    }
    return {locations: actualLocation, breakpointId: response.breakpointId};
  }

  /**
   * @param {!Protocol.Debugger.BreakpointId} breakpointId
   * @return {!Promise}
   */
  async removeBreakpoint(breakpointId) {
    const response = await this._agent.invoke_removeBreakpoint({breakpointId});
    if (response[Protocol.Error]) {
      console.error('Failed to remove breakpoint: ' + response[Protocol.Error]);
    }
  }

  /**
   * @param {!Location} startLocation
   * @param {?Location} endLocation
   * @param {boolean} restrictToFunction
   * @return {!Promise<!Array<!BreakLocation>>}
   */
  async getPossibleBreakpoints(startLocation, endLocation, restrictToFunction) {
    const response = await this._agent.invoke_getPossibleBreakpoints({
      start: startLocation.payload(),
      end: endLocation ? endLocation.payload() : undefined,
      restrictToFunction: restrictToFunction
    });
    if (response[Protocol.Error] || !response.locations) {
      return [];
    }
    return response.locations.map(location => BreakLocation.fromPayload(this, location));
  }

  /**
   * @param {!Protocol.Runtime.StackTraceId} stackId
   * @return {!Promise<?Protocol.Runtime.StackTrace>}
   */
  async fetchAsyncStackTrace(stackId) {
    const response = await this._agent.invoke_getStackTrace({stackTraceId: stackId});
    return response[Protocol.Error] ? null : response.stackTrace;
  }

  /**
   * @param {!Protocol.Debugger.BreakpointId} breakpointId
   * @param {!Protocol.Debugger.Location} location
   */
  _breakpointResolved(breakpointId, location) {
    this._breakpointResolvedEventTarget.dispatchEventToListeners(breakpointId, Location.fromPayload(this, location));
  }

  globalObjectCleared() {
    this._setDebuggerPausedDetails(null);
    this._reset();
    // TODO(dgozman): move clients to ExecutionContextDestroyed/ScriptCollected events.
    this.dispatchEventToListeners(Events.GlobalObjectCleared, this);
  }

  _reset() {
    for (const scriptWithSourceMap of this._sourceMapIdToScript.values()) {
      this._sourceMapManager.detachSourceMap(scriptWithSourceMap);
    }
    this._sourceMapIdToScript.clear();

    this._scripts.clear();
    this._scriptsBySourceURL.clear();
    this._stringMap.clear();
    this._discardableScripts = [];
    this._autoStepOver = false;
  }

  /**
   * @return {!Array<!SDK.Script>}
   */
  scripts() {
    return Array.from(this._scripts.values());
  }

  /**
   * @param {!Protocol.Runtime.ScriptId} scriptId
   * @return {?SDK.Script}
   */
  scriptForId(scriptId) {
    return this._scripts.get(scriptId) || null;
  }

  /**
   * @return {!Array.<!SDK.Script>}
   */
  scriptsForSourceURL(sourceURL) {
    if (!sourceURL) {
      return [];
    }
    return this._scriptsBySourceURL.get(sourceURL) || [];
  }

  /**
   * @param {!SDK.ExecutionContext} executionContext
   * @return {!Array<!SDK.Script>}
   */
  scriptsForExecutionContext(executionContext) {
    const result = [];
    for (const script of this._scripts.values()) {
      if (script.executionContextId === executionContext.id) {
        result.push(script);
      }
    }
    return result;
  }

  /**
   * @param {!Protocol.Runtime.ScriptId} scriptId
   * @param {string} newSource
   * @param {function(?Protocol.Error, !Protocol.Runtime.ExceptionDetails=)} callback
   */
  setScriptSource(scriptId, newSource, callback) {
    this._scripts.get(scriptId).editSource(
        newSource, this._didEditScriptSource.bind(this, scriptId, newSource, callback));
  }

  /**
   * @param {!Protocol.Runtime.ScriptId} scriptId
   * @param {string} newSource
   * @param {function(?Protocol.Error, !Protocol.Runtime.ExceptionDetails=)} callback
   * @param {?Protocol.Error} error
   * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
   * @param {!Array.<!Protocol.Debugger.CallFrame>=} callFrames
   * @param {!Protocol.Runtime.StackTrace=} asyncStackTrace
   * @param {!Protocol.Runtime.StackTraceId=} asyncStackTraceId
   * @param {boolean=} needsStepIn
   */
  _didEditScriptSource(
      scriptId, newSource, callback, error, exceptionDetails, callFrames, asyncStackTrace, asyncStackTraceId,
      needsStepIn) {
    callback(error, exceptionDetails);
    if (needsStepIn) {
      this.stepInto();
      return;
    }

    if (!error && callFrames && callFrames.length) {
      this._pausedScript(
          callFrames, this._debuggerPausedDetails.reason, this._debuggerPausedDetails.auxData,
          this._debuggerPausedDetails.breakpointIds, asyncStackTrace, asyncStackTraceId);
    }
  }

  /**
   * @return {?Array.<!CallFrame>}
   */
  get callFrames() {
    return this._debuggerPausedDetails ? this._debuggerPausedDetails.callFrames : null;
  }

  /**
   * @return {?DebuggerPausedDetails}
   */
  debuggerPausedDetails() {
    return this._debuggerPausedDetails;
  }

  /**
   * @param {?DebuggerPausedDetails} debuggerPausedDetails
   * @return {boolean}
   */
  _setDebuggerPausedDetails(debuggerPausedDetails) {
    this._isPausing = false;
    this._debuggerPausedDetails = debuggerPausedDetails;
    if (this._debuggerPausedDetails) {
      if (this._beforePausedCallback) {
        if (!this._beforePausedCallback.call(null, this._debuggerPausedDetails)) {
          return false;
        }
      }
      // If we resolved a location in auto-stepping callback, reset the
      // step-over marker.
      this._autoStepOver = false;
      this.dispatchEventToListeners(Events.DebuggerPaused, this);
    }
    if (debuggerPausedDetails) {
      this.setSelectedCallFrame(debuggerPausedDetails.callFrames[0]);
    } else {
      this.setSelectedCallFrame(null);
    }
    return true;
  }

  /**
   * @param {?function(!DebuggerPausedDetails):boolean} callback
   */
  setBeforePausedCallback(callback) {
    this._beforePausedCallback = callback;
  }

  /**
   * @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
   * @param {string} reason
   * @param {!Object|undefined} auxData
   * @param {!Array.<string>} breakpointIds
   * @param {!Protocol.Runtime.StackTrace=} asyncStackTrace
   * @param {!Protocol.Runtime.StackTraceId=} asyncStackTraceId
   * @param {!Protocol.Runtime.StackTraceId=} asyncCallStackTraceId
   */
  async _pausedScript(
      callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId, asyncCallStackTraceId) {
    if (asyncCallStackTraceId) {
      // Note: this is only to support old backends. Newer ones do not send asyncCallStackTraceId.
      SDK.DebuggerModel._scheduledPauseOnAsyncCall = asyncCallStackTraceId;
      const promises = [];
      for (const model of SDK.DebuggerModel._debuggerIdToModel.values()) {
        promises.push(model._pauseOnAsyncCall(asyncCallStackTraceId));
      }
      await Promise.all(promises);
      this.resume();
      return;
    }

    const pausedDetails =
        new DebuggerPausedDetails(this, callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId);

    if (pausedDetails && this._continueToLocationCallback) {
      const callback = this._continueToLocationCallback;
      delete this._continueToLocationCallback;
      if (callback(pausedDetails)) {
        return;
      }
    }

    if (!this._setDebuggerPausedDetails(pausedDetails)) {
      if (this._autoStepOver) {
        this._agent.stepOver();
      } else {
        this._agent.stepInto();
      }
    }

    SDK.DebuggerModel._scheduledPauseOnAsyncCall = null;
  }

  _resumedScript() {
    this._setDebuggerPausedDetails(null);
    this.dispatchEventToListeners(Events.DebuggerResumed, this);
  }

  /**
   * @param {!Protocol.Runtime.ScriptId} scriptId
   * @param {string} sourceURL
   * @param {number} startLine
   * @param {number} startColumn
   * @param {number} endLine
   * @param {number} endColumn
   * @param {!Protocol.Runtime.ExecutionContextId} executionContextId
   * @param {string} hash
   * @param {*|undefined} executionContextAuxData
   * @param {boolean} isLiveEdit
   * @param {string|undefined} sourceMapURL
   * @param {boolean} hasSourceURLComment
   * @param {boolean} hasSyntaxError
   * @param {number} length
   * @param {?Protocol.Runtime.StackTrace} originStackTrace
   * @return {!SDK.Script}
   */
  _parsedScriptSource(
      scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
      executionContextAuxData, isLiveEdit, sourceMapURL, hasSourceURLComment, hasSyntaxError, length,
      originStackTrace) {
    if (this._scripts.has(scriptId)) {
      return this._scripts.get(scriptId);
    }
    let isContentScript = false;
    if (executionContextAuxData && ('isDefault' in executionContextAuxData)) {
      isContentScript = !executionContextAuxData['isDefault'];
    }
    sourceURL = this._internString(sourceURL);
    const script = new SDK.Script(
        this, scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId,
        this._internString(hash), isContentScript, isLiveEdit, sourceMapURL, hasSourceURLComment, length,
        originStackTrace);
    this._registerScript(script);
    this.dispatchEventToListeners(Events.ParsedScriptSource, script);

    const sourceMapId =
        SDK.DebuggerModel._sourceMapId(script.executionContextId, script.sourceURL, script.sourceMapURL);
    if (sourceMapId && !hasSyntaxError) {
      // Consecutive script evaluations in the same execution context with the same sourceURL
      // and sourceMappingURL should result in source map reloading.
      const previousScript = this._sourceMapIdToScript.get(sourceMapId);
      if (previousScript) {
        this._sourceMapManager.detachSourceMap(previousScript);
      }
      this._sourceMapIdToScript.set(sourceMapId, script);
      this._sourceMapManager.attachSourceMap(script, script.sourceURL, script.sourceMapURL);
    }

    const isDiscardable = hasSyntaxError && script.isAnonymousScript();
    if (isDiscardable) {
      this._discardableScripts.push(script);
      this._collectDiscardedScripts();
    }
    return script;
  }

  /**
   * @param {!SDK.Script} script
   * @param {string} newSourceMapURL
   */
  setSourceMapURL(script, newSourceMapURL) {
    let sourceMapId = SDK.DebuggerModel._sourceMapId(script.executionContextId, script.sourceURL, script.sourceMapURL);
    if (sourceMapId && this._sourceMapIdToScript.get(sourceMapId) === script) {
      this._sourceMapIdToScript.delete(sourceMapId);
    }
    this._sourceMapManager.detachSourceMap(script);

    script.sourceMapURL = newSourceMapURL;
    sourceMapId = SDK.DebuggerModel._sourceMapId(script.executionContextId, script.sourceURL, script.sourceMapURL);
    if (!sourceMapId) {
      return;
    }
    this._sourceMapIdToScript.set(sourceMapId, script);
    this._sourceMapManager.attachSourceMap(script, script.sourceURL, script.sourceMapURL);
  }

  /**
   * @param {!SDK.ExecutionContext} executionContext
   */
  executionContextDestroyed(executionContext) {
    const sourceMapIds = Array.from(this._sourceMapIdToScript.keys());
    for (const sourceMapId of sourceMapIds) {
      const script = this._sourceMapIdToScript.get(sourceMapId);
      if (script.executionContextId === executionContext.id) {
        this._sourceMapIdToScript.delete(sourceMapId);
        this._sourceMapManager.detachSourceMap(script);
      }
    }
  }

  /**
   * @param {!SDK.Script} script
   */
  _registerScript(script) {
    this._scripts.set(script.scriptId, script);
    if (script.isAnonymousScript()) {
      return;
    }

    let scripts = this._scriptsBySourceURL.get(script.sourceURL);
    if (!scripts) {
      scripts = [];
      this._scriptsBySourceURL.set(script.sourceURL, scripts);
    }
    scripts.push(script);
  }

  /**
   * @param {!SDK.Script} script
   */
  _unregisterScript(script) {
    console.assert(script.isAnonymousScript());
    this._scripts.delete(script.scriptId);
  }

  _collectDiscardedScripts() {
    if (this._discardableScripts.length < 1000) {
      return;
    }
    const scriptsToDiscard = this._discardableScripts.splice(0, 100);
    for (const script of scriptsToDiscard) {
      this._unregisterScript(script);
      this.dispatchEventToListeners(Events.DiscardedAnonymousScriptSource, script);
    }
  }

  /**
   * @param {!SDK.Script} script
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {?Location}
   */
  createRawLocation(script, lineNumber, columnNumber) {
    return new Location(this, script.scriptId, lineNumber, columnNumber);
  }

  /**
   * @param {string} sourceURL
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {?Location}
   */
  createRawLocationByURL(sourceURL, lineNumber, columnNumber) {
    let closestScript = null;
    const scripts = this._scriptsBySourceURL.get(sourceURL) || [];
    for (let i = 0, l = scripts.length; i < l; ++i) {
      const script = scripts[i];
      if (!closestScript) {
        closestScript = script;
      }
      if (script.lineOffset > lineNumber || (script.lineOffset === lineNumber && script.columnOffset > columnNumber)) {
        continue;
      }
      if (script.endLine < lineNumber || (script.endLine === lineNumber && script.endColumn <= columnNumber)) {
        continue;
      }
      closestScript = script;
      break;
    }
    return closestScript ? new Location(this, closestScript.scriptId, lineNumber, columnNumber) : null;
  }

  /**
   * @param {!Protocol.Runtime.ScriptId} scriptId
   * @param {number} lineNumber
   * @param {number} columnNumber
   * @return {?Location}
   */
  createRawLocationByScriptId(scriptId, lineNumber, columnNumber) {
    const script = this.scriptForId(scriptId);
    return script ? this.createRawLocation(script, lineNumber, columnNumber) : null;
  }

  /**
   * @param {!Protocol.Runtime.StackTrace} stackTrace
   * @return {!Array<!Location>}
   */
  createRawLocationsByStackTrace(stackTrace) {
    const frames = [];
    while (stackTrace) {
      for (const frame of stackTrace.callFrames) {
        frames.push(frame);
      }
      stackTrace = stackTrace.parent;
    }

    const rawLocations = [];
    for (const frame of frames) {
      const rawLocation = this.createRawLocationByScriptId(frame.scriptId, frame.lineNumber, frame.columnNumber);
      if (rawLocation) {
        rawLocations.push(rawLocation);
      }
    }
    return rawLocations;
  }

  /**
   * @return {boolean}
   */
  isPaused() {
    return !!this.debuggerPausedDetails();
  }

  /**
   * @return {boolean}
   */
  isPausing() {
    return this._isPausing;
  }

  /**
   * @param {?CallFrame} callFrame
   */
  setSelectedCallFrame(callFrame) {
    if (this._selectedCallFrame === callFrame) {
      return;
    }
    this._selectedCallFrame = callFrame;
    this.dispatchEventToListeners(Events.CallFrameSelected, this);
  }

  /**
   * @return {?CallFrame}
   */
  selectedCallFrame() {
    return this._selectedCallFrame;
  }

  /**
   * @param {!SDK.RuntimeModel.EvaluationOptions} options
   * @return {!Promise<!SDK.RuntimeModel.EvaluationResult>}
   */
  evaluateOnSelectedCallFrame(options) {
    return this.selectedCallFrame().evaluate(options);
  }

  /**
   * @param {!SDK.RemoteObject} remoteObject
   * @return {!Promise<?SDK.DebuggerModel.FunctionDetails>}
   */
  functionDetailsPromise(remoteObject) {
    return remoteObject.getAllProperties(false /* accessorPropertiesOnly */, false /* generatePreview */)
        .then(buildDetails.bind(this));

    /**
     * @param {!SDK.GetPropertiesResult} response
     * @return {?SDK.DebuggerModel.FunctionDetails}
     * @this {!DebuggerModel}
     */
    function buildDetails(response) {
      if (!response) {
        return null;
      }
      let location = null;
      if (response.internalProperties) {
        for (const prop of response.internalProperties) {
          if (prop.name === '[[FunctionLocation]]') {
            location = prop.value;
          }
        }
      }
      let functionName = null;
      if (response.properties) {
        for (const prop of response.properties) {
          if (prop.name === 'name' && prop.value && prop.value.type === 'string') {
            functionName = prop.value;
          }
          if (prop.name === 'displayName' && prop.value && prop.value.type === 'string') {
            functionName = prop.value;
            break;
          }
        }
      }
      let debuggerLocation = null;
      if (location) {
        debuggerLocation = this.createRawLocationByScriptId(
            location.value.scriptId, location.value.lineNumber, location.value.columnNumber);
      }
      return {location: debuggerLocation, functionName: functionName ? functionName.value : ''};
    }
  }

  /**
   * @param {number} scopeNumber
   * @param {string} variableName
   * @param {!Protocol.Runtime.CallArgument} newValue
   * @param {string} callFrameId
   * @return {!Promise<string|undefined>}
   */
  async setVariableValue(scopeNumber, variableName, newValue, callFrameId) {
    const response = await this._agent.invoke_setVariableValue({scopeNumber, variableName, newValue, callFrameId});
    const error = response[Protocol.Error];
    if (error) {
      console.error(error);
    }
    return error;
  }

  /**
   * @param {!Protocol.Debugger.BreakpointId} breakpointId
   * @param {function(!Common.Event)} listener
   * @param {!Object=} thisObject
   */
  addBreakpointListener(breakpointId, listener, thisObject) {
    this._breakpointResolvedEventTarget.addEventListener(breakpointId, listener, thisObject);
  }

  /**
   * @param {!Protocol.Debugger.BreakpointId} breakpointId
   * @param {function(!Common.Event)} listener
   * @param {!Object=} thisObject
   */
  removeBreakpointListener(breakpointId, listener, thisObject) {
    this._breakpointResolvedEventTarget.removeEventListener(breakpointId, listener, thisObject);
  }

  /**
   * @param {!Array<string>} patterns
   * @return {!Promise<boolean>}
   */
  async setBlackboxPatterns(patterns) {
    const response = await this._agent.invoke_setBlackboxPatterns({patterns});
    const error = response[Protocol.Error];
    if (error) {
      console.error(error);
    }
    return !error;
  }

  /**
   * @override
   */
  dispose() {
    this._sourceMapManager.dispose();
    SDK.DebuggerModel._debuggerIdToModel.delete(this._debuggerId);
    Common.moduleSetting('pauseOnExceptionEnabled').removeChangeListener(this._pauseOnExceptionStateChanged, this);
    Common.moduleSetting('pauseOnCaughtException').removeChangeListener(this._pauseOnExceptionStateChanged, this);
    Common.moduleSetting('disableAsyncStackTraces').removeChangeListener(this._asyncStackTracesStateChanged, this);
  }

  /**
   * @override
   * @return {!Promise}
   */
  async suspendModel() {
    await this._disableDebugger();
  }

  /**
   * @override
   * @return {!Promise}
   */
  async resumeModel() {
    await this._enableDebugger();
  }

  /**
   * @param {string} string
   * @return {string} string
   */
  _internString(string) {
    if (!this._stringMap.has(string)) {
      this._stringMap.set(string, string);
    }
    return this._stringMap.get(string);
  }
}

/** @type {!Map<string, !SDK.DebuggerModel>} */
export const _debuggerIdToModel = new Map();

/** @type {?Protocol.Runtime.StackTraceId} */
export const _scheduledPauseOnAsyncCall = null;

/**
 * Keep these in sync with WebCore::V8Debugger
 *
 * @enum {string}
 */
export const PauseOnExceptionsState = {
  DontPauseOnExceptions: 'none',
  PauseOnAllExceptions: 'all',
  PauseOnUncaughtExceptions: 'uncaught'
};

/** @enum {symbol} */
export const Events = {
  DebuggerWasEnabled: Symbol('DebuggerWasEnabled'),
  DebuggerWasDisabled: Symbol('DebuggerWasDisabled'),
  DebuggerPaused: Symbol('DebuggerPaused'),
  DebuggerResumed: Symbol('DebuggerResumed'),
  ParsedScriptSource: Symbol('ParsedScriptSource'),
  FailedToParseScriptSource: Symbol('FailedToParseScriptSource'),
  DiscardedAnonymousScriptSource: Symbol('DiscardedAnonymousScriptSource'),
  GlobalObjectCleared: Symbol('GlobalObjectCleared'),
  CallFrameSelected: Symbol('CallFrameSelected'),
  ConsoleCommandEvaluatedInSelectedCallFrame: Symbol('ConsoleCommandEvaluatedInSelectedCallFrame'),
  DebuggerIsReadyToPause: Symbol('DebuggerIsReadyToPause'),
};

/** @enum {string} */
export const BreakReason = {
  DOM: 'DOM',
  EventListener: 'EventListener',
  XHR: 'XHR',
  Exception: 'exception',
  PromiseRejection: 'promiseRejection',
  Assert: 'assert',
  DebugCommand: 'debugCommand',
  OOM: 'OOM',
  Other: 'other'
};

const ContinueToLocationTargetCallFrames = {
  Any: 'any',
  Current: 'current'
};

/**
 * @extends {Protocol.DebuggerDispatcher}
 * @unrestricted
 */
class DebuggerDispatcher {
  /**
   * @param {!DebuggerModel} debuggerModel
   */
  constructor(debuggerModel) {
    this._debuggerModel = debuggerModel;
  }

  /**
   * @override
   * @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
   * @param {string} reason
   * @param {!Object=} auxData
   * @param {!Array.<string>=} breakpointIds
   * @param {!Protocol.Runtime.StackTrace=} asyncStackTrace
   * @param {!Protocol.Runtime.StackTraceId=} asyncStackTraceId
   * @param {!Protocol.Runtime.StackTraceId=} asyncCallStackTraceId
   */
  paused(callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId, asyncCallStackTraceId) {
    this._debuggerModel._pausedScript(
        callFrames, reason, auxData, breakpointIds || [], asyncStackTrace, asyncStackTraceId, asyncCallStackTraceId);
  }

  /**
   * @override
   */
  resumed() {
    this._debuggerModel._resumedScript();
  }

  /**
   * @override
   * @param {!Protocol.Runtime.ScriptId} scriptId
   * @param {string} sourceURL
   * @param {number} startLine
   * @param {number} startColumn
   * @param {number} endLine
   * @param {number} endColumn
   * @param {!Protocol.Runtime.ExecutionContextId} executionContextId
   * @param {string} hash
   * @param {*=} executionContextAuxData
   * @param {boolean=} isLiveEdit
   * @param {string=} sourceMapURL
   * @param {boolean=} hasSourceURL
   * @param {boolean=} isModule
   * @param {number=} length
   * @param {!Protocol.Runtime.StackTrace=} stackTrace
   */
  scriptParsed(
      scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
      executionContextAuxData, isLiveEdit, sourceMapURL, hasSourceURL, isModule, length, stackTrace) {
    this._debuggerModel._parsedScriptSource(
        scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
        executionContextAuxData, !!isLiveEdit, sourceMapURL, !!hasSourceURL, false, length || 0, stackTrace || null);
  }

  /**
   * @override
   * @param {!Protocol.Runtime.ScriptId} scriptId
   * @param {string} sourceURL
   * @param {number} startLine
   * @param {number} startColumn
   * @param {number} endLine
   * @param {number} endColumn
   * @param {!Protocol.Runtime.ExecutionContextId} executionContextId
   * @param {string} hash
   * @param {*=} executionContextAuxData
   * @param {string=} sourceMapURL
   * @param {boolean=} hasSourceURL
   * @param {boolean=} isModule
   * @param {number=} length
   * @param {!Protocol.Runtime.StackTrace=} stackTrace
   */
  scriptFailedToParse(
      scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
      executionContextAuxData, sourceMapURL, hasSourceURL, isModule, length, stackTrace) {
    this._debuggerModel._parsedScriptSource(
        scriptId, sourceURL, startLine, startColumn, endLine, endColumn, executionContextId, hash,
        executionContextAuxData, false, sourceMapURL, !!hasSourceURL, true, length || 0, stackTrace || null);
  }

  /**
   * @override
   * @param {!Protocol.Debugger.BreakpointId} breakpointId
   * @param {!Protocol.Debugger.Location} location
   */
  breakpointResolved(breakpointId, location) {
    this._debuggerModel._breakpointResolved(breakpointId, location);
  }
}

/**
 * @unrestricted
 */
export class Location {
  /**
   * @param {!DebuggerModel} debuggerModel
   * @param {string} scriptId
   * @param {number} lineNumber
   * @param {number=} columnNumber
   */
  constructor(debuggerModel, scriptId, lineNumber, columnNumber) {
    this.debuggerModel = debuggerModel;
    this.scriptId = scriptId;
    this.lineNumber = lineNumber;
    this.columnNumber = columnNumber || 0;
  }

  /**
   * @param {!DebuggerModel} debuggerModel
   * @param {!Protocol.Debugger.Location} payload
   * @return {!Location}
   */
  static fromPayload(debuggerModel, payload) {
    return new Location(debuggerModel, payload.scriptId, payload.lineNumber, payload.columnNumber);
  }

  /**
   * @return {!Protocol.Debugger.Location}
   */
  payload() {
    return {scriptId: this.scriptId, lineNumber: this.lineNumber, columnNumber: this.columnNumber};
  }

  /**
   * @return {?SDK.Script}
   */
  script() {
    return this.debuggerModel.scriptForId(this.scriptId);
  }

  /**
   * @param {function()=} pausedCallback
   */
  continueToLocation(pausedCallback) {
    if (pausedCallback) {
      this.debuggerModel._continueToLocationCallback = this._paused.bind(this, pausedCallback);
    }
    this.debuggerModel._agent.continueToLocation(this.payload(), ContinueToLocationTargetCallFrames.Current);
  }

  /**
   * @param {function()|undefined} pausedCallback
   * @param {!DebuggerPausedDetails} debuggerPausedDetails
   * @return {boolean}
   */
  _paused(pausedCallback, debuggerPausedDetails) {
    const location = debuggerPausedDetails.callFrames[0].location();
    if (location.scriptId === this.scriptId && location.lineNumber === this.lineNumber &&
        location.columnNumber === this.columnNumber) {
      pausedCallback();
      return true;
    }
    return false;
  }

  /**
   * @return {string}
   */
  id() {
    return this.debuggerModel.target().id() + ':' + this.scriptId + ':' + this.lineNumber + ':' + this.columnNumber;
  }
}

/**
 * @unrestricted
 */
export class BreakLocation extends Location {
  /**
   * @param {!DebuggerModel} debuggerModel
   * @param {string} scriptId
   * @param {number} lineNumber
   * @param {number=} columnNumber
   * @param {!Protocol.Debugger.BreakLocationType=} type
   */
  constructor(debuggerModel, scriptId, lineNumber, columnNumber, type) {
    super(debuggerModel, scriptId, lineNumber, columnNumber);
    if (type) {
      this.type = type;
    }
  }

  /**
   * @override
   * @param {!DebuggerModel} debuggerModel
   * @param {!Protocol.Debugger.BreakLocation} payload
   * @return {!BreakLocation}
   */
  static fromPayload(debuggerModel, payload) {
    return new BreakLocation(debuggerModel, payload.scriptId, payload.lineNumber, payload.columnNumber, payload.type);
  }
}

/**
 * @unrestricted
 */
export class CallFrame {
  /**
   * @param {!DebuggerModel} debuggerModel
   * @param {!SDK.Script} script
   * @param {!Protocol.Debugger.CallFrame} payload
   */
  constructor(debuggerModel, script, payload) {
    this.debuggerModel = debuggerModel;
    this._script = script;
    this._payload = payload;
    this._location = Location.fromPayload(debuggerModel, payload.location);
    this._scopeChain = [];
    this._localScope = null;
    for (let i = 0; i < payload.scopeChain.length; ++i) {
      const scope = new Scope(this, i);
      this._scopeChain.push(scope);
      if (scope.type() === Protocol.Debugger.ScopeType.Local) {
        this._localScope = scope;
      }
    }
    if (payload.functionLocation) {
      this._functionLocation = Location.fromPayload(debuggerModel, payload.functionLocation);
    }
    this._returnValue =
        payload.returnValue ? this.debuggerModel._runtimeModel.createRemoteObject(payload.returnValue) : null;
  }

  /**
   * @param {!DebuggerModel} debuggerModel
   * @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
   * @return {!Array.<!CallFrame>}
   */
  static fromPayloadArray(debuggerModel, callFrames) {
    const result = [];
    for (let i = 0; i < callFrames.length; ++i) {
      const callFrame = callFrames[i];
      const script = debuggerModel.scriptForId(callFrame.location.scriptId);
      if (script) {
        result.push(new CallFrame(debuggerModel, script, callFrame));
      }
    }
    return result;
  }

  /**
   * @return {!SDK.Script}
   */
  get script() {
    return this._script;
  }

  /**
   * @return {string}
   */
  get id() {
    return this._payload.callFrameId;
  }

  /**
   * @return {!Array.<!Scope>}
   */
  scopeChain() {
    return this._scopeChain;
  }

  /**
   * @return {?Scope}
   */
  localScope() {
    return this._localScope;
  }

  /**
   * @return {?SDK.RemoteObject}
   */
  thisObject() {
    return this._payload.this ? this.debuggerModel._runtimeModel.createRemoteObject(this._payload.this) : null;
  }

  /**
   * @return {?SDK.RemoteObject}
   */
  returnValue() {
    return this._returnValue;
  }

  /**
   * @param {string} expression
   * @return {!Promise<?SDK.RemoteObject>}
   */
  async setReturnValue(expression) {
    if (!this._returnValue) {
      return null;
    }

    const evaluateResponse = await this.debuggerModel._agent.invoke_evaluateOnCallFrame(
        {callFrameId: this.id, expression: expression, silent: true, objectGroup: 'backtrace'});
    if (evaluateResponse[Protocol.Error] || evaluateResponse.exceptionDetails) {
      return null;
    }
    const response = await this.debuggerModel._agent.invoke_setReturnValue({newValue: evaluateResponse.result});
    if (response[Protocol.Error]) {
      return null;
    }
    this._returnValue = this.debuggerModel._runtimeModel.createRemoteObject(evaluateResponse.result);
    return this._returnValue;
  }

  /**
   * @return {string}
   */
  get functionName() {
    return this._payload.functionName;
  }

  /**
   * @return {!Location}
   */
  location() {
    return this._location;
  }

  /**
   * @return {?Location}
   */
  functionLocation() {
    return this._functionLocation || null;
  }

  /**
   * @param {!SDK.RuntimeModel.EvaluationOptions} options
   * @return {!Promise<!SDK.RuntimeModel.EvaluationResult>}
   */
  async evaluate(options) {
    const runtimeModel = this.debuggerModel.runtimeModel();
    // Assume backends either support both throwOnSideEffect and timeout options or neither.
    const needsTerminationOptions = !!options.throwOnSideEffect || options.timeout !== undefined;
    if (needsTerminationOptions &&
        (runtimeModel.hasSideEffectSupport() === false ||
         (runtimeModel.hasSideEffectSupport() === null && !await runtimeModel.checkSideEffectSupport()))) {
      return {error: 'Side-effect checks not supported by backend.'};
    }

    const response = await this.debuggerModel._agent.invoke_evaluateOnCallFrame({
      callFrameId: this.id,
      expression: options.expression,
      objectGroup: options.objectGroup,
      includeCommandLineAPI: options.includeCommandLineAPI,
      silent: options.silent,
      returnByValue: options.returnByValue,
      generatePreview: options.generatePreview,
      throwOnSideEffect: options.throwOnSideEffect,
      timeout: options.timeout
    });
    const error = response[Protocol.Error];
    if (error) {
      console.error(error);
      return {error: error};
    }
    return {object: runtimeModel.createRemoteObject(response.result), exceptionDetails: response.exceptionDetails};
  }

  async restart() {
    const response = await this.debuggerModel._agent.invoke_restartFrame({callFrameId: this._payload.callFrameId});
    if (!response[Protocol.Error]) {
      this.debuggerModel.stepInto();
    }
  }
}

/**
 * @unrestricted
 */
export class Scope {
  /**
   * @param {!CallFrame} callFrame
   * @param {number} ordinal
   */
  constructor(callFrame, ordinal) {
    this._callFrame = callFrame;
    this._payload = callFrame._payload.scopeChain[ordinal];
    this._type = this._payload.type;
    this._name = this._payload.name;
    this._ordinal = ordinal;
    this._startLocation =
        this._payload.startLocation ? Location.fromPayload(callFrame.debuggerModel, this._payload.startLocation) : null;
    this._endLocation =
        this._payload.endLocation ? Location.fromPayload(callFrame.debuggerModel, this._payload.endLocation) : null;
  }

  /**
   * @return {!CallFrame}
   */
  callFrame() {
    return this._callFrame;
  }

  /**
   * @return {string}
   */
  type() {
    return this._type;
  }

  /**
   * @return {string}
   */
  typeName() {
    switch (this._type) {
      case Protocol.Debugger.ScopeType.Local:
        return Common.UIString('Local');
      case Protocol.Debugger.ScopeType.Closure:
        return Common.UIString('Closure');
      case Protocol.Debugger.ScopeType.Catch:
        return Common.UIString('Catch');
      case Protocol.Debugger.ScopeType.Block:
        return Common.UIString('Block');
      case Protocol.Debugger.ScopeType.Script:
        return Common.UIString('Script');
      case Protocol.Debugger.ScopeType.With:
        return Common.UIString('With Block');
      case Protocol.Debugger.ScopeType.Global:
        return Common.UIString('Global');
      case Protocol.Debugger.ScopeType.Module:
        return Common.UIString('Module');
    }
    return '';
  }


  /**
   * @return {string|undefined}
   */
  name() {
    return this._name;
  }

  /**
   * @return {?Location}
   */
  startLocation() {
    return this._startLocation;
  }

  /**
   * @return {?Location}
   */
  endLocation() {
    return this._endLocation;
  }

  /**
   * @return {!SDK.RemoteObject}
   */
  object() {
    if (this._object) {
      return this._object;
    }
    const runtimeModel = this._callFrame.debuggerModel._runtimeModel;

    const declarativeScope =
        this._type !== Protocol.Debugger.ScopeType.With && this._type !== Protocol.Debugger.ScopeType.Global;
    if (declarativeScope) {
      this._object = runtimeModel.createScopeRemoteObject(
          this._payload.object, new SDK.ScopeRef(this._ordinal, this._callFrame.id));
    } else {
      this._object = runtimeModel.createRemoteObject(this._payload.object);
    }

    return this._object;
  }

  /**
   * @return {string}
   */
  description() {
    const declarativeScope =
        this._type !== Protocol.Debugger.ScopeType.With && this._type !== Protocol.Debugger.ScopeType.Global;
    return declarativeScope ? '' : (this._payload.object.description || '');
  }
}

/**
 * @unrestricted
 */
export class DebuggerPausedDetails {
  /**
   * @param {!DebuggerModel} debuggerModel
   * @param {!Array.<!Protocol.Debugger.CallFrame>} callFrames
   * @param {string} reason
   * @param {!Object|undefined} auxData
   * @param {!Array.<string>} breakpointIds
   * @param {!Protocol.Runtime.StackTrace=} asyncStackTrace
   * @param {!Protocol.Runtime.StackTraceId=} asyncStackTraceId
   */
  constructor(debuggerModel, callFrames, reason, auxData, breakpointIds, asyncStackTrace, asyncStackTraceId) {
    this.debuggerModel = debuggerModel;
    this.callFrames = CallFrame.fromPayloadArray(debuggerModel, callFrames);
    this.reason = reason;
    this.auxData = auxData;
    this.breakpointIds = breakpointIds;
    if (asyncStackTrace) {
      this.asyncStackTrace = this._cleanRedundantFrames(asyncStackTrace);
    }
    this.asyncStackTraceId = asyncStackTraceId;
  }

  /**
   * @return {?SDK.RemoteObject}
   */
  exception() {
    if (this.reason !== BreakReason.Exception && this.reason !== BreakReason.PromiseRejection) {
      return null;
    }
    return this.debuggerModel._runtimeModel.createRemoteObject(
        /** @type {!Protocol.Runtime.RemoteObject} */ (this.auxData));
  }

  /**
   * @param {!Protocol.Runtime.StackTrace} asyncStackTrace
   * @return {!Protocol.Runtime.StackTrace}
   */
  _cleanRedundantFrames(asyncStackTrace) {
    let stack = asyncStackTrace;
    let previous = null;
    while (stack) {
      if (stack.description === 'async function' && stack.callFrames.length) {
        stack.callFrames.shift();
      }
      if (previous && !stack.callFrames.length) {
        previous.parent = stack.parent;
      } else {
        previous = stack;
      }
      stack = stack.parent;
    }
    return asyncStackTrace;
  }
}

/* Legacy exported object */
self.SDK = self.SDK || {};

/* Legacy exported object */
SDK = SDK || {};

/** @constructor */
SDK.DebuggerModel = DebuggerModel;

/** @enum {string} */
SDK.DebuggerModel.PauseOnExceptionsState = PauseOnExceptionsState;

/** @enum {symbol} */
SDK.DebuggerModel.Events = Events;

/** @enum {string} */
SDK.DebuggerModel.BreakReason = BreakReason;

/** @constructor */
SDK.DebuggerModel.Location = Location;

/** @constructor */
SDK.DebuggerModel.BreakLocation = BreakLocation;

/** @constructor */
SDK.DebuggerModel.CallFrame = CallFrame;

/** @constructor */
SDK.DebuggerModel.Scope = Scope;

/** @constructor */
SDK.DebuggerPausedDetails = DebuggerPausedDetails;

SDK.SDKModel.register(SDK.DebuggerModel, SDK.Target.Capability.JS, true);

/** @typedef {{location: ?Location, functionName: string}} */
SDK.DebuggerModel.FunctionDetails;

/** @typedef {{
 *    breakpointId: ?Protocol.Debugger.BreakpointId,
 *    locations: !Array<!Location>
 *  }}
 */
SDK.DebuggerModel.SetBreakpointResult;

/** @type {!Map<string, !SDK.DebuggerModel>} */
SDK.DebuggerModel._debuggerIdToModel = _debuggerIdToModel;

/** @type {?Protocol.Runtime.StackTraceId} */
SDK.DebuggerModel._scheduledPauseOnAsyncCall = _scheduledPauseOnAsyncCall;
