lib/jsdom/browser/Window.js
function Window(options) {
  EventTarget.setup(this);

  const rawPerformance = new RawPerformance();
  const windowInitialized = rawPerformance.now();

  const window = this;

  mixin(window, WindowEventHandlersImpl.prototype);
  mixin(window, GlobalEventHandlersImpl.prototype);

  this._initGlobalEvents();

  ///// INTERFACES FROM THE DOM
  // TODO: consider a mode of some sort where these are not shared between all DOM instances
  // It'd be very memory-expensive in most cases, though.
  for (const name in dom) {
    Object.defineProperty(window, name, {
      enumerable: false,
      configurable: true,
      writable: true,
      value: dom[name]
    });
  }

  ///// PRIVATE DATA PROPERTIES

  this._resourceLoader = options.resourceLoader;

  // vm initialization is deferred until script processing is activated
  this._globalProxy = this;
  Object.defineProperty(idlUtils.implForWrapper(this), idlUtils.wrapperSymbol, { get: () => this._globalProxy });

  let timers = Object.create(null);
  let animationFrameCallbacks = Object.create(null);

  // List options explicitly to be clear which are passed through
  this._document = Document.create([], {
    options: {
      parsingMode: options.parsingMode,
      contentType: options.contentType,
      encoding: options.encoding,
      cookieJar: options.cookieJar,
      url: options.url,
      lastModified: options.lastModified,
      referrer: options.referrer,
      concurrentNodeIterators: options.concurrentNodeIterators,
      parseOptions: options.parseOptions,
      defaultView: this._globalProxy,
      global: this
    }
  });
  // https://html.spec.whatwg.org/#session-history
  this._sessionHistory = new SessionHistory({
    document: idlUtils.implForWrapper(this._document),
    url: idlUtils.implForWrapper(this._document)._URL,
    stateObject: null
  }, this);

  this._virtualConsole = options.virtualConsole;

  this._runScripts = options.runScripts;
  if (this._runScripts === "outside-only" || this._runScripts === "dangerously") {
    contextifyWindow(this);
  }

  // Set up the window as if it's a top level window.
  // If it's not, then references will be corrected by frame/iframe code.
  this._parent = this._top = this._globalProxy;
  this._frameElement = null;

  // This implements window.frames.length, since window.frames returns a
  // self reference to the window object.  This value is incremented in the
  // HTMLFrameElement implementation.
  this._length = 0;

  this._pretendToBeVisual = options.pretendToBeVisual;
  this._storageQuota = options.storageQuota;

  // Some properties (such as localStorage and sessionStorage) share data
  // between windows in the same origin. This object is intended
  // to contain such data.
  if (options.commonForOrigin && options.commonForOrigin[this._document.origin]) {
    this._commonForOrigin = options.commonForOrigin;
  } else {
    this._commonForOrigin = {
      [this._document.origin]: {
        localStorageArea: new Map(),
        sessionStorageArea: new Map(),
        windowsInSameOrigin: [this]
      }
    };
  }

  this._currentOriginData = this._commonForOrigin[this._document.origin];

  ///// WEB STORAGE

  this._localStorage = Storage.create([], {
    associatedWindow: this,
    storageArea: this._currentOriginData.localStorageArea,
    type: "localStorage",
    url: this._document.documentURI,
    storageQuota: this._storageQuota
  });
  this._sessionStorage = Storage.create([], {
    associatedWindow: this,
    storageArea: this._currentOriginData.sessionStorageArea,
    type: "sessionStorage",
    url: this._document.documentURI,
    storageQuota: this._storageQuota
  });

  ///// GETTERS

  const locationbar = BarProp.create();
  const menubar = BarProp.create();
  const personalbar = BarProp.create();
  const scrollbars = BarProp.create();
  const statusbar = BarProp.create();
  const toolbar = BarProp.create();
  const external = External.create();
  const navigator = Navigator.create([], { userAgent: this._resourceLoader._userAgent });
  const performance = Performance.create([], { rawPerformance });
  const screen = Screen.create();

  define(this, {
    get length() {
      return window._length;
    },
    get window() {
      return window._globalProxy;
    },
    get frameElement() {
      return idlUtils.wrapperForImpl(window._frameElement);
    },
    get frames() {
      return window._globalProxy;
    },
    get self() {
      return window._globalProxy;
    },
    get parent() {
      return window._parent;
    },
    get top() {
      return window._top;
    },
    get document() {
      return window._document;
    },
    get external() {
      return external;
    },
    get location() {
      return idlUtils.wrapperForImpl(idlUtils.implForWrapper(window._document)._location);
    },
    get history() {
      return idlUtils.wrapperForImpl(idlUtils.implForWrapper(window._document)._history);
    },
    get navigator() {
      return navigator;
    },
    get locationbar() {
      return locationbar;
    },
    get menubar() {
      return menubar;
    },
    get personalbar() {
      return personalbar;
    },
    get scrollbars() {
      return scrollbars;
    },
    get statusbar() {
      return statusbar;
    },
    get toolbar() {
      return toolbar;
    },
    get performance() {
      return performance;
    },
    get screen() {
      return screen;
    },
    get localStorage() {
      if (this._document.origin === "null") {
        throw new DOMException("localStorage is not available for opaque origins", "SecurityError");
      }

      return this._localStorage;
    },
    get sessionStorage() {
      if (this._document.origin === "null") {
        throw new DOMException("sessionStorage is not available for opaque origins", "SecurityError");
      }

      return this._sessionStorage;
    }
  });

  namedPropertiesWindow.initializeWindow(this, this._globalProxy);

  ///// METHODS for [ImplicitThis] hack
  // See https://lists.w3.org/Archives/Public/public-script-coord/2015JanMar/0109.html
  this.addEventListener = this.addEventListener.bind(this);
  this.removeEventListener = this.removeEventListener.bind(this);
  this.dispatchEvent = this.dispatchEvent.bind(this);

  ///// METHODS

  let latestTimerId = 0;
  let latestAnimationFrameCallbackId = 0;

  this.setTimeout = function (fn, ms) {
    const args = [];
    for (let i = 2; i < arguments.length; ++i) {
      args[i - 2] = arguments[i];
    }
    return startTimer(window, setTimeout, clearTimeout, ++latestTimerId, fn, ms, timers, args);
  };
  this.setInterval = function (fn, ms) {
    const args = [];
    for (let i = 2; i < arguments.length; ++i) {
      args[i - 2] = arguments[i];
    }
    return startTimer(window, setInterval, clearInterval, ++latestTimerId, fn, ms, timers, args);
  };
  this.clearInterval = stopTimer.bind(this, timers);
  this.clearTimeout = stopTimer.bind(this, timers);

  if (this._pretendToBeVisual) {
    this.requestAnimationFrame = fn => {
      const timestamp = rawPerformance.now() - windowInitialized;
      const fps = 1000 / 60;

      return startTimer(
        window,
        setTimeout,
        clearTimeout,
        ++latestAnimationFrameCallbackId,
        fn,
        fps,
        animationFrameCallbacks,
        [timestamp]
      );
    };
    this.cancelAnimationFrame = stopTimer.bind(this, animationFrameCallbacks);
  }

  this.__stopAllTimers = function () {
    stopAllTimers(timers);
    stopAllTimers(animationFrameCallbacks);

    latestTimerId = 0;
    latestAnimationFrameCallbackId = 0;

    timers = Object.create(null);
    animationFrameCallbacks = Object.create(null);
  };

  function Option(text, value, defaultSelected, selected) {
    if (text === undefined) {
      text = "";
    }
    text = webIDLConversions.DOMString(text);

    if (value !== undefined) {
      value = webIDLConversions.DOMString(value);
    }

    defaultSelected = webIDLConversions.boolean(defaultSelected);
    selected = webIDLConversions.boolean(selected);

    const option = window._document.createElement("option");
    const impl = idlUtils.implForWrapper(option);

    if (text !== "") {
      impl.text = text;
    }
    if (value !== undefined) {
      impl.setAttributeNS(null, "value", value);
    }
    if (defaultSelected) {
      impl.setAttributeNS(null, "selected", "");
    }
    impl._selectedness = selected;

    return option;
  }
  Object.defineProperty(Option, "prototype", {
    value: this.HTMLOptionElement.prototype,
    configurable: false,
    enumerable: false,
    writable: false
  });
  Object.defineProperty(window, "Option", {
    value: Option,
    configurable: true,
    enumerable: false,
    writable: true
  });

  function Image() {
    const img = window._document.createElement("img");
    const impl = idlUtils.implForWrapper(img);

    if (arguments.length > 0) {
      impl.setAttributeNS(null, "width", String(arguments[0]));
    }
    if (arguments.length > 1) {
      impl.setAttributeNS(null, "height", String(arguments[1]));
    }

    return img;
  }
  Object.defineProperty(Image, "prototype", {
    value: this.HTMLImageElement.prototype,
    configurable: false,
    enumerable: false,
    writable: false
  });
  Object.defineProperty(window, "Image", {
    value: Image,
    configurable: true,
    enumerable: false,
    writable: true
  });

  function Audio(src) {
    const audio = window._document.createElement("audio");
    const impl = idlUtils.implForWrapper(audio);
    impl.setAttributeNS(null, "preload", "auto");

    if (src !== undefined) {
      impl.setAttributeNS(null, "src", String(src));
    }

    return audio;
  }
  Object.defineProperty(Audio, "prototype", {
    value: this.HTMLAudioElement.prototype,
    configurable: false,
    enumerable: false,
    writable: false
  });
  Object.defineProperty(window, "Audio", {
    value: Audio,
    configurable: true,
    enumerable: false,
    writable: true
  });

  this.postMessage = postMessage;

  this.atob = function (str) {
    const result = atob(str);
    if (result === null) {
      throw new DOMException("The string to be decoded contains invalid characters.", "InvalidCharacterError");
    }
    return result;
  };

  this.btoa = function (str) {
    const result = btoa(str);
    if (result === null) {
      throw new DOMException("The string to be encoded contains invalid characters.", "InvalidCharacterError");
    }
    return result;
  };

  this.FileReader = createFileReader({
    window: this
  }).interface;
  this.WebSocket = createWebSocket({
    window: this
  }).interface;

  const AbortSignalWrapper = createAbortSignal({
    window: this
  });
  this.AbortSignal = AbortSignalWrapper.interface;
  this.AbortController = createAbortController({
    AbortSignal: AbortSignalWrapper
  }).interface;

  this.XMLHttpRequest = createXMLHttpRequest(this);

  // TODO: necessary for Blob and FileReader due to different-globals weirdness; investigate how to avoid this.
  this.ArrayBuffer = ArrayBuffer;
  this.Int8Array = Int8Array;
  this.Uint8Array = Uint8Array;
  this.Uint8ClampedArray = Uint8ClampedArray;
  this.Int16Array = Int16Array;
  this.Uint16Array = Uint16Array;
  this.Int32Array = Int32Array;
  this.Uint32Array = Uint32Array;
  this.Float32Array = Float32Array;
  this.Float64Array = Float64Array;

  this.stop = function () {
    const manager = idlUtils.implForWrapper(this._document)._requestManager;
    if (manager) {
      manager.close();
    }
  };

  this.close = function () {
    // Recursively close child frame windows, then ourselves.
    const currentWindow = this;
    (function windowCleaner(windowToClean) {
      for (let i = 0; i < windowToClean.length; i++) {
        windowCleaner(windowToClean[i]);
      }

      // We"re already in our own window.close().
      if (windowToClean !== currentWindow) {
        windowToClean.close();
      }
    }(this));

    // Clear out all listeners. Any in-flight or upcoming events should not get delivered.
    idlUtils.implForWrapper(this)._eventListeners = Object.create(null);

    if (this._document) {
      if (this._document.body) {
        this._document.body.innerHTML = "";
      }

      if (this._document.close) {
        // It's especially important to clear out the listeners here because document.close() causes a "load" event to
        // fire.
        idlUtils.implForWrapper(this._document)._eventListeners = Object.create(null);
        this._document.close();
      }
      const doc = idlUtils.implForWrapper(this._document);
      if (doc._requestManager) {
        doc._requestManager.close();
      }
      delete this._document;
    }

    this.__stopAllTimers();
    WebSocketImpl.cleanUpWindow(this);
  };

  this.getComputedStyle = function (elt) {
    elt = Element.convert(elt);

    const declaration = new CSSStyleDeclaration();
    const { forEach, indexOf } = Array.prototype;
    const { style } = elt;

    function setPropertiesFromRule(rule) {
      if (!rule.selectorText) {
        return;
      }

      const cssSelectorSplitRe = /((?:[^,"']|"[^"]*"|'[^']*')+)/;
      const selectors = rule.selectorText.split(cssSelectorSplitRe);
      let matched = false;

      for (const selectorText of selectors) {
        if (selectorText !== "" && selectorText !== "," && !matched && matchesDontThrow(elt, selectorText)) {
          matched = true;
          forEach.call(rule.style, property => {
            declaration.setProperty(
              property,
              rule.style.getPropertyValue(property),
              rule.style.getPropertyPriority(property)
            );
          });
        }
      }
    }

    function readStylesFromStyleSheet(sheet) {
      forEach.call(sheet.cssRules, rule => {
        if (rule.media) {
          if (indexOf.call(rule.media, "screen") !== -1) {
            forEach.call(rule.cssRules, setPropertiesFromRule);
          }
        } else {
          setPropertiesFromRule(rule);
        }
      });
    }

    if (!parsedDefaultStyleSheet) {
      parsedDefaultStyleSheet = cssom.parse(defaultStyleSheet);
    }
    readStylesFromStyleSheet(parsedDefaultStyleSheet);
    forEach.call(elt.ownerDocument.styleSheets, readStylesFromStyleSheet);

    forEach.call(style, property => {
      declaration.setProperty(property, style.getPropertyValue(property), style.getPropertyPriority(property));
    });

    return declaration;
  };

  // The captureEvents() and releaseEvents() methods must do nothing
  this.captureEvents = function () {};

  this.releaseEvents = function () {};

  ///// PUBLIC DATA PROPERTIES (TODO: should be getters)

  function wrapConsoleMethod(method) {
    return (...args) => {
      window._virtualConsole.emit(method, ...args);
    };
  }

  this.console = {
    assert: wrapConsoleMethod("assert"),
    clear: wrapConsoleMethod("clear"),
    count: wrapConsoleMethod("count"),
    countReset: wrapConsoleMethod("countReset"),
    debug: wrapConsoleMethod("debug"),
    dir: wrapConsoleMethod("dir"),
    dirxml: wrapConsoleMethod("dirxml"),
    error: wrapConsoleMethod("error"),
    group: wrapConsoleMethod("group"),
    groupCollapsed: wrapConsoleMethod("groupCollapsed"),
    groupEnd: wrapConsoleMethod("groupEnd"),
    info: wrapConsoleMethod("info"),
    log: wrapConsoleMethod("log"),
    table: wrapConsoleMethod("table"),
    time: wrapConsoleMethod("time"),
    timeEnd: wrapConsoleMethod("timeEnd"),
    trace: wrapConsoleMethod("trace"),
    warn: wrapConsoleMethod("warn")
  };

  function notImplementedMethod(name) {
    return function () {
      notImplemented(name, window);
    };
  }

  define(this, {
    name: "",
    status: "",
    devicePixelRatio: 1,
    innerWidth: 1024,
    innerHeight: 768,
    outerWidth: 1024,
    outerHeight: 768,
    pageXOffset: 0,
    pageYOffset: 0,
    screenX: 0,
    screenLeft: 0,
    screenY: 0,
    screenTop: 0,
    scrollX: 0,
    scrollY: 0,

    alert: notImplementedMethod("window.alert"),
    blur: notImplementedMethod("window.blur"),
    confirm: notImplementedMethod("window.confirm"),
    focus: notImplementedMethod("window.focus"),
    moveBy: notImplementedMethod("window.moveBy"),
    moveTo: notImplementedMethod("window.moveTo"),
    open: notImplementedMethod("window.open"),
    print: notImplementedMethod("window.print"),
    prompt: notImplementedMethod("window.prompt"),
    resizeBy: notImplementedMethod("window.resizeBy"),
    resizeTo: notImplementedMethod("window.resizeTo"),
    scroll: notImplementedMethod("window.scroll"),
    scrollBy: notImplementedMethod("window.scrollBy"),
    scrollTo: notImplementedMethod("window.scrollTo")
  });

  ///// INITIALIZATION

  process.nextTick(() => {
    if (!window.document) {
      return; // window might've been closed already
    }

    if (window.document.readyState === "complete") {
      fireAnEvent("load", window, undefined, {}, window.document);
    } else {
      window.document.addEventListener("load", () => {
        fireAnEvent("load", window, undefined, {}, window.document);

        if (!idlUtils.implForWrapper(window._document)._pageShowingFlag) {
          idlUtils.implForWrapper(window._document)._pageShowingFlag = true;
          fireAnEvent("pageshow", window, PageTransitionEvent, { persisted: false }, window.document);
        }
      });
    }
  });
}
function Window(options) {
  EventTarget.setup(this);

  const rawPerformance = new RawPerformance();
  const windowInitialized = rawPerformance.now();

  const window = this;

  mixin(window, WindowEventHandlersImpl.prototype);
  mixin(window, GlobalEventHandlersImpl.prototype);

  this._initGlobalEvents();

  ///// INTERFACES FROM THE DOM
  // TODO: consider a mode of some sort where these are not shared between all DOM instances
  // It'd be very memory-expensive in most cases, though.
  for (const name in dom) {
    Object.defineProperty(window, name, {
      enumerable: false,
      configurable: true,
      writable: true,
      value: dom[name]
    });
  }

  ///// PRIVATE DATA PROPERTIES

  this._resourceLoader = options.resourceLoader;

  // vm initialization is deferred until script processing is activated
  this._globalProxy = this;
  Object.defineProperty(idlUtils.implForWrapper(this), idlUtils.wrapperSymbol, { get: () => this._globalProxy });

  let timers = Object.create(null);
  let animationFrameCallbacks = Object.create(null);

  // List options explicitly to be clear which are passed through
  this._document = Document.create([], {
    options: {
      parsingMode: options.parsingMode,
      contentType: options.contentType,
      encoding: options.encoding,
      cookieJar: options.cookieJar,
      url: options.url,
      lastModified: options.lastModified,
      referrer: options.referrer,
      concurrentNodeIterators: options.concurrentNodeIterators,
      parseOptions: options.parseOptions,
      defaultView: this._globalProxy,
      global: this
    }
  });
  // https://html.spec.whatwg.org/#session-history
  this._sessionHistory = new SessionHistory({
    document: idlUtils.implForWrapper(this._document),
    url: idlUtils.implForWrapper(this._document)._URL,
    stateObject: null
  }, this);

  this._virtualConsole = options.virtualConsole;

  this._runScripts = options.runScripts;
  if (this._runScripts === "outside-only" || this._runScripts === "dangerously") {
    contextifyWindow(this);
  }

  // Set up the window as if it's a top level window.
  // If it's not, then references will be corrected by frame/iframe code.
  this._parent = this._top = this._globalProxy;
  this._frameElement = null;

  // This implements window.frames.length, since window.frames returns a
  // self reference to the window object.  This value is incremented in the
  // HTMLFrameElement implementation.
  this._length = 0;

  this._pretendToBeVisual = options.pretendToBeVisual;
  this._storageQuota = options.storageQuota;

  // Some properties (such as localStorage and sessionStorage) share data
  // between windows in the same origin. This object is intended
  // to contain such data.
  if (options.commonForOrigin && options.commonForOrigin[this._document.origin]) {
    this._commonForOrigin = options.commonForOrigin;
  } else {
    this._commonForOrigin = {
      [this._document.origin]: {
        localStorageArea: new Map(),
        sessionStorageArea: new Map(),
        windowsInSameOrigin: [this]
      }
    };
  }

  this._currentOriginData = this._commonForOrigin[this._document.origin];

  ///// WEB STORAGE

  this._localStorage = Storage.create([], {
    associatedWindow: this,
    storageArea: this._currentOriginData.localStorageArea,
    type: "localStorage",
    url: this._document.documentURI,
    storageQuota: this._storageQuota
  });
  this._sessionStorage = Storage.create([], {
    associatedWindow: this,
    storageArea: this._currentOriginData.sessionStorageArea,
    type: "sessionStorage",
    url: this._document.documentURI,
    storageQuota: this._storageQuota
  });

  ///// GETTERS

  const locationbar = BarProp.create();
  const menubar = BarProp.create();
  const personalbar = BarProp.create();
  const scrollbars = BarProp.create();
  const statusbar = BarProp.create();
  const toolbar = BarProp.create();
  const external = External.create();
  const navigator = Navigator.create([], { userAgent: this._resourceLoader._userAgent });
  const performance = Performance.create([], { rawPerformance });
  const screen = Screen.create();

  define(this, {
    get length() {
      return window._length;
    },
    get window() {
      return window._globalProxy;
    },
    get frameElement() {
      return idlUtils.wrapperForImpl(window._frameElement);
    },
    get frames() {
      return window._globalProxy;
    },
    get self() {
      return window._globalProxy;
    },
    get parent() {
      return window._parent;
    },
    get top() {
      return window._top;
    },
    get document() {
      return window._document;
    },
    get external() {
      return external;
    },
    get location() {
      return idlUtils.wrapperForImpl(idlUtils.implForWrapper(window._document)._location);
    },
    get history() {
      return idlUtils.wrapperForImpl(idlUtils.implForWrapper(window._document)._history);
    },
    get navigator() {
      return navigator;
    },
    get locationbar() {
      return locationbar;
    },
    get menubar() {
      return menubar;
    },
    get personalbar() {
      return personalbar;
    },
    get scrollbars() {
      return scrollbars;
    },
    get statusbar() {
      return statusbar;
    },
    get toolbar() {
      return toolbar;
    },
    get performance() {
      return performance;
    },
    get screen() {
      return screen;
    },
    get localStorage() {
      if (this._document.origin === "null") {
        throw new DOMException("localStorage is not available for opaque origins", "SecurityError");
      }

      return this._localStorage;
    },
    get sessionStorage() {
      if (this._document.origin === "null") {
        throw new DOMException("sessionStorage is not available for opaque origins", "SecurityError");
      }

      return this._sessionStorage;
    }
  });

  namedPropertiesWindow.initializeWindow(this, this._globalProxy);

  ///// METHODS for [ImplicitThis] hack
  // See https://lists.w3.org/Archives/Public/public-script-coord/2015JanMar/0109.html
  this.addEventListener = this.addEventListener.bind(this);
  this.removeEventListener = this.removeEventListener.bind(this);
  this.dispatchEvent = this.dispatchEvent.bind(this);

  ///// METHODS

  let latestTimerId = 0;
  let latestAnimationFrameCallbackId = 0;

  this.setTimeout = function (fn, ms) {
    const args = [];
    for (let i = 2; i < arguments.length; ++i) {
      args[i - 2] = arguments[i];
    }
    return startTimer(window, setTimeout, clearTimeout, ++latestTimerId, fn, ms, timers, args);
  };
  this.setInterval = function (fn, ms) {
    const args = [];
    for (let i = 2; i < arguments.length; ++i) {
      args[i - 2] = arguments[i];
    }
    return startTimer(window, setInterval, clearInterval, ++latestTimerId, fn, ms, timers, args);
  };
  this.clearInterval = stopTimer.bind(this, timers);
  this.clearTimeout = stopTimer.bind(this, timers);

  if (this._pretendToBeVisual) {
    this.requestAnimationFrame = fn => {
      const timestamp = rawPerformance.now() - windowInitialized;
      const fps = 1000 / 60;

      return startTimer(
        window,
        setTimeout,
        clearTimeout,
        ++latestAnimationFrameCallbackId,
        fn,
        fps,
        animationFrameCallbacks,
        [timestamp]
      );
    };
    this.cancelAnimationFrame = stopTimer.bind(this, animationFrameCallbacks);
  }

  this.__stopAllTimers = function () {
    stopAllTimers(timers);
    stopAllTimers(animationFrameCallbacks);

    latestTimerId = 0;
    latestAnimationFrameCallbackId = 0;

    timers = Object.create(null);
    animationFrameCallbacks = Object.create(null);
  };

  function Option(text, value, defaultSelected, selected) {
    if (text === undefined) {
      text = "";
    }
    text = webIDLConversions.DOMString(text);

    if (value !== undefined) {
      value = webIDLConversions.DOMString(value);
    }

    defaultSelected = webIDLConversions.boolean(defaultSelected);
    selected = webIDLConversions.boolean(selected);

    const option = window._document.createElement("option");
    const impl = idlUtils.implForWrapper(option);

    if (text !== "") {
      impl.text = text;
    }
    if (value !== undefined) {
      impl.setAttributeNS(null, "value", value);
    }
    if (defaultSelected) {
      impl.setAttributeNS(null, "selected", "");
    }
    impl._selectedness = selected;

    return option;
  }
  Object.defineProperty(Option, "prototype", {
    value: this.HTMLOptionElement.prototype,
    configurable: false,
    enumerable: false,
    writable: false
  });
  Object.defineProperty(window, "Option", {
    value: Option,
    configurable: true,
    enumerable: false,
    writable: true
  });

  function Image() {
    const img = window._document.createElement("img");
    const impl = idlUtils.implForWrapper(img);

    if (arguments.length > 0) {
      impl.setAttributeNS(null, "width", String(arguments[0]));
    }
    if (arguments.length > 1) {
      impl.setAttributeNS(null, "height", String(arguments[1]));
    }

    return img;
  }
  Object.defineProperty(Image, "prototype", {
    value: this.HTMLImageElement.prototype,
    configurable: false,
    enumerable: false,
    writable: false
  });
  Object.defineProperty(window, "Image", {
    value: Image,
    configurable: true,
    enumerable: false,
    writable: true
  });

  function Audio(src) {
    const audio = window._document.createElement("audio");
    const impl = idlUtils.implForWrapper(audio);
    impl.setAttributeNS(null, "preload", "auto");

    if (src !== undefined) {
      impl.setAttributeNS(null, "src", String(src));
    }

    return audio;
  }
  Object.defineProperty(Audio, "prototype", {
    value: this.HTMLAudioElement.prototype,
    configurable: false,
    enumerable: false,
    writable: false
  });
  Object.defineProperty(window, "Audio", {
    value: Audio,
    configurable: true,
    enumerable: false,
    writable: true
  });

  this.postMessage = postMessage;

  this.atob = function (str) {
    const result = atob(str);
    if (result === null) {
      throw new DOMException("The string to be decoded contains invalid characters.", "InvalidCharacterError");
    }
    return result;
  };

  this.btoa = function (str) {
    const result = btoa(str);
    if (result === null) {
      throw new DOMException("The string to be encoded contains invalid characters.", "InvalidCharacterError");
    }
    return result;
  };

  this.FileReader = createFileReader({
    window: this
  }).interface;
  this.WebSocket = createWebSocket({
    window: this
  }).interface;

  const AbortSignalWrapper = createAbortSignal({
    window: this
  });
  this.AbortSignal = AbortSignalWrapper.interface;
  this.AbortController = createAbortController({
    AbortSignal: AbortSignalWrapper
  }).interface;

  this.XMLHttpRequest = createXMLHttpRequest(this);

  // TODO: necessary for Blob and FileReader due to different-globals weirdness; investigate how to avoid this.
  this.ArrayBuffer = ArrayBuffer;
  this.Int8Array = Int8Array;
  this.Uint8Array = Uint8Array;
  this.Uint8ClampedArray = Uint8ClampedArray;
  this.Int16Array = Int16Array;
  this.Uint16Array = Uint16Array;
  this.Int32Array = Int32Array;
  this.Uint32Array = Uint32Array;
  this.Float32Array = Float32Array;
  this.Float64Array = Float64Array;

  this.stop = function () {
    const manager = idlUtils.implForWrapper(this._document)._requestManager;
    if (manager) {
      manager.close();
    }
  };

  this.close = function () {
    // Recursively close child frame windows, then ourselves.
    const currentWindow = this;
    (function windowCleaner(windowToClean) {
      for (let i = 0; i < windowToClean.length; i++) {
        windowCleaner(windowToClean[i]);
      }

      // We"re already in our own window.close().
      if (windowToClean !== currentWindow) {
        windowToClean.close();
      }
    }(this));

    // Clear out all listeners. Any in-flight or upcoming events should not get delivered.
    idlUtils.implForWrapper(this)._eventListeners = Object.create(null);

    if (this._document) {
      if (this._document.body) {
        this._document.body.innerHTML = "";
      }

      if (this._document.close) {
        // It's especially important to clear out the listeners here because document.close() causes a "load" event to
        // fire.
        idlUtils.implForWrapper(this._document)._eventListeners = Object.create(null);
        this._document.close();
      }
      const doc = idlUtils.implForWrapper(this._document);
      if (doc._requestManager) {
        doc._requestManager.close();
      }
      delete this._document;
    }

    this.__stopAllTimers();
    WebSocketImpl.cleanUpWindow(this);
  };

  this.getComputedStyle = function (elt) {
    elt = Element.convert(elt);

    const declaration = new CSSStyleDeclaration();
    const { forEach, indexOf } = Array.prototype;
    const { style } = elt;

    function setPropertiesFromRule(rule) {
      if (!rule.selectorText) {
        return;
      }

      const cssSelectorSplitRe = /((?:[^,"']|"[^"]*"|'[^']*')+)/;
      const selectors = rule.selectorText.split(cssSelectorSplitRe);
      let matched = false;

      for (const selectorText of selectors) {
        if (selectorText !== "" && selectorText !== "," && !matched && matchesDontThrow(elt, selectorText)) {
          matched = true;
          forEach.call(rule.style, property => {
            declaration.setProperty(
              property,
              rule.style.getPropertyValue(property),
              rule.style.getPropertyPriority(property)
            );
          });
        }
      }
    }

    function readStylesFromStyleSheet(sheet) {
      forEach.call(sheet.cssRules, rule => {
        if (rule.media) {
          if (indexOf.call(rule.media, "screen") !== -1) {
            forEach.call(rule.cssRules, setPropertiesFromRule);
          }
        } else {
          setPropertiesFromRule(rule);
        }
      });
    }

    if (!parsedDefaultStyleSheet) {
      parsedDefaultStyleSheet = cssom.parse(defaultStyleSheet);
    }
    readStylesFromStyleSheet(parsedDefaultStyleSheet);
    forEach.call(elt.ownerDocument.styleSheets, readStylesFromStyleSheet);

    forEach.call(style, property => {
      declaration.setProperty(property, style.getPropertyValue(property), style.getPropertyPriority(property));
    });

    return declaration;
  };

  // The captureEvents() and releaseEvents() methods must do nothing
  this.captureEvents = function () {};

  this.releaseEvents = function () {};

  ///// PUBLIC DATA PROPERTIES (TODO: should be getters)

  function wrapConsoleMethod(method) {
    return (...args) => {
      window._virtualConsole.emit(method, ...args);
    };
  }

  this.console = {
    assert: wrapConsoleMethod("assert"),
    clear: wrapConsoleMethod("clear"),
    count: wrapConsoleMethod("count"),
    countReset: wrapConsoleMethod("countReset"),
    debug: wrapConsoleMethod("debug"),
    dir: wrapConsoleMethod("dir"),
    dirxml: wrapConsoleMethod("dirxml"),
    error: wrapConsoleMethod("error"),
    group: wrapConsoleMethod("group"),
    groupCollapsed: wrapConsoleMethod("groupCollapsed"),
    groupEnd: wrapConsoleMethod("groupEnd"),
    info: wrapConsoleMethod("info"),
    log: wrapConsoleMethod("log"),
    table: wrapConsoleMethod("table"),
    time: wrapConsoleMethod("time"),
    timeEnd: wrapConsoleMethod("timeEnd"),
    trace: wrapConsoleMethod("trace"),
    warn: wrapConsoleMethod("warn")
  };

  function notImplementedMethod(name) {
    return function () {
      notImplemented(name, window);
    };
  }

  define(this, {
    name: "",
    status: "",
    devicePixelRatio: 1,
    innerWidth: 1024,
    innerHeight: 768,
    outerWidth: 1024,
    outerHeight: 768,
    pageXOffset: 0,
    pageYOffset: 0,
    screenX: 0,
    screenLeft: 0,
    screenY: 0,
    screenTop: 0,
    scrollX: 0,
    scrollY: 0,

    alert: notImplementedMethod("window.alert"),
    blur: notImplementedMethod("window.blur"),
    confirm: notImplementedMethod("window.confirm"),
    focus: notImplementedMethod("window.focus"),
    moveBy: notImplementedMethod("window.moveBy"),
    moveTo: notImplementedMethod("window.moveTo"),
    open: notImplementedMethod("window.open"),
    print: notImplementedMethod("window.print"),
    prompt: notImplementedMethod("window.prompt"),
    resizeBy: notImplementedMethod("window.resizeBy"),
    resizeTo: notImplementedMethod("window.resizeTo"),
    scroll: notImplementedMethod("window.scroll"),
    scrollBy: notImplementedMethod("window.scrollBy"),
    scrollTo: notImplementedMethod("window.scrollTo")
  });

  ///// INITIALIZATION

  process.nextTick(() => {
    if (!window.document) {
      return; // window might've been closed already
    }

    if (window.document.readyState === "complete") {
      fireAnEvent("load", window, undefined, {}, window.document);
    } else {
      window.document.addEventListener("load", () => {
        fireAnEvent("load", window, undefined, {}, window.document);

        if (!idlUtils.implForWrapper(window._document)._pageShowingFlag) {
          idlUtils.implForWrapper(window._document)._pageShowingFlag = true;
          fireAnEvent("pageshow", window, PageTransitionEvent, { persisted: false }, window.document);
        }
      });
    }
  });
}
function Window ( options ) { EventTarget . setup ( this ) ; const rawPerformance = new RawPerformance ( ) ; const windowInitialized = rawPerformance . now ( ) ; const window = this ; mixin ( window , WindowEventHandlersImpl . prototype ) ; mixin ( window , GlobalEventHandlersImpl . prototype ) ; this . _initGlobalEvents ( ) ; ///// INTERFACES FROM THE DOM // TODO: consider a mode of some sort where these are not shared between all DOM instances // It'd be very memory-expensive in most cases, though. for ( const name in dom ) { Object . defineProperty ( window , name , { enumerable : false , configurable : true , writable : true , value : dom [ name ] } ) ; } ///// PRIVATE DATA PROPERTIES this . _resourceLoader = options . resourceLoader ; // vm initialization is deferred until script processing is activated this . _globalProxy = this ; Object . defineProperty ( idlUtils . implForWrapper ( this ) , idlUtils . wrapperSymbol , { get : ( ) => this . _globalProxy } ) ; let timers = Object . create ( null ) ; let animationFrameCallbacks = Object . create ( null ) ; // List options explicitly to be clear which are passed through this . _document = Document . create ( [ ] , { options : { parsingMode : options . parsingMode , contentType : options . contentType , encoding : options . encoding , cookieJar : options . cookieJar , url : options . url , lastModified : options . lastModified , referrer : options . referrer , concurrentNodeIterators : options . concurrentNodeIterators , parseOptions : options . parseOptions , defaultView : this . _globalProxy , global : this } } ) ; // https://html.spec.whatwg.org/#session-history this . _sessionHistory = new SessionHistory ( { document : idlUtils . implForWrapper ( this . _document ) , url : idlUtils . implForWrapper ( this . _document ) . _URL , stateObject : null } , this ) ; this . _virtualConsole = options . virtualConsole ; this . _runScripts = options . runScripts ; if ( this . _runScripts === "outside-only" || this . _runScripts === "dangerously" ) { contextifyWindow ( this ) ; } // Set up the window as if it's a top level window. // If it's not, then references will be corrected by frame/iframe code. this . _parent = this . _top = this . _globalProxy ; this . _frameElement = null ; // This implements window.frames.length, since window.frames returns a // self reference to the window object.  This value is incremented in the // HTMLFrameElement implementation. this . _length = 0 ; this . _pretendToBeVisual = options . pretendToBeVisual ; this . _storageQuota = options . storageQuota ; // Some properties (such as localStorage and sessionStorage) share data // between windows in the same origin. This object is intended // to contain such data. if ( options . commonForOrigin && options . commonForOrigin [ this . _document . origin ] ) { this . _commonForOrigin = options . commonForOrigin ; } else { this . _commonForOrigin = { [ this . _document . origin ] : { localStorageArea : new Map ( ) , sessionStorageArea : new Map ( ) , windowsInSameOrigin : [ this ] } } ; } this . _currentOriginData = this . _commonForOrigin [ this . _document . origin ] ; ///// WEB STORAGE this . _localStorage = Storage . create ( [ ] , { associatedWindow : this , storageArea : this . _currentOriginData . localStorageArea , type : "localStorage" , url : this . _document . documentURI , storageQuota : this . _storageQuota } ) ; this . _sessionStorage = Storage . create ( [ ] , { associatedWindow : this , storageArea : this . _currentOriginData . sessionStorageArea , type : "sessionStorage" , url : this . _document . documentURI , storageQuota : this . _storageQuota } ) ; ///// GETTERS const locationbar = BarProp . create ( ) ; const menubar = BarProp . create ( ) ; const personalbar = BarProp . create ( ) ; const scrollbars = BarProp . create ( ) ; const statusbar = BarProp . create ( ) ; const toolbar = BarProp . create ( ) ; const external = External . create ( ) ; const navigator = Navigator . create ( [ ] , { userAgent : this . _resourceLoader . _userAgent } ) ; const performance = Performance . create ( [ ] , { rawPerformance } ) ; const screen = Screen . create ( ) ; define ( this , { get length ( ) { return window . _length ; } , get window ( ) { return window . _globalProxy ; } , get frameElement ( ) { return idlUtils . wrapperForImpl ( window . _frameElement ) ; } , get frames ( ) { return window . _globalProxy ; } , get self ( ) { return window . _globalProxy ; } , get parent ( ) { return window . _parent ; } , get top ( ) { return window . _top ; } , get document ( ) { return window . _document ; } , get external ( ) { return external ; } , get location ( ) { return idlUtils . wrapperForImpl ( idlUtils . implForWrapper ( window . _document ) . _location ) ; } , get history ( ) { return idlUtils . wrapperForImpl ( idlUtils . implForWrapper ( window . _document ) . _history ) ; } , get navigator ( ) { return navigator ; } , get locationbar ( ) { return locationbar ; } , get menubar ( ) { return menubar ; } , get personalbar ( ) { return personalbar ; } , get scrollbars ( ) { return scrollbars ; } , get statusbar ( ) { return statusbar ; } , get toolbar ( ) { return toolbar ; } , get performance ( ) { return performance ; } , get screen ( ) { return screen ; } , get localStorage ( ) { if ( this . _document . origin === "null" ) { throw new DOMException ( "localStorage is not available for opaque origins" , "SecurityError" ) ; } return this . _localStorage ; } , get sessionStorage ( ) { if ( this . _document . origin === "null" ) { throw new DOMException ( "sessionStorage is not available for opaque origins" , "SecurityError" ) ; } return this . _sessionStorage ; } } ) ; namedPropertiesWindow . initializeWindow ( this , this . _globalProxy ) ; ///// METHODS for [ImplicitThis] hack // See https://lists.w3.org/Archives/Public/public-script-coord/2015JanMar/0109.html this . addEventListener = this . addEventListener . bind ( this ) ; this . removeEventListener = this . removeEventListener . bind ( this ) ; this . dispatchEvent = this . dispatchEvent . bind ( this ) ; ///// METHODS let latestTimerId = 0 ; let latestAnimationFrameCallbackId = 0 ; this . setTimeout = function ( fn , ms ) { const args = [ ] ; for ( let i = 2 ; i < arguments . length ; ++ i ) { args [ i - 2 ] = arguments [ i ] ; } return startTimer ( window , setTimeout , clearTimeout , ++ latestTimerId , fn , ms , timers , args ) ; } ; this . setInterval = function ( fn , ms ) { const args = [ ] ; for ( let i = 2 ; i < arguments . length ; ++ i ) { args [ i - 2 ] = arguments [ i ] ; } return startTimer ( window , setInterval , clearInterval , ++ latestTimerId , fn , ms , timers , args ) ; } ; this . clearInterval = stopTimer . bind ( this , timers ) ; this . clearTimeout = stopTimer . bind ( this , timers ) ; if ( this . _pretendToBeVisual ) { this . requestAnimationFrame = fn => { const timestamp = rawPerformance . now ( ) - windowInitialized ; const fps = 1000 / 60 ; return startTimer ( window , setTimeout , clearTimeout , ++ latestAnimationFrameCallbackId , fn , fps , animationFrameCallbacks , [ timestamp ] ) ; } ; this . cancelAnimationFrame = stopTimer . bind ( this , animationFrameCallbacks ) ; } this . __stopAllTimers = function ( ) { stopAllTimers ( timers ) ; stopAllTimers ( animationFrameCallbacks ) ; latestTimerId = 0 ; latestAnimationFrameCallbackId = 0 ; timers = Object . create ( null ) ; animationFrameCallbacks = Object . create ( null ) ; } ; function Option ( text , value , defaultSelected , selected ) { if ( text === undefined ) { text = "" ; } text = webIDLConversions . DOMString ( text ) ; if ( value !== undefined ) { value = webIDLConversions . DOMString ( value ) ; } defaultSelected = webIDLConversions . boolean ( defaultSelected ) ; selected = webIDLConversions . boolean ( selected ) ; const option = window . _document . createElement ( "option" ) ; const impl = idlUtils . implForWrapper ( option ) ; if ( text !== "" ) { impl . text = text ; } if ( value !== undefined ) { impl . setAttributeNS ( null , "value" , value ) ; } if ( defaultSelected ) { impl . setAttributeNS ( null , "selected" , "" ) ; } impl . _selectedness = selected ; return option ; } Object . defineProperty ( Option , "prototype" , { value : this . HTMLOptionElement . prototype , configurable : false , enumerable : false , writable : false } ) ; Object . defineProperty ( window , "Option" , { value : Option , configurable : true , enumerable : false , writable : true } ) ; function Image ( ) { const img = window . _document . createElement ( "img" ) ; const impl = idlUtils . implForWrapper ( img ) ; if ( arguments . length > 0 ) { impl . setAttributeNS ( null , "width" , String ( arguments [ 0 ] ) ) ; } if ( arguments . length > 1 ) { impl . setAttributeNS ( null , "height" , String ( arguments [ 1 ] ) ) ; } return img ; } Object . defineProperty ( Image , "prototype" , { value : this . HTMLImageElement . prototype , configurable : false , enumerable : false , writable : false } ) ; Object . defineProperty ( window , "Image" , { value : Image , configurable : true , enumerable : false , writable : true } ) ; function Audio ( src ) { const audio = window . _document . createElement ( "audio" ) ; const impl = idlUtils . implForWrapper ( audio ) ; impl . setAttributeNS ( null , "preload" , "auto" ) ; if ( src !== undefined ) { impl . setAttributeNS ( null , "src" , String ( src ) ) ; } return audio ; } Object . defineProperty ( Audio , "prototype" , { value : this . HTMLAudioElement . prototype , configurable : false , enumerable : false , writable : false } ) ; Object . defineProperty ( window , "Audio" , { value : Audio , configurable : true , enumerable : false , writable : true } ) ; this . postMessage = postMessage ; this . atob = function ( str ) { const result = atob ( str ) ; if ( result === null ) { throw new DOMException ( "The string to be decoded contains invalid characters." , "InvalidCharacterError" ) ; } return result ; } ; this . btoa = function ( str ) { const result = btoa ( str ) ; if ( result === null ) { throw new DOMException ( "The string to be encoded contains invalid characters." , "InvalidCharacterError" ) ; } return result ; } ; this . FileReader = createFileReader ( { window : this } ) . interface ; this . WebSocket = createWebSocket ( { window : this } ) . interface ; const AbortSignalWrapper = createAbortSignal ( { window : this } ) ; this . AbortSignal = AbortSignalWrapper . interface ; this . AbortController = createAbortController ( { AbortSignal : AbortSignalWrapper } ) . interface ; this . XMLHttpRequest = createXMLHttpRequest ( this ) ; // TODO: necessary for Blob and FileReader due to different-globals weirdness; investigate how to avoid this. this . ArrayBuffer = ArrayBuffer ; this . Int8Array = Int8Array ; this . Uint8Array = Uint8Array ; this . Uint8ClampedArray = Uint8ClampedArray ; this . Int16Array = Int16Array ; this . Uint16Array = Uint16Array ; this . Int32Array = Int32Array ; this . Uint32Array = Uint32Array ; this . Float32Array = Float32Array ; this . Float64Array = Float64Array ; this . stop = function ( ) { const manager = idlUtils . implForWrapper ( this . _document ) . _requestManager ; if ( manager ) { manager . close ( ) ; } } ; this . close = function ( ) { // Recursively close child frame windows, then ourselves. const currentWindow = this ; ( function windowCleaner ( windowToClean ) { for ( let i = 0 ; i < windowToClean . length ; i ++ ) { windowCleaner ( windowToClean [ i ] ) ; } // We"re already in our own window.close(). if ( windowToClean !== currentWindow ) { windowToClean . close ( ) ; } } ( this ) ) ; // Clear out all listeners. Any in-flight or upcoming events should not get delivered. idlUtils . implForWrapper ( this ) . _eventListeners = Object . create ( null ) ; if ( this . _document ) { if ( this . _document . body ) { this . _document . body . innerHTML = "" ; } if ( this . _document . close ) { // It's especially important to clear out the listeners here because document.close() causes a "load" event to // fire. idlUtils . implForWrapper ( this . _document ) . _eventListeners = Object . create ( null ) ; this . _document . close ( ) ; } const doc = idlUtils . implForWrapper ( this . _document ) ; if ( doc . _requestManager ) { doc . _requestManager . close ( ) ; } delete this . _document ; } this . __stopAllTimers ( ) ; WebSocketImpl . cleanUpWindow ( this ) ; } ; this . getComputedStyle = function ( elt ) { elt = Element . convert ( elt ) ; const declaration = new CSSStyleDeclaration ( ) ; const { forEach , indexOf } = Array . prototype ; const { style } = elt ; function setPropertiesFromRule ( rule ) { if ( ! rule . selectorText ) { return ; } const cssSelectorSplitRe = / ((?:[^,"']|"[^"]*"|'[^']*')+) / ; const selectors = rule . selectorText . split ( cssSelectorSplitRe ) ; let matched = false ; for ( const selectorText of selectors ) { if ( selectorText !== "" && selectorText !== "," && ! matched && matchesDontThrow ( elt , selectorText ) ) { matched = true ; forEach . call ( rule . style , property => { declaration . setProperty ( property , rule . style . getPropertyValue ( property ) , rule . style . getPropertyPriority ( property ) ) ; } ) ; } } } function readStylesFromStyleSheet ( sheet ) { forEach . call ( sheet . cssRules , rule => { if ( rule . media ) { if ( indexOf . call ( rule . media , "screen" ) !== - 1 ) { forEach . call ( rule . cssRules , setPropertiesFromRule ) ; } } else { setPropertiesFromRule ( rule ) ; } } ) ; } if ( ! parsedDefaultStyleSheet ) { parsedDefaultStyleSheet = cssom . parse ( defaultStyleSheet ) ; } readStylesFromStyleSheet ( parsedDefaultStyleSheet ) ; forEach . call ( elt . ownerDocument . styleSheets , readStylesFromStyleSheet ) ; forEach . call ( style , property => { declaration . setProperty ( property , style . getPropertyValue ( property ) , style . getPropertyPriority ( property ) ) ; } ) ; return declaration ; } ; // The captureEvents() and releaseEvents() methods must do nothing this . captureEvents = function ( ) { } ; this . releaseEvents = function ( ) { } ; ///// PUBLIC DATA PROPERTIES (TODO: should be getters) function wrapConsoleMethod ( method ) { return ( ... args ) => { window . _virtualConsole . emit ( method , ... args ) ; } ; } this . console = { assert : wrapConsoleMethod ( "assert" ) , clear : wrapConsoleMethod ( "clear" ) , count : wrapConsoleMethod ( "count" ) , countReset : wrapConsoleMethod ( "countReset" ) , debug : wrapConsoleMethod ( "debug" ) , dir : wrapConsoleMethod ( "dir" ) , dirxml : wrapConsoleMethod ( "dirxml" ) , error : wrapConsoleMethod ( "error" ) , group : wrapConsoleMethod ( "group" ) , groupCollapsed : wrapConsoleMethod ( "groupCollapsed" ) , groupEnd : wrapConsoleMethod ( "groupEnd" ) , info : wrapConsoleMethod ( "info" ) , log : wrapConsoleMethod ( "log" ) , table : wrapConsoleMethod ( "table" ) , time : wrapConsoleMethod ( "time" ) , timeEnd : wrapConsoleMethod ( "timeEnd" ) , trace : wrapConsoleMethod ( "trace" ) , warn : wrapConsoleMethod ( "warn" ) } ; function notImplementedMethod ( name ) { return function ( ) { notImplemented ( name , window ) ; } ; } define ( this , { name : "" , status : "" , devicePixelRatio : 1 , innerWidth : 1024 , innerHeight : 768 , outerWidth : 1024 , outerHeight : 768 , pageXOffset : 0 , pageYOffset : 0 , screenX : 0 , screenLeft : 0 , screenY : 0 , screenTop : 0 , scrollX : 0 , scrollY : 0 , alert : notImplementedMethod ( "window.alert" ) , blur : notImplementedMethod ( "window.blur" ) , confirm : notImplementedMethod ( "window.confirm" ) , focus : notImplementedMethod ( "window.focus" ) , moveBy : notImplementedMethod ( "window.moveBy" ) , moveTo : notImplementedMethod ( "window.moveTo" ) , open : notImplementedMethod ( "window.open" ) , print : notImplementedMethod ( "window.print" ) , prompt : notImplementedMethod ( "window.prompt" ) , resizeBy : notImplementedMethod ( "window.resizeBy" ) , resizeTo : notImplementedMethod ( "window.resizeTo" ) , scroll : notImplementedMethod ( "window.scroll" ) , scrollBy : notImplementedMethod ( "window.scrollBy" ) , scrollTo : notImplementedMethod ( "window.scrollTo" ) } ) ; ///// INITIALIZATION process . nextTick ( ( ) => { if ( ! window . document ) { return ; // window might've been closed already } if ( window . document . readyState === "complete" ) { fireAnEvent ( "load" , window , undefined , { } , window . document ) ; } else { window . document . addEventListener ( "load" , ( ) => { fireAnEvent ( "load" , window , undefined , { } , window . document ) ; if ( ! idlUtils . implForWrapper ( window . _document ) . _pageShowingFlag ) { idlUtils . implForWrapper ( window . _document ) . _pageShowingFlag = true ; fireAnEvent ( "pageshow" , window , PageTransitionEvent , { persisted : false } , window . document ) ; } } ) ; } } ) ; }
NOTE: per https://heycam.github.io/webidl/#Global, all properties on the Window object must be own-properties. That is why we assign everything inside of the constructor, instead of using a shared prototype. You can verify this in e.g. Firefox or Internet Explorer, which do a good job with Web IDL compliance.
NOTE : per https : // heycam . github . io / webidl / #Global all properties on the Window object must be own - properties . That is why we assign everything inside of the constructor instead of using a shared prototype . You can verify this in e . g . Firefox or Internet Explorer which do a good job with Web IDL compliance .