text: /*
   * Copyright (C) 2012 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
   */
  SDK.RuntimeModel = class extends SDK.SDKModel {
    /**
     * @param {!SDK.Target} target
     */
    constructor(target) {
      super(target);
  
      this._agent = target.runtimeAgent();
      this.target().registerRuntimeDispatcher(new SDK.RuntimeDispatcher(this));
      this._agent.enable();
      /** @type {!Map<number, !SDK.ExecutionContext>} */
      this._executionContextById = new Map();
      this._executionContextComparator = SDK.ExecutionContext.comparator;
      /** @type {?boolean} */
      this._hasSideEffectSupport = null;
  
      if (Common.moduleSetting('customFormatters').get())
        this._agent.setCustomObjectFormatterEnabled(true);
  
      Common.moduleSetting('customFormatters').addChangeListener(this._customFormattersStateChanged.bind(this));
    }
  
    /**
     * @param {string} code
     * @return {string}
     */
    static wrapObjectLiteralExpressionIfNeeded(code) {
      // Only parenthesize what appears to be an object literal.
      if (!(/^\s*\{/.test(code) && /\}\s*$/.test(code)))
        return code;
  
      const parse = (async () => 0).constructor;
      try {
        // Check if the code can be interpreted as an expression.
        parse('return ' + code + ';');
  
        // No syntax error! Does it work parenthesized?
        const wrappedCode = '(' + code + ')';
        parse(wrappedCode);
  
        return wrappedCode;
      } catch (e) {
        return code;
      }
    }
  
    /**
     * @return {!SDK.DebuggerModel}
     */
    debuggerModel() {
      return /** @type {!SDK.DebuggerModel} */ (this.target().model(SDK.DebuggerModel));
    }
  
    /**
     * @return {!SDK.HeapProfilerModel}
     */
    heapProfilerModel() {
      return /** @type {!SDK.HeapProfilerModel} */ (this.target().model(SDK.HeapProfilerModel));
    }
  
    /**
     * @return {!Array.<!SDK.ExecutionContext>}
     */
    executionContexts() {
      return this._executionContextById.valuesArray().sort(this.executionContextComparator());
    }
  
    /**
     * @param {function(!SDK.ExecutionContext,!SDK.ExecutionContext)} comparator
     */
    setExecutionContextComparator(comparator) {
      this._executionContextComparator = comparator;
    }
  
    /**
     * @return {function(!SDK.ExecutionContext,!SDK.ExecutionContext)} comparator
     */
    executionContextComparator() {
      return this._executionContextComparator;
    }
  
    /**
     * @return {?SDK.ExecutionContext}
     */
    defaultExecutionContext() {
      for (const context of this.executionContexts()) {
        if (context.isDefault)
          return context;
      }
      return null;
    }
  
    /**
     * @param {!Protocol.Runtime.ExecutionContextId} id
     * @return {?SDK.ExecutionContext}
     */
    executionContext(id) {
      return this._executionContextById.get(id) || null;
    }
  
    /**
     * @param {!Protocol.Runtime.ExecutionContextDescription} context
     */
    _executionContextCreated(context) {
      const data = context.auxData || {isDefault: true};
      const executionContext =
          new SDK.ExecutionContext(this, context.id, context.name, context.origin, data['isDefault'], data['frameId']);
      this._executionContextById.set(executionContext.id, executionContext);
      this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExecutionContextCreated, executionContext);
    }
  
    /**
     * @param {number} executionContextId
     */
    _executionContextDestroyed(executionContextId) {
      const executionContext = this._executionContextById.get(executionContextId);
      if (!executionContext)
        return;
      this.debuggerModel().executionContextDestroyed(executionContext);
      this._executionContextById.delete(executionContextId);
      this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExecutionContextDestroyed, executionContext);
    }
  
    fireExecutionContextOrderChanged() {
      this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExecutionContextOrderChanged, this);
    }
  
    _executionContextsCleared() {
      this.debuggerModel().globalObjectCleared();
      const contexts = this.executionContexts();
      this._executionContextById.clear();
      for (let i = 0; i < contexts.length; ++i)
        this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExecutionContextDestroyed, contexts[i]);
    }
  
    /**
     * @param {!Protocol.Runtime.RemoteObject} payload
     * @return {!SDK.RemoteObject}
     */
    createRemoteObject(payload) {
      console.assert(typeof payload === 'object', 'Remote object payload should only be an object');
      return new SDK.RemoteObjectImpl(
          this, payload.objectId, payload.type, payload.subtype, payload.value, payload.unserializableValue,
          payload.description, payload.preview, payload.customPreview, payload.className);
    }
  
    /**
     * @param {!Protocol.Runtime.RemoteObject} payload
     * @param {!SDK.ScopeRef} scopeRef
     * @return {!SDK.RemoteObject}
     */
    createScopeRemoteObject(payload, scopeRef) {
      return new SDK.ScopeRemoteObject(
          this, payload.objectId, scopeRef, payload.type, payload.subtype, payload.value, payload.unserializableValue,
          payload.description, payload.preview);
    }
  
    /**
     * @param {number|string|boolean|undefined|bigint} value
     * @return {!SDK.RemoteObject}
     */
    createRemoteObjectFromPrimitiveValue(value) {
      const type = typeof value;
      let unserializableValue = undefined;
      const unserializableDescription = SDK.RemoteObject.unserializableDescription(value);
      if (unserializableDescription !== null)
        unserializableValue = /** @type {!Protocol.Runtime.UnserializableValue} */ (unserializableDescription);
      if (typeof unserializableValue !== 'undefined')
        value = undefined;
      return new SDK.RemoteObjectImpl(this, undefined, type, undefined, value, unserializableValue);
    }
  
    /**
     * @param {string} name
     * @param {number|string|boolean} value
     * @return {!SDK.RemoteObjectProperty}
     */
    createRemotePropertyFromPrimitiveValue(name, value) {
      return new SDK.RemoteObjectProperty(name, this.createRemoteObjectFromPrimitiveValue(value));
    }
  
    discardConsoleEntries() {
      this._agent.discardConsoleEntries();
    }
  
    /**
     * @param {string} objectGroupName
     */
    releaseObjectGroup(objectGroupName) {
      this._agent.releaseObjectGroup(objectGroupName);
    }
  
    runIfWaitingForDebugger() {
      this._agent.runIfWaitingForDebugger();
    }
  
    /**
     * @param {!Common.Event} event
     */
    _customFormattersStateChanged(event) {
      const enabled = /** @type {boolean} */ (event.data);
      this._agent.setCustomObjectFormatterEnabled(enabled);
    }
  
    /**
     * @param {string} expression
     * @param {string} sourceURL
     * @param {boolean} persistScript
     * @param {number} executionContextId
     * @return {?Promise<!SDK.RuntimeModel.CompileScriptResult>}
     */
    async compileScript(expression, sourceURL, persistScript, executionContextId) {
      const response = await this._agent.invoke_compileScript({
        expression: expression,
        sourceURL: sourceURL,
        persistScript: persistScript,
        executionContextId: executionContextId
      });
  
      if (response[Protocol.Error]) {
        console.error(response[Protocol.Error]);
        return null;
      }
      return {scriptId: response.scriptId, exceptionDetails: response.exceptionDetails};
    }
  
    /**
     * @param {!Protocol.Runtime.ScriptId} scriptId
     * @param {number} executionContextId
     * @param {string=} objectGroup
     * @param {boolean=} silent
     * @param {boolean=} includeCommandLineAPI
     * @param {boolean=} returnByValue
     * @param {boolean=} generatePreview
     * @param {boolean=} awaitPromise
     * @return {!Promise<!SDK.RuntimeModel.EvaluationResult>}
     */
    async runScript(
        scriptId, executionContextId, objectGroup, silent, includeCommandLineAPI, returnByValue, generatePreview,
        awaitPromise) {
      const response = await this._agent.invoke_runScript({
        scriptId,
        executionContextId,
        objectGroup,
        silent,
        includeCommandLineAPI,
        returnByValue,
        generatePreview,
        awaitPromise
      });
  
      const error = response[Protocol.Error];
      if (error) {
        console.error(error);
        return {error: error};
      }
      return {object: this.createRemoteObject(response.result), exceptionDetails: response.exceptionDetails};
    }
  
    /**
     * @param {!SDK.RemoteObject} prototype
     * @return {!Promise<!SDK.RuntimeModel.QueryObjectResult>}
     */
    async queryObjects(prototype) {
      if (!prototype.objectId)
        return {error: 'Prototype should be an Object.'};
      const response = await this._agent.invoke_queryObjects(
          {prototypeObjectId: /** @type {string} */ (prototype.objectId), objectGroup: 'console'});
      const error = response[Protocol.Error];
      if (error) {
        console.error(error);
        return {error: error};
      }
      return {objects: this.createRemoteObject(response.objects)};
    }
  
    /**
     * @return {!Promise<string>}
     */
    async isolateId() {
      return (await this._agent.getIsolateId()) || this.target().id();
    }
  
    /**
     * @return {!Promise<?{usedSize: number, totalSize: number}>}
     */
    async heapUsage() {
      const result = await this._agent.invoke_getHeapUsage({});
      return result[Protocol.Error] ? null : result;
    }
  
    /**
     * @param {!Protocol.Runtime.RemoteObject} payload
     * @param {!Object=} hints
     */
    _inspectRequested(payload, hints) {
      const object = this.createRemoteObject(payload);
  
      if (hints.copyToClipboard) {
        this._copyRequested(object);
        return;
      }
  
      if (hints.queryObjects) {
        this._queryObjectsRequested(object);
        return;
      }
  
      if (object.isNode()) {
        Common.Revealer.reveal(object).then(object.release.bind(object));
        return;
      }
  
      if (object.type === 'function') {
        SDK.RemoteFunction.objectAsFunction(object).targetFunctionDetails().then(didGetDetails);
        return;
      }
  
      /**
       * @param {?SDK.DebuggerModel.FunctionDetails} response
       */
      function didGetDetails(response) {
        object.release();
        if (!response || !response.location)
          return;
        Common.Revealer.reveal(response.location);
      }
      object.release();
    }
  
    /**
     * @param {!SDK.RemoteObject} object
     */
    _copyRequested(object) {
      if (!object.objectId) {
        InspectorFrontendHost.copyText(object.unserializableValue() || object.value);
        return;
      }
      object.callFunctionJSON(
          toStringForClipboard, [{value: object.subtype}], InspectorFrontendHost.copyText.bind(InspectorFrontendHost));
  
      /**
       * @param {string} subtype
       * @this {Object}
       * @suppressReceiverCheck
       */
      function toStringForClipboard(subtype) {
        if (subtype === 'node')
          return this.outerHTML;
        if (subtype && typeof this === 'undefined')
          return subtype + '';
        try {
          return JSON.stringify(this, null, '  ');
        } catch (e) {
          return '' + this;
        }
      }
    }
  
    /**
     * @param {!SDK.RemoteObject} object
     */
    async _queryObjectsRequested(object) {
      const result = await this.queryObjects(object);
      object.release();
      if (result.error) {
        Common.console.error(result.error);
        return;
      }
      this.dispatchEventToListeners(SDK.RuntimeModel.Events.QueryObjectRequested, {objects: result.objects});
    }
  
    /**
     * @param {!Protocol.Runtime.ExceptionDetails} exceptionDetails
     * @return {string}
     */
    static simpleTextFromException(exceptionDetails) {
      let text = exceptionDetails.text;
      if (exceptionDetails.exception && exceptionDetails.exception.description) {
        let description = exceptionDetails.exception.description;
        if (description.indexOf('\n') !== -1)
          description = description.substring(0, description.indexOf('\n'));
        text += ' ' + description;
      }
      return text;
    }
  
    /**
     * @param {number} timestamp
     * @param {!Protocol.Runtime.ExceptionDetails} exceptionDetails
     */
    exceptionThrown(timestamp, exceptionDetails) {
      const exceptionWithTimestamp = {timestamp: timestamp, details: exceptionDetails};
      this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExceptionThrown, exceptionWithTimestamp);
    }
  
    /**
     * @param {number} exceptionId
     */
    _exceptionRevoked(exceptionId) {
      this.dispatchEventToListeners(SDK.RuntimeModel.Events.ExceptionRevoked, exceptionId);
    }
  
    /**
     * @param {string} type
     * @param {!Array.<!Protocol.Runtime.RemoteObject>} args
     * @param {number} executionContextId
     * @param {number} timestamp
     * @param {!Protocol.Runtime.StackTrace=} stackTrace
     * @param {string=} context
     */
    _consoleAPICalled(type, args, executionContextId, timestamp, stackTrace, context) {
      const consoleAPICall = {
        type: type,
        args: args,
        executionContextId: executionContextId,
        timestamp: timestamp,
        stackTrace: stackTrace,
        context: context
      };
      this.dispatchEventToListeners(SDK.RuntimeModel.Events.ConsoleAPICalled, consoleAPICall);
    }
  
    /**
     * @param {!Protocol.Runtime.ScriptId} scriptId
     * @return {number}
     */
    executionContextIdForScriptId(scriptId) {
      const script = this.debuggerModel().scriptForId(scriptId);
      return script ? script.executionContextId : 0;
    }
  
    /**
     * @param {!Protocol.Runtime.StackTrace} stackTrace
     * @return {number}
     */
    executionContextForStackTrace(stackTrace) {
      while (stackTrace && !stackTrace.callFrames.length)
        stackTrace = stackTrace.parent;
      if (!stackTrace || !stackTrace.callFrames.length)
        return 0;
      return this.executionContextIdForScriptId(stackTrace.callFrames[0].scriptId);
    }
  
    /**
     * @return {?boolean}
     */
    hasSideEffectSupport() {
      return this._hasSideEffectSupport;
    }
  
    /**
     * @return {!Promise<boolean>}
     */
    async checkSideEffectSupport() {
      const testContext = this.executionContexts().peekLast();
      if (!testContext)
        return false;
      // Check for a positive throwOnSideEffect response without triggering side effects.
      const response = await this._agent.invoke_evaluate(
          {expression: SDK.RuntimeModel._sideEffectTestExpression, contextId: testContext.id, throwOnSideEffect: true});
  
      const exceptionDetails = !response[Protocol.Error] && response.exceptionDetails;
      const supports =
          !!(exceptionDetails && exceptionDetails.exception &&
             exceptionDetails.exception.description.startsWith('EvalError: Possible side-effect in debug-evaluate'));
      this._hasSideEffectSupport = supports;
      return supports;
    }
  
    /**
     * @return {!Promise}
     */
    terminateExecution() {
      return this._agent.invoke_terminateExecution({});
    }
  };
  
  SDK.SDKModel.register(SDK.RuntimeModel, SDK.Target.Capability.JS, true);
  
  /**
   * This expression:
   * - IMPORTANT: must not actually cause user-visible or JS-visible side-effects.
   * - Must throw when evaluated with `throwOnSideEffect: true`.
   * - Must be valid when run from any ExecutionContext that supports `throwOnSideEffect`.
   * @const
   * @type {string}
   */
  SDK.RuntimeModel._sideEffectTestExpression = '(async function(){ await 1; })()';
  
  /** @enum {symbol} */
  SDK.RuntimeModel.Events = {
    ExecutionContextCreated: Symbol('ExecutionContextCreated'),
    ExecutionContextDestroyed: Symbol('ExecutionContextDestroyed'),
    ExecutionContextChanged: Symbol('ExecutionContextChanged'),
    ExecutionContextOrderChanged: Symbol('ExecutionContextOrderChanged'),
    ExceptionThrown: Symbol('ExceptionThrown'),
    ExceptionRevoked: Symbol('ExceptionRevoked'),
    ConsoleAPICalled: Symbol('ConsoleAPICalled'),
    QueryObjectRequested: Symbol('QueryObjectRequested'),
  };
  
  /** @typedef {{timestamp: number, details: !Protocol.Runtime.ExceptionDetails}} */
  SDK.RuntimeModel.ExceptionWithTimestamp;
  
  /** @typedef {{
   *    scriptId: (Protocol.Runtime.ScriptId|undefined),
   *    exceptionDetails: (!Protocol.Runtime.ExceptionDetails|undefined)
   *  }}
   */
  SDK.RuntimeModel.CompileScriptResult;
  
  /** @typedef {{
   *    expression: string,
   *    objectGroup: (string|undefined),
   *    includeCommandLineAPI: (boolean|undefined),
   *    silent: (boolean|undefined),
   *    returnByValue: (boolean|undefined),
   *    generatePreview: (boolean|undefined),
   *    throwOnSideEffect: (boolean|undefined),
   *    timeout: (number|undefined)
   *  }}
   */
  SDK.RuntimeModel.EvaluationOptions;
  
  /** @typedef {{
   *    object: (!SDK.RemoteObject|undefined),
   *    exceptionDetails: (!Protocol.Runtime.ExceptionDetails|undefined),
   *    error: (!Protocol.Error|undefined)}
   *  }}
   */
  SDK.RuntimeModel.EvaluationResult;
  
  /** @typedef {{
   *    objects: (!SDK.RemoteObject|undefined),
   *    error: (!Protocol.Error|undefined)}
   *  }}
   */
  SDK.RuntimeModel.QueryObjectResult;
  
  /**
   * @typedef {{
   *    type: string,
   *    args: !Array<!Protocol.Runtime.RemoteObject>,
   *    executionContextId: number,
   *    timestamp: number,
   *    stackTrace: (!Protocol.Runtime.StackTrace|undefined)
   * }}
   */
  SDK.RuntimeModel.ConsoleAPICall;
  
  /**
   * @extends {Protocol.RuntimeDispatcher}
   * @unrestricted
   */
  SDK.RuntimeDispatcher = class {
    /**
     * @param {!SDK.RuntimeModel} runtimeModel
     */
    constructor(runtimeModel) {
      this._runtimeModel = runtimeModel;
    }
  
    /**
     * @override
     * @param {!Protocol.Runtime.ExecutionContextDescription} context
     */
    executionContextCreated(context) {
      this._runtimeModel._executionContextCreated(context);
    }
  
    /**
     * @override
     * @param {!Protocol.Runtime.ExecutionContextId} executionContextId
     */
    executionContextDestroyed(executionContextId) {
      this._runtimeModel._executionContextDestroyed(executionContextId);
    }
  
    /**
     * @override
     */
    executionContextsCleared() {
      this._runtimeModel._executionContextsCleared();
    }
  
    /**
     * @override
     * @param {number} timestamp
     * @param {!Protocol.Runtime.ExceptionDetails} exceptionDetails
     */
    exceptionThrown(timestamp, exceptionDetails) {
      this._runtimeModel.exceptionThrown(timestamp, exceptionDetails);
    }
  
    /**
     * @override
     * @param {string} reason
     * @param {number} exceptionId
     */
    exceptionRevoked(reason, exceptionId) {
      this._runtimeModel._exceptionRevoked(exceptionId);
    }
  
    /**
     * @override
     * @param {string} type
     * @param {!Array.<!Protocol.Runtime.RemoteObject>} args
     * @param {number} executionContextId
     * @param {number} timestamp
     * @param {!Protocol.Runtime.StackTrace=} stackTrace
     * @param {string=} context
     */
    consoleAPICalled(type, args, executionContextId, timestamp, stackTrace, context) {
      this._runtimeModel._consoleAPICalled(type, args, executionContextId, timestamp, stackTrace, context);
    }
  
    /**
     * @override
     * @param {!Protocol.Runtime.RemoteObject} payload
     * @param {!Object=} hints
     */
    inspectRequested(payload, hints) {
      this._runtimeModel._inspectRequested(payload, hints);
    }
  };
  
  /**
   * @unrestricted
   */
  SDK.ExecutionContext = class {
    /**
     * @param {!SDK.RuntimeModel} runtimeModel
     * @param {number} id
     * @param {string} name
     * @param {string} origin
     * @param {boolean} isDefault
     * @param {string=} frameId
     */
    constructor(runtimeModel, id, name, origin, isDefault, frameId) {
      this.id = id;
      this.name = name;
      this.origin = origin;
      this.isDefault = isDefault;
      this.runtimeModel = runtimeModel;
      this.debuggerModel = runtimeModel.debuggerModel();
      this.frameId = frameId;
      this._setLabel('');
    }
  
    /**
     * @return {!SDK.Target}
     */
    target() {
      return this.runtimeModel.target();
    }
  
    /**
     * @param {!SDK.ExecutionContext} a
     * @param {!SDK.ExecutionContext} b
     * @return {number}
     */
    static comparator(a, b) {
      /**
       * @param {!SDK.Target} target
       * @return {number}
       */
      function targetWeight(target) {
        if (!target.parentTarget())
          return 4;
        if (target.hasBrowserCapability())
          return 3;
        if (target.hasJSCapability())
          return 2;
        return 1;
      }
  
      const weightDiff = targetWeight(a.target()) - targetWeight(b.target());
      if (weightDiff)
        return -weightDiff;
  
      // Main world context should always go first.
      if (a.isDefault)
        return -1;
      if (b.isDefault)
        return +1;
      return a.name.localeCompare(b.name);
    }
  
    /**
     * @param {!SDK.RuntimeModel.EvaluationOptions} options
     * @param {boolean} userGesture
     * @param {boolean} awaitPromise
     * @return {!Promise<!SDK.RuntimeModel.EvaluationResult>}
     */
    evaluate(options, userGesture, awaitPromise) {
      // FIXME: It will be moved to separate ExecutionContext.
      if (this.debuggerModel.selectedCallFrame())
        return this.debuggerModel.evaluateOnSelectedCallFrame(options);
      // Assume backends either support both throwOnSideEffect and timeout options or neither.
      const needsTerminationOptions = !!options.throwOnSideEffect || options.timeout !== undefined;
      if (!needsTerminationOptions || this.runtimeModel.hasSideEffectSupport())
        return this._evaluateGlobal(options, userGesture, awaitPromise);
  
      /** @type {!SDK.RuntimeModel.EvaluationResult} */
      const unsupportedError = {error: 'Side-effect checks not supported by backend.'};
      if (this.runtimeModel.hasSideEffectSupport() === false)
        return Promise.resolve(unsupportedError);
  
      return this.runtimeModel.checkSideEffectSupport().then(() => {
        if (this.runtimeModel.hasSideEffectSupport())
          return this._evaluateGlobal(options, userGesture, awaitPromise);
        return Promise.resolve(unsupportedError);
      });
    }
  
    /**
     * @param {string} objectGroup
     * @param {boolean} generatePreview
     * @return {!Promise<!SDK.RuntimeModel.EvaluationResult>}
     */
    globalObject(objectGroup, generatePreview) {
      return this._evaluateGlobal(
          {
            expression: 'this',
            objectGroup: objectGroup,
            includeCommandLineAPI: false,
            silent: true,
            returnByValue: false,
            generatePreview: generatePreview
          },
          /* userGesture */ false, /* awaitPromise */ false);
    }
  
    /**
     * @param {!SDK.RuntimeModel.EvaluationOptions} options
     * @param {boolean} userGesture
     * @param {boolean} awaitPromise
     * @return {!Promise<!SDK.RuntimeModel.EvaluationResult>}
     */
    async _evaluateGlobal(options, userGesture, awaitPromise) {
      if (!options.expression) {
        // There is no expression, so the completion should happen against global properties.
        options.expression = 'this';
      }
  
      const response = await this.runtimeModel._agent.invoke_evaluate({
        expression: options.expression,
        objectGroup: options.objectGroup,
        includeCommandLineAPI: options.includeCommandLineAPI,
        silent: options.silent,
        contextId: this.id,
        returnByValue: options.returnByValue,
        generatePreview: options.generatePreview,
        userGesture: userGesture,
        awaitPromise: awaitPromise,
        throwOnSideEffect: options.throwOnSideEffect,
        timeout: options.timeout
      });
  
      const error = response[Protocol.Error];
      if (error) {
        console.error(error);
        return {error: error};
      }
      return {object: this.runtimeModel.createRemoteObject(response.result), exceptionDetails: response.exceptionDetails};
    }
  
    /**
     * @return {!Promise<?Array<string>>}
     */
    async globalLexicalScopeNames() {
      const response = await this.runtimeModel._agent.invoke_globalLexicalScopeNames({executionContextId: this.id});
      return response[Protocol.Error] ? [] : response.names;
    }
  
    /**
     * @return {string}
     */
    label() {
      return this._label;
    }
  
    /**
     * @param {string} label
     */
    setLabel(label) {
      this._setLabel(label);
      this.runtimeModel.dispatchEventToListeners(SDK.RuntimeModel.Events.ExecutionContextChanged, this);
    }
  
    /**
     * @param {string} label
     */
    _setLabel(label) {
      if (label) {
        this._label = label;
        return;
      }
      if (this.name) {
        this._label = this.name;
        return;
      }
      const parsedUrl = this.origin.asParsedURL();
      this._label = parsedUrl ? parsedUrl.lastPathComponentWithFragment() : '';
    }
  };
  