tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Errors.sys.mjs (29734B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { RemoteError } from "chrome://remote/content/shared/RemoteError.sys.mjs";
      6 
      7 const lazy = {};
      8 
      9 ChromeUtils.defineESModuleGetters(lazy, {
     10  pprint: "chrome://remote/content/shared/Format.sys.mjs",
     11 });
     12 
     13 const ERRORS = new Set([
     14  "DetachedShadowRootError",
     15  "ElementClickInterceptedError",
     16  "ElementNotAccessibleError",
     17  "ElementNotInteractableError",
     18  "InsecureCertificateError",
     19  "InvalidArgumentError",
     20  "InvalidCookieDomainError",
     21  "InvalidElementStateError",
     22  "InvalidSelectorError",
     23  "InvalidSessionIDError",
     24  "InvalidWebExtensionError",
     25  "JavaScriptError",
     26  "MoveTargetOutOfBoundsError",
     27  "NoSuchAlertError",
     28  "NoSuchElementError",
     29  "NoSuchFrameError",
     30  "NoSuchHandleError",
     31  "NoSuchHistoryEntryError",
     32  "NoSuchInterceptError",
     33  "NoSuchNetworkCollectorError",
     34  "NoSuchNetworkDataError",
     35  "NoSuchNodeError",
     36  "NoSuchRequestError",
     37  "NoSuchScriptError",
     38  "NoSuchShadowRootError",
     39  "NoSuchUserContextError",
     40  "NoSuchWebExtensionError",
     41  "NoSuchWindowError",
     42  "ScriptTimeoutError",
     43  "SessionNotCreatedError",
     44  "StaleElementReferenceError",
     45  "TimeoutError",
     46  "UnableToCaptureScreen",
     47  "UnableToSetCookieError",
     48  "UnableToSetFileInputError",
     49  "UnavailableNetworkDataError",
     50  "UnexpectedAlertOpenError",
     51  "UnknownCommandError",
     52  "UnknownError",
     53  "UnsupportedOperationError",
     54  "WebDriverError",
     55 ]);
     56 
     57 const BUILTIN_ERRORS = new Set([
     58  "Error",
     59  "EvalError",
     60  "InternalError",
     61  "RangeError",
     62  "ReferenceError",
     63  "SyntaxError",
     64  "TypeError",
     65  "URIError",
     66 ]);
     67 
     68 /** @namespace */
     69 export const error = {
     70  /**
     71   * Check if ``val`` is an instance of the ``Error`` prototype.
     72   *
     73   * Because error objects may originate from different globals, comparing
     74   * the prototype of the left hand side with the prototype property from
     75   * the right hand side, which is what ``instanceof`` does, will not work.
     76   * If the LHS and RHS come from different globals, this check will always
     77   * fail because the two objects will not have the same identity.
     78   *
     79   * Therefore it is not safe to use ``instanceof`` in any multi-global
     80   * situation, e.g. in content across multiple ``Window`` objects or anywhere
     81   * in chrome scope.
     82   *
     83   * This function also contains a special check if ``val`` is an XPCOM
     84   * ``nsIException`` because they are special snowflakes and may indeed
     85   * cause Firefox to crash if used with ``instanceof``.
     86   *
     87   * @param {*} val
     88   *     Any value that should be undergo the test for errorness.
     89   * @returns {boolean}
     90   *     True if error, false otherwise.
     91   */
     92  isError(val) {
     93    if (val === null || typeof val != "object") {
     94      return false;
     95    } else if (val instanceof Ci.nsIException) {
     96      return true;
     97    }
     98 
     99    // DOMRectList errors on string comparison
    100    try {
    101      let proto = Object.getPrototypeOf(val);
    102      return BUILTIN_ERRORS.has(proto.toString());
    103    } catch (e) {
    104      return false;
    105    }
    106  },
    107 
    108  /**
    109   * Checks if ``obj`` is an object in the :js:class:`WebDriverError`
    110   * prototypal chain.
    111   *
    112   * @param {*} obj
    113   *     Arbitrary object to test.
    114   *
    115   * @returns {boolean}
    116   *     True if ``obj`` is of the WebDriverError prototype chain,
    117   *     false otherwise.
    118   */
    119  isWebDriverError(obj) {
    120    // Don't use "instanceof" to compare error objects because of possible
    121    // problems when the other instance was created in a different global and
    122    // as such won't have the same prototype object.
    123    return error.isError(obj) && "name" in obj && ERRORS.has(obj.name);
    124  },
    125 
    126  /**
    127   * Ensures error instance is a :js:class:`WebDriverError`.
    128   *
    129   * If the given error is already in the WebDriverError prototype
    130   * chain, ``err`` is returned unmodified.  If it is not, it is wrapped
    131   * in the provided WebDriverError class (defaults to :js:class:`UnknownError`).
    132   *
    133   * @param {Error} err
    134   *     Error to conditionally turn into a WebDriverError.
    135   * @param {WebDriverError=} targetErrorClass
    136   *     Target WebDriver error class to wrap the error with.
    137   *     Defaults to UnknownError.
    138   *
    139   * @returns {WebDriverError}
    140   *     If ``err`` is a WebDriverError, it is returned unmodified.
    141   *     Otherwise a WebDriver error of the target error class type is returned.
    142   */
    143  wrap(err, targetErrorClass = UnknownError) {
    144    if (error.isWebDriverError(err)) {
    145      return err;
    146    }
    147 
    148    return new targetErrorClass(err);
    149  },
    150 
    151  /**
    152   * Unhandled error reporter.  Dumps the error and its stacktrace to console,
    153   * and reports error to the Browser Console.
    154   */
    155  report(err) {
    156    let msg = "Marionette threw an error: " + error.stringify(err);
    157    dump(msg + "\n");
    158    console.error(msg);
    159  },
    160 
    161  /**
    162   * Prettifies an instance of Error and its stacktrace to a string.
    163   */
    164  stringify(err) {
    165    try {
    166      let s = err.toString();
    167      if ("stack" in err) {
    168        s += "\n" + err.stack;
    169      }
    170      return s;
    171    } catch (e) {
    172      return "<unprintable error>";
    173    }
    174  },
    175 
    176  /** Create a stacktrace to the current line in the program. */
    177  stack() {
    178    let trace = new Error().stack;
    179    let sa = trace.split("\n");
    180    sa = sa.slice(1);
    181    let rv = "stacktrace:\n" + sa.join("\n");
    182    return rv.trimEnd();
    183  },
    184 };
    185 
    186 /**
    187 * WebDriverError is the prototypal parent of all WebDriver errors.
    188 * It should not be used directly, as it does not correspond to a real
    189 * error in the specification.
    190 */
    191 class WebDriverError extends RemoteError {
    192  /**
    193   * Base error for WebDriver protocols.
    194   *
    195   * @param {(string|Error)=} obj
    196   *     Optional string describing error situation or Error instance
    197   *     to propagate.
    198   * @param {object=} data
    199   *     Additional error data helpful in diagnosing the error.
    200   */
    201  constructor(obj, data = {}) {
    202    super(obj);
    203 
    204    this.name = this.constructor.name;
    205    this.status = "webdriver error";
    206    this.data = data;
    207 
    208    // Error's ctor does not preserve x' stack
    209    if (error.isError(obj)) {
    210      this.lineNumber = obj.lineNumber;
    211      this.columnNumber = obj.columnNumber;
    212      if (!obj.stack) {
    213        // Provides a stacktrace if it was missing on the original Error object
    214        this.stack = `@${obj.fileName}:${obj.lineNumber}:${obj.columnNumber}\n`;
    215      } else {
    216        this.stack = obj.stack;
    217      }
    218    }
    219 
    220    if (error.isWebDriverError(obj)) {
    221      this.message = obj.message;
    222      this.data = obj.data;
    223    }
    224  }
    225 
    226  /**
    227   * @returns {Record<string, string>}
    228   *     JSON serialisation of error prototype.
    229   */
    230  toJSON() {
    231    const result = {
    232      error: this.status,
    233      message: this.message || "",
    234      stacktrace: this.stack || "",
    235    };
    236 
    237    // Only add the field if additional data has been specified.
    238    if (Object.keys(this.data).length) {
    239      result.data = this.data;
    240    }
    241 
    242    return result;
    243  }
    244 
    245  /**
    246   * Unmarshals a JSON error representation to the appropriate Marionette
    247   * error type.
    248   *
    249   * @param {Record<string, string>} json
    250   *     Error object.
    251   *
    252   * @returns {Error}
    253   *     Error prototype.
    254   */
    255  static fromJSON(json) {
    256    if (typeof json.error == "undefined") {
    257      let s = JSON.stringify(json);
    258      throw new TypeError("Undeserialisable error type: " + s);
    259    }
    260    if (!STATUSES.has(json.error)) {
    261      throw new TypeError("Not of WebDriverError descent: " + json.error);
    262    }
    263 
    264    let cls = STATUSES.get(json.error);
    265    let err = new cls();
    266    if ("message" in json) {
    267      err.message = json.message;
    268    }
    269    if ("stacktrace" in json) {
    270      err.stack = json.stacktrace;
    271    }
    272    if ("data" in json) {
    273      err.data = json.data;
    274    }
    275 
    276    return err;
    277  }
    278 }
    279 
    280 /**
    281 * The Gecko a11y API indicates that the element is not accessible.
    282 *
    283 * @param {(string|Error)=} obj
    284 *     Optional string describing error situation or Error instance
    285 *     to propagate.
    286 * @param {object=} data
    287 *     Additional error data helpful in diagnosing the error.
    288 */
    289 class ElementNotAccessibleError extends WebDriverError {
    290  constructor(obj, data = {}) {
    291    super(obj, data);
    292    this.status = "element not accessible";
    293  }
    294 }
    295 
    296 /**
    297 * An element click could not be completed because the element receiving
    298 * the events is obscuring the element that was requested clicked.
    299 *
    300 * @param {string=} message
    301 *     Optional string describing error situation. Will be replaced if both
    302 *     `data.obscuredEl` and `data.coords` are provided.
    303 * @param {object=} data
    304 *     Additional error data helpful in diagnosing the error.
    305 * @param {Element=} obscuredEl
    306 *     Element obscuring the element receiving the click.  Providing this
    307 *     is not required, but will produce a nicer error message.
    308 * @param {Map.<string, number>=} coords
    309 *     Original click location.  Providing this is not required, but
    310 *     will produce a nicer error message.
    311 */
    312 class ElementClickInterceptedError extends WebDriverError {
    313  constructor(obj, data = {}, obscuredEl = undefined, coords = undefined) {
    314    let obscuredElDetails = null;
    315    let overlayingElDetails = null;
    316 
    317    if (obscuredEl && coords) {
    318      const doc = obscuredEl.ownerDocument;
    319      const overlayingEl = doc.elementFromPoint(coords.x, coords.y);
    320 
    321      obscuredElDetails = lazy.pprint`${obscuredEl}`;
    322      overlayingElDetails = lazy.pprint`${overlayingEl}`;
    323 
    324      switch (obscuredEl.style.pointerEvents) {
    325        case "none":
    326          obj =
    327            `Element ${obscuredElDetails} is not clickable ` +
    328            `at point (${coords.x},${coords.y}) ` +
    329            `because it does not have pointer events enabled, ` +
    330            `and element ${overlayingElDetails} ` +
    331            `would receive the click instead`;
    332          break;
    333 
    334        default:
    335          obj =
    336            `Element ${obscuredElDetails} is not clickable ` +
    337            `at point (${coords.x},${coords.y}) ` +
    338            `because another element ${overlayingElDetails} ` +
    339            `obscures it`;
    340          break;
    341      }
    342    }
    343 
    344    if (coords) {
    345      data.coords = coords;
    346    }
    347    if (obscuredElDetails) {
    348      data.obscuredElement = obscuredElDetails;
    349    }
    350    if (overlayingElDetails) {
    351      data.overlayingElement = overlayingElDetails;
    352    }
    353 
    354    super(obj, data);
    355    this.status = "element click intercepted";
    356  }
    357 }
    358 
    359 /**
    360 * A command could not be completed because the element is not pointer-
    361 * or keyboard interactable.
    362 *
    363 * @param {(string|Error)=} obj
    364 *     Optional string describing error situation or Error instance
    365 *     to propagate.
    366 * @param {object=} data
    367 *     Additional error data helpful in diagnosing the error.
    368 */
    369 class ElementNotInteractableError extends WebDriverError {
    370  constructor(obj, data = {}) {
    371    super(obj, data);
    372    this.status = "element not interactable";
    373  }
    374 }
    375 
    376 /**
    377 * Navigation caused the user agent to hit a certificate warning, which
    378 * is usually the result of an expired or invalid TLS certificate.
    379 *
    380 * @param {(string|Error)=} obj
    381 *     Optional string describing error situation or Error instance
    382 *     to propagate.
    383 * @param {object=} data
    384 *     Additional error data helpful in diagnosing the error.
    385 */
    386 class InsecureCertificateError extends WebDriverError {
    387  constructor(obj, data = {}) {
    388    super(obj, data);
    389    this.status = "insecure certificate";
    390  }
    391 }
    392 
    393 /**
    394 * The arguments passed to a command are either invalid or malformed.
    395 *
    396 * @param {(string|Error)=} obj
    397 *     Optional string describing error situation or Error instance
    398 *     to propagate.
    399 * @param {object=} data
    400 *     Additional error data helpful in diagnosing the error.
    401 */
    402 class InvalidArgumentError extends WebDriverError {
    403  constructor(obj, data = {}) {
    404    super(obj, data);
    405    this.status = "invalid argument";
    406  }
    407 }
    408 
    409 /**
    410 * An illegal attempt was made to set a cookie under a different
    411 * domain than the current page.
    412 *
    413 * @param {(string|Error)=} obj
    414 *     Optional string describing error situation or Error instance
    415 *     to propagate.
    416 * @param {object=} data
    417 *     Additional error data helpful in diagnosing the error.
    418 */
    419 class InvalidCookieDomainError extends WebDriverError {
    420  constructor(obj, data = {}) {
    421    super(obj, data);
    422    this.status = "invalid cookie domain";
    423  }
    424 }
    425 
    426 /**
    427 * A command could not be completed because the element is in an
    428 * invalid state, e.g. attempting to clear an element that isn't both
    429 * editable and resettable.
    430 *
    431 * @param {(string|Error)=} obj
    432 *     Optional string describing error situation or Error instance
    433 *     to propagate.
    434 * @param {object=} data
    435 *     Additional error data helpful in diagnosing the error.
    436 */
    437 class InvalidElementStateError extends WebDriverError {
    438  constructor(obj, data = {}) {
    439    super(obj, data);
    440    this.status = "invalid element state";
    441  }
    442 }
    443 
    444 /**
    445 * Argument was an invalid selector.
    446 *
    447 * @param {(string|Error)=} obj
    448 *     Optional string describing error situation or Error instance
    449 *     to propagate.
    450 * @param {object=} data
    451 *     Additional error data helpful in diagnosing the error.
    452 */
    453 class InvalidSelectorError extends WebDriverError {
    454  constructor(obj, data = {}) {
    455    super(obj, data);
    456    this.status = "invalid selector";
    457  }
    458 }
    459 
    460 /**
    461 * Occurs if the given session ID is not in the list of active sessions,
    462 * meaning the session either does not exist or that it's not active.
    463 *
    464 * @param {(string|Error)=} obj
    465 *     Optional string describing error situation or Error instance
    466 *     to propagate.
    467 * @param {object=} data
    468 *     Additional error data helpful in diagnosing the error.
    469 */
    470 class InvalidSessionIDError extends WebDriverError {
    471  constructor(obj, data = {}) {
    472    super(obj, data);
    473    this.status = "invalid session id";
    474  }
    475 }
    476 
    477 /**
    478 * Tried to install an invalid web extension.
    479 *
    480 * @param {(string|Error)=} obj
    481 *     Optional string describing error situation or Error instance
    482 *     to propagate.
    483 * @param {object=} data
    484 *     Additional error data helpful in diagnosing the error.
    485 */
    486 class InvalidWebExtensionError extends WebDriverError {
    487  constructor(obj, data = {}) {
    488    super(obj, data);
    489    this.status = "invalid web extension";
    490  }
    491 }
    492 
    493 /**
    494 * An error occurred whilst executing JavaScript supplied by the user.
    495 *
    496 * @param {(string|Error)=} obj
    497 *     Optional string describing error situation or Error instance
    498 *     to propagate.
    499 * @param {object=} data
    500 *     Additional error data helpful in diagnosing the error.
    501 */
    502 class JavaScriptError extends WebDriverError {
    503  constructor(obj, data = {}) {
    504    super(obj, data);
    505    this.status = "javascript error";
    506  }
    507 }
    508 
    509 /**
    510 * The target for mouse interaction is not in the browser's viewport
    511 * and cannot be brought into that viewport.
    512 *
    513 * @param {(string|Error)=} obj
    514 *     Optional string describing error situation or Error instance
    515 *     to propagate.
    516 * @param {object=} data
    517 *     Additional error data helpful in diagnosing the error.
    518 */
    519 class MoveTargetOutOfBoundsError extends WebDriverError {
    520  constructor(obj, data = {}) {
    521    super(obj, data);
    522    this.status = "move target out of bounds";
    523  }
    524 }
    525 
    526 /**
    527 * An attempt was made to operate on a modal dialog when one was
    528 * not open.
    529 *
    530 * @param {(string|Error)=} obj
    531 *     Optional string describing error situation or Error instance
    532 *     to propagate.
    533 * @param {object=} data
    534 *     Additional error data helpful in diagnosing the error.
    535 */
    536 class NoSuchAlertError extends WebDriverError {
    537  constructor(obj, data = {}) {
    538    super(obj, data);
    539    this.status = "no such alert";
    540  }
    541 }
    542 
    543 /**
    544 * An element could not be located on the page using the given
    545 * search parameters.
    546 *
    547 * @param {(string|Error)=} obj
    548 *     Optional string describing error situation or Error instance
    549 *     to propagate.
    550 * @param {object=} data
    551 *     Additional error data helpful in diagnosing the error.
    552 */
    553 class NoSuchElementError extends WebDriverError {
    554  constructor(obj, data = {}) {
    555    super(obj, data);
    556    this.status = "no such element";
    557  }
    558 }
    559 
    560 /**
    561 * A command tried to remove an unknown preload script.
    562 *
    563 * @param {(string|Error)=} obj
    564 *     Optional string describing error situation or Error instance
    565 *     to propagate.
    566 * @param {object=} data
    567 *     Additional error data helpful in diagnosing the error.
    568 */
    569 class NoSuchScriptError extends WebDriverError {
    570  constructor(obj, data = {}) {
    571    super(obj, data);
    572    this.status = "no such script";
    573  }
    574 }
    575 
    576 /**
    577 * A shadow root was not attached to the element.
    578 *
    579 * @param {(string|Error)=} obj
    580 *     Optional string describing error situation or Error instance
    581 *     to propagate.
    582 * @param {object=} data
    583 *     Additional error data helpful in diagnosing the error.
    584 */
    585 class NoSuchShadowRootError extends WebDriverError {
    586  constructor(obj, data = {}) {
    587    super(obj, data);
    588    this.status = "no such shadow root";
    589  }
    590 }
    591 
    592 /**
    593 * A shadow root is no longer attached to the document.
    594 *
    595 * @param {(string|Error)=} obj
    596 *     Optional string describing error situation or Error instance
    597 *     to propagate.
    598 * @param {object=} data
    599 *     Additional error data helpful in diagnosing the error.
    600 */
    601 class DetachedShadowRootError extends WebDriverError {
    602  constructor(obj, data = {}) {
    603    super(obj, data);
    604    this.status = "detached shadow root";
    605  }
    606 }
    607 
    608 /**
    609 * A command to switch to a frame could not be satisfied because
    610 * the frame could not be found.
    611 *
    612 * @param {(string|Error)=} obj
    613 *     Optional string describing error situation or Error instance
    614 *     to propagate.
    615 * @param {object=} data
    616 *     Additional error data helpful in diagnosing the error.
    617 */
    618 class NoSuchFrameError extends WebDriverError {
    619  constructor(obj, data = {}) {
    620    super(obj, data);
    621    this.status = "no such frame";
    622  }
    623 }
    624 
    625 /**
    626 * The handle of a strong object reference could not be found.
    627 *
    628 * @param {(string|Error)=} obj
    629 *     Optional string describing error situation or Error instance
    630 *     to propagate.
    631 * @param {object=} data
    632 *     Additional error data helpful in diagnosing the error.
    633 */
    634 class NoSuchHandleError extends WebDriverError {
    635  constructor(obj, data = {}) {
    636    super(obj, data);
    637    this.status = "no such handle";
    638  }
    639 }
    640 
    641 /**
    642 * The entry of the history could not be found.
    643 *
    644 * @param {(string|Error)=} obj
    645 *     Optional string describing error situation or Error instance
    646 *     to propagate.
    647 * @param {object=} data
    648 *     Additional error data helpful in diagnosing the error.
    649 */
    650 class NoSuchHistoryEntryError extends WebDriverError {
    651  constructor(obj, data = {}) {
    652    super(obj, data);
    653    this.status = "no such history entry";
    654  }
    655 }
    656 
    657 /**
    658 * Tried to remove an unknown network intercept.
    659 *
    660 * @param {(string|Error)=} obj
    661 *     Optional string describing error situation or Error instance
    662 *     to propagate.
    663 * @param {object=} data
    664 *     Additional error data helpful in diagnosing the error.
    665 */
    666 class NoSuchInterceptError extends WebDriverError {
    667  constructor(obj, data = {}) {
    668    super(obj, data);
    669    this.status = "no such intercept";
    670  }
    671 }
    672 
    673 /**
    674 * A network data collector with the given unique id could not be found.
    675 *
    676 * @param {(string|Error)=} obj
    677 *     Optional string describing error situation or Error instance
    678 *     to propagate.
    679 * @param {object=} data
    680 *     Additional error data helpful in diagnosing the error.
    681 */
    682 class NoSuchNetworkCollectorError extends WebDriverError {
    683  constructor(obj, data = {}) {
    684    super(obj, data);
    685    this.status = "no such network collector";
    686  }
    687 }
    688 
    689 /**
    690 * A network data for the provided request id and data type could not be found.
    691 *
    692 * @param {(string|Error)=} obj
    693 *     Optional string describing error situation or Error instance
    694 *     to propagate.
    695 * @param {object=} data
    696 *     Additional error data helpful in diagnosing the error.
    697 */
    698 class NoSuchNetworkDataError extends WebDriverError {
    699  constructor(obj, data = {}) {
    700    super(obj, data);
    701    this.status = "no such network data";
    702  }
    703 }
    704 
    705 /**
    706 * A node as given by its unique shared id could not be found within the cache
    707 * of known nodes.
    708 *
    709 * @param {(string|Error)=} obj
    710 *     Optional string describing error situation or Error instance
    711 *     to propagate.
    712 * @param {object=} data
    713 *     Additional error data helpful in diagnosing the error.
    714 */
    715 class NoSuchNodeError extends WebDriverError {
    716  constructor(obj, data = {}) {
    717    super(obj, data);
    718    this.status = "no such node";
    719  }
    720 }
    721 
    722 /**
    723 * Tried to continue an unknown request.
    724 *
    725 * @param {(string|Error)=} obj
    726 *     Optional string describing error situation or Error instance
    727 *     to propagate.
    728 * @param {object=} data
    729 *     Additional error data helpful in diagnosing the error.
    730 */
    731 class NoSuchRequestError extends WebDriverError {
    732  constructor(obj, data = {}) {
    733    super(obj, data);
    734    this.status = "no such request";
    735  }
    736 }
    737 
    738 /**
    739 * A command tried to reference an unknown user context (containers in Firefox).
    740 *
    741 * @param {(string|Error)=} obj
    742 *     Optional string describing error situation or Error instance
    743 *     to propagate.
    744 * @param {object=} data
    745 *     Additional error data helpful in diagnosing the error.
    746 */
    747 class NoSuchUserContextError extends WebDriverError {
    748  constructor(obj, data = {}) {
    749    super(obj, data);
    750    this.status = "no such user context";
    751  }
    752 }
    753 
    754 /**
    755 * A command tried to reference an unknown web extension.
    756 *
    757 * @param {(string|Error)=} obj
    758 *     Optional string describing error situation or Error instance
    759 *     to propagate.
    760 * @param {object=} data
    761 *     Additional error data helpful in diagnosing the error.
    762 */
    763 class NoSuchWebExtensionError extends WebDriverError {
    764  constructor(obj, data = {}) {
    765    super(obj, data);
    766    this.status = "no such web extension";
    767  }
    768 }
    769 
    770 /**
    771 * A command to switch to a window could not be satisfied because
    772 * the window could not be found.
    773 *
    774 * @param {(string|Error)=} obj
    775 *     Optional string describing error situation or Error instance
    776 *     to propagate.
    777 * @param {object=} data
    778 *     Additional error data helpful in diagnosing the error.
    779 */
    780 class NoSuchWindowError extends WebDriverError {
    781  constructor(obj, data = {}) {
    782    super(obj, data);
    783    this.status = "no such window";
    784  }
    785 }
    786 
    787 /**
    788 * A script did not complete before its timeout expired.
    789 *
    790 * @param {(string|Error)=} obj
    791 *     Optional string describing error situation or Error instance
    792 *     to propagate.
    793 * @param {object=} data
    794 *     Additional error data helpful in diagnosing the error.
    795 */
    796 class ScriptTimeoutError extends WebDriverError {
    797  constructor(obj, data = {}) {
    798    super(obj, data);
    799    this.status = "script timeout";
    800  }
    801 }
    802 
    803 /**
    804 * A new session could not be created.
    805 *
    806 * @param {(string|Error)=} obj
    807 *     Optional string describing error situation or Error instance
    808 *     to propagate.
    809 * @param {object=} data
    810 *     Additional error data helpful in diagnosing the error.
    811 */
    812 class SessionNotCreatedError extends WebDriverError {
    813  constructor(obj, data = {}) {
    814    super(obj, data);
    815    this.status = "session not created";
    816  }
    817 }
    818 
    819 /**
    820 * A command failed because the referenced element is no longer
    821 * attached to the DOM.
    822 *
    823 * @param {(string|Error)=} obj
    824 *     Optional string describing error situation or Error instance
    825 *     to propagate.
    826 * @param {object=} data
    827 *     Additional error data helpful in diagnosing the error.
    828 */
    829 class StaleElementReferenceError extends WebDriverError {
    830  constructor(obj, options = {}) {
    831    super(obj, options);
    832    this.status = "stale element reference";
    833  }
    834 }
    835 
    836 /**
    837 * An operation did not complete before its timeout expired.
    838 *
    839 * @param {(string|Error)=} obj
    840 *     Optional string describing error situation or Error instance
    841 *     to propagate.
    842 * @param {object=} data
    843 *     Additional error data helpful in diagnosing the error.
    844 */
    845 class TimeoutError extends WebDriverError {
    846  constructor(obj, data = {}) {
    847    super(obj, data);
    848    this.status = "timeout";
    849  }
    850 }
    851 
    852 /**
    853 * A command to set a cookie's value could not be satisfied.
    854 *
    855 * @param {(string|Error)=} obj
    856 *     Optional string describing error situation or Error instance
    857 *     to propagate.
    858 * @param {object=} data
    859 *     Additional error data helpful in diagnosing the error.
    860 */
    861 class UnableToSetCookieError extends WebDriverError {
    862  constructor(obj, data = {}) {
    863    super(obj, data);
    864    this.status = "unable to set cookie";
    865  }
    866 }
    867 
    868 /**
    869 * A command to set a file could not be satisfied.
    870 *
    871 * @param {(string|Error)=} obj
    872 *     Optional string describing error situation or Error instance
    873 *     to propagate.
    874 * @param {object=} data
    875 *     Additional error data helpful in diagnosing the error.
    876 */
    877 class UnableToSetFileInputError extends WebDriverError {
    878  constructor(obj, data = {}) {
    879    super(obj, data);
    880    this.status = "unable to set file input";
    881  }
    882 }
    883 
    884 /**
    885 * A command to capture a screenshot could not be satisfied.
    886 *
    887 * @param {(string|Error)=} obj
    888 *     Optional string describing error situation or Error instance
    889 *     to propagate.
    890 * @param {object=} data
    891 *     Additional error data helpful in diagnosing the error.
    892 */
    893 class UnableToCaptureScreen extends WebDriverError {
    894  constructor(obj, data = {}) {
    895    super(obj, data);
    896    this.status = "unable to capture screen";
    897  }
    898 }
    899 
    900 /**
    901 * A network data content is not available.
    902 *
    903 * @param {(string|Error)=} obj
    904 *     Optional string describing error situation or Error instance
    905 *     to propagate.
    906 * @param {object=} data
    907 *     Additional error data helpful in diagnosing the error.
    908 */
    909 class UnavailableNetworkDataError extends WebDriverError {
    910  constructor(obj, data = {}) {
    911    super(obj, data);
    912    this.status = "unavailable network data";
    913  }
    914 }
    915 
    916 /**
    917 * A modal dialog was open, blocking this operation.
    918 *
    919 * @param {(string|Error)=} obj
    920 *     Optional string describing error situation or Error instance
    921 *     to propagate.
    922 * @param {object=} data
    923 *     Additional error data helpful in diagnosing the error.
    924 */
    925 class UnexpectedAlertOpenError extends WebDriverError {
    926  constructor(obj, data = {}) {
    927    super(obj, data);
    928    this.status = "unexpected alert open";
    929  }
    930 }
    931 
    932 /**
    933 * A command could not be executed because the remote end is not
    934 * aware of it.
    935 *
    936 * @param {(string|Error)=} obj
    937 *     Optional string describing error situation or Error instance
    938 *     to propagate.
    939 * @param {object=} data
    940 *     Additional error data helpful in diagnosing the error.
    941 */
    942 class UnknownCommandError extends WebDriverError {
    943  constructor(obj, data = {}) {
    944    super(obj, data);
    945    this.status = "unknown command";
    946  }
    947 }
    948 
    949 /**
    950 * An unknown error occurred in the remote end while processing
    951 * the command.
    952 *
    953 * @param {(string|Error)=} obj
    954 *     Optional string describing error situation or Error instance
    955 *     to propagate.
    956 * @param {object=} data
    957 *     Additional error data helpful in diagnosing the error.
    958 */
    959 class UnknownError extends WebDriverError {
    960  constructor(obj, data = {}) {
    961    super(obj, data);
    962    this.status = "unknown error";
    963  }
    964 }
    965 
    966 /**
    967 * Indicates that a command that should have executed properly
    968 * cannot be supported for some reason.
    969 *
    970 * @param {(string|Error)=} obj
    971 *     Optional string describing error situation or Error instance
    972 *     to propagate.
    973 * @param {object=} data
    974 *     Additional error data helpful in diagnosing the error.
    975 */
    976 class UnsupportedOperationError extends WebDriverError {
    977  constructor(obj, data = {}) {
    978    super(obj, data);
    979    this.status = "unsupported operation";
    980  }
    981 }
    982 
    983 const STATUSES = new Map([
    984  ["detached shadow root", DetachedShadowRootError],
    985  ["element click intercepted", ElementClickInterceptedError],
    986  ["element not accessible", ElementNotAccessibleError],
    987  ["element not interactable", ElementNotInteractableError],
    988  ["insecure certificate", InsecureCertificateError],
    989  ["invalid argument", InvalidArgumentError],
    990  ["invalid cookie domain", InvalidCookieDomainError],
    991  ["invalid element state", InvalidElementStateError],
    992  ["invalid selector", InvalidSelectorError],
    993  ["invalid session id", InvalidSessionIDError],
    994  ["invalid web extension", InvalidWebExtensionError],
    995  ["javascript error", JavaScriptError],
    996  ["move target out of bounds", MoveTargetOutOfBoundsError],
    997  ["no such alert", NoSuchAlertError],
    998  ["no such element", NoSuchElementError],
    999  ["no such frame", NoSuchFrameError],
   1000  ["no such handle", NoSuchHandleError],
   1001  ["no such history entry", NoSuchHistoryEntryError],
   1002  ["no such intercept", NoSuchInterceptError],
   1003  ["no such network collector", NoSuchNetworkCollectorError],
   1004  ["no such network data", NoSuchNetworkDataError],
   1005  ["no such node", NoSuchNodeError],
   1006  ["no such request", NoSuchRequestError],
   1007  ["no such script", NoSuchScriptError],
   1008  ["no such shadow root", NoSuchShadowRootError],
   1009  ["no such user context", NoSuchUserContextError],
   1010  ["no such web extension", NoSuchWebExtensionError],
   1011  ["no such window", NoSuchWindowError],
   1012  ["script timeout", ScriptTimeoutError],
   1013  ["session not created", SessionNotCreatedError],
   1014  ["stale element reference", StaleElementReferenceError],
   1015  ["timeout", TimeoutError],
   1016  ["unable to capture screen", UnableToCaptureScreen],
   1017  ["unable to set cookie", UnableToSetCookieError],
   1018  ["unable to set file input", UnableToSetFileInputError],
   1019  ["unavailable network data", UnavailableNetworkDataError],
   1020  ["unexpected alert open", UnexpectedAlertOpenError],
   1021  ["unknown command", UnknownCommandError],
   1022  ["unknown error", UnknownError],
   1023  ["unsupported operation", UnsupportedOperationError],
   1024  ["webdriver error", WebDriverError],
   1025 ]);
   1026 
   1027 // Errors must be exported as part of the `error` object.
   1028 // We could declare each error as global variable, but because they are Error
   1029 // prototypes this would mess up their names.
   1030 for (let cls of STATUSES.values()) {
   1031  error[cls.name] = cls;
   1032 }