"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var snapshotterInjected_exports = {};
__export(snapshotterInjected_exports, {
  frameSnapshotStreamer: () => frameSnapshotStreamer
});
module.exports = __toCommonJS(snapshotterInjected_exports);
function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
  if (window[snapshotStreamer])
    return;
  const kShadowAttribute = "__playwright_shadow_root_";
  const kValueAttribute = "__playwright_value_";
  const kCheckedAttribute = "__playwright_checked_";
  const kSelectedAttribute = "__playwright_selected_";
  const kScrollTopAttribute = "__playwright_scroll_top_";
  const kScrollLeftAttribute = "__playwright_scroll_left_";
  const kStyleSheetAttribute = "__playwright_style_sheet_";
  const kTargetAttribute = "__playwright_target__";
  const kCustomElementsAttribute = "__playwright_custom_elements__";
  const kCurrentSrcAttribute = "__playwright_current_src__";
  const kBoundingRectAttribute = "__playwright_bounding_rect__";
  const kPopoverOpenAttribute = "__playwright_popover_open_";
  const kDialogOpenAttribute = "__playwright_dialog_open_";
  const kSnapshotFrameId = Symbol("__playwright_snapshot_frameid_");
  const kCachedData = Symbol("__playwright_snapshot_cache_");
  const kEndOfList = Symbol("__playwright_end_of_list_");
  function resetCachedData(obj) {
    delete obj[kCachedData];
  }
  function ensureCachedData(obj) {
    if (!obj[kCachedData])
      obj[kCachedData] = {};
    return obj[kCachedData];
  }
  function removeHash(url) {
    try {
      const u = new URL(url);
      u.hash = "";
      return u.toString();
    } catch (e) {
      return url;
    }
  }
  class Streamer {
    constructor() {
      this._lastSnapshotNumber = 0;
      this._staleStyleSheets = /* @__PURE__ */ new Set();
      this._readingStyleSheet = false;
      const invalidateCSSGroupingRule = (rule) => {
        if (rule.parentStyleSheet)
          this._invalidateStyleSheet(rule.parentStyleSheet);
      };
      this._interceptNativeMethod(window.CSSStyleSheet.prototype, "insertRule", (sheet) => this._invalidateStyleSheet(sheet));
      this._interceptNativeMethod(window.CSSStyleSheet.prototype, "deleteRule", (sheet) => this._invalidateStyleSheet(sheet));
      this._interceptNativeMethod(window.CSSStyleSheet.prototype, "addRule", (sheet) => this._invalidateStyleSheet(sheet));
      this._interceptNativeMethod(window.CSSStyleSheet.prototype, "removeRule", (sheet) => this._invalidateStyleSheet(sheet));
      this._interceptNativeGetter(window.CSSStyleSheet.prototype, "rules", (sheet) => this._invalidateStyleSheet(sheet));
      this._interceptNativeGetter(window.CSSStyleSheet.prototype, "cssRules", (sheet) => this._invalidateStyleSheet(sheet));
      this._interceptNativeMethod(window.CSSStyleSheet.prototype, "replaceSync", (sheet) => this._invalidateStyleSheet(sheet));
      this._interceptNativeMethod(window.CSSGroupingRule.prototype, "insertRule", invalidateCSSGroupingRule);
      this._interceptNativeMethod(window.CSSGroupingRule.prototype, "deleteRule", invalidateCSSGroupingRule);
      this._interceptNativeGetter(window.CSSGroupingRule.prototype, "cssRules", invalidateCSSGroupingRule);
      this._interceptNativeAsyncMethod(window.CSSStyleSheet.prototype, "replace", (sheet) => this._invalidateStyleSheet(sheet));
      this._fakeBase = document.createElement("base");
      this._observer = new MutationObserver((list) => this._handleMutations(list));
      const observerConfig = { attributes: true, subtree: true };
      this._observer.observe(document, observerConfig);
      this._refreshListenersWhenNeeded();
    }
    _refreshListenersWhenNeeded() {
      this._refreshListeners();
      const customEventName = "__playwright_snapshotter_global_listeners_check__";
      let seenEvent = false;
      const handleCustomEvent = () => seenEvent = true;
      window.addEventListener(customEventName, handleCustomEvent);
      const observer = new MutationObserver((entries) => {
        const newDocumentElement = entries.some((entry) => Array.from(entry.addedNodes).includes(document.documentElement));
        if (newDocumentElement) {
          seenEvent = false;
          window.dispatchEvent(new CustomEvent(customEventName));
          if (!seenEvent) {
            window.addEventListener(customEventName, handleCustomEvent);
            this._refreshListeners();
          }
        }
      });
      observer.observe(document, { childList: true });
    }
    _refreshListeners() {
      document.addEventListener("__playwright_mark_target__", (event) => {
        if (!event.detail)
          return;
        const callId = event.detail;
        event.composedPath()[0].__playwright_target__ = callId;
      });
      document.addEventListener("__playwright_unmark_target__", (event) => {
        if (!event.detail)
          return;
        const callId = event.detail;
        if (event.composedPath()[0].__playwright_target__ === callId)
          delete event.composedPath()[0].__playwright_target__;
      });
    }
    _interceptNativeMethod(obj, method, cb) {
      const native = obj[method];
      if (!native)
        return;
      obj[method] = function(...args) {
        const result = native.call(this, ...args);
        cb(this, result);
        return result;
      };
    }
    _interceptNativeAsyncMethod(obj, method, cb) {
      const native = obj[method];
      if (!native)
        return;
      obj[method] = async function(...args) {
        const result = await native.call(this, ...args);
        cb(this, result);
        return result;
      };
    }
    _interceptNativeGetter(obj, prop, cb) {
      const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
      Object.defineProperty(obj, prop, {
        ...descriptor,
        get: function() {
          const result = descriptor.get.call(this);
          cb(this, result);
          return result;
        }
      });
    }
    _handleMutations(list) {
      for (const mutation of list)
        ensureCachedData(mutation.target).attributesCached = void 0;
    }
    _invalidateStyleSheet(sheet) {
      if (this._readingStyleSheet)
        return;
      this._staleStyleSheets.add(sheet);
    }
    _updateStyleElementStyleSheetTextIfNeeded(sheet, forceText) {
      const data = ensureCachedData(sheet);
      if (this._staleStyleSheets.has(sheet) || forceText && data.cssText === void 0) {
        this._staleStyleSheets.delete(sheet);
        try {
          data.cssText = this._getSheetText(sheet);
        } catch (e) {
          data.cssText = "";
        }
      }
      return data.cssText;
    }
    // Returns either content, ref, or no override.
    _updateLinkStyleSheetTextIfNeeded(sheet, snapshotNumber) {
      const data = ensureCachedData(sheet);
      if (this._staleStyleSheets.has(sheet)) {
        this._staleStyleSheets.delete(sheet);
        try {
          data.cssText = this._getSheetText(sheet);
          data.cssRef = snapshotNumber;
          return data.cssText;
        } catch (e) {
        }
      }
      return data.cssRef === void 0 ? void 0 : snapshotNumber - data.cssRef;
    }
    markIframe(iframeElement, frameId) {
      iframeElement[kSnapshotFrameId] = frameId;
    }
    reset() {
      this._staleStyleSheets.clear();
      const visitNode = (node) => {
        resetCachedData(node);
        if (node.nodeType === Node.ELEMENT_NODE) {
          const element = node;
          if (element.shadowRoot)
            visitNode(element.shadowRoot);
        }
        for (let child = node.firstChild; child; child = child.nextSibling)
          visitNode(child);
      };
      visitNode(document.documentElement);
      visitNode(this._fakeBase);
    }
    __sanitizeMetaAttribute(name, value, httpEquiv) {
      if (name === "charset")
        return "utf-8";
      if (httpEquiv.toLowerCase() !== "content-type" || name !== "content")
        return value;
      const [type, ...params] = value.split(";");
      if (type !== "text/html" || params.length <= 0)
        return value;
      const charsetParamIdx = params.findIndex((param) => param.trim().startsWith("charset="));
      if (charsetParamIdx > -1)
        params[charsetParamIdx] = "charset=utf-8";
      return `${type}; ${params.join("; ")}`;
    }
    _sanitizeUrl(url) {
      if (url.startsWith("javascript:") || url.startsWith("vbscript:"))
        return "";
      return url;
    }
    _sanitizeSrcSet(srcset) {
      return srcset.split(",").map((src) => {
        src = src.trim();
        const spaceIndex = src.lastIndexOf(" ");
        if (spaceIndex === -1)
          return this._sanitizeUrl(src);
        return this._sanitizeUrl(src.substring(0, spaceIndex).trim()) + src.substring(spaceIndex);
      }).join(", ");
    }
    _resolveUrl(base, url) {
      if (url === "")
        return "";
      try {
        return new URL(url, base).href;
      } catch (e) {
        return url;
      }
    }
    _getSheetBase(sheet) {
      let rootSheet = sheet;
      while (rootSheet.parentStyleSheet)
        rootSheet = rootSheet.parentStyleSheet;
      if (rootSheet.ownerNode)
        return rootSheet.ownerNode.baseURI;
      return document.baseURI;
    }
    _getSheetText(sheet) {
      this._readingStyleSheet = true;
      try {
        const rules = [];
        for (const rule of sheet.cssRules)
          rules.push(rule.cssText);
        return rules.join("\n");
      } finally {
        this._readingStyleSheet = false;
      }
    }
    captureSnapshot() {
      const timestamp = performance.now();
      const snapshotNumber = ++this._lastSnapshotNumber;
      let nodeCounter = 0;
      let shadowDomNesting = 0;
      let headNesting = 0;
      this._handleMutations(this._observer.takeRecords());
      const definedCustomElements = /* @__PURE__ */ new Set();
      const visitNode = (node) => {
        const nodeType = node.nodeType;
        const nodeName = nodeType === Node.DOCUMENT_FRAGMENT_NODE ? "template" : node.nodeName;
        if (nodeType !== Node.ELEMENT_NODE && nodeType !== Node.DOCUMENT_FRAGMENT_NODE && nodeType !== Node.TEXT_NODE)
          return;
        if (nodeName === "SCRIPT")
          return;
        if (nodeName === "LINK" && nodeType === Node.ELEMENT_NODE) {
          const rel = node.getAttribute("rel")?.toLowerCase();
          if (rel === "preload" || rel === "prefetch")
            return;
        }
        if (removeNoScript && nodeName === "NOSCRIPT")
          return;
        if (nodeName === "META" && node.httpEquiv.toLowerCase() === "content-security-policy")
          return;
        if ((nodeName === "IFRAME" || nodeName === "FRAME") && headNesting)
          return;
        const data = ensureCachedData(node);
        const values = [];
        let equals = !!data.cached;
        let extraNodes = 0;
        const expectValue = (value) => {
          equals = equals && data.cached[values.length] === value;
          values.push(value);
        };
        const checkAndReturn = (n) => {
          data.attributesCached = true;
          if (equals)
            return { equals: true, n: [[snapshotNumber - data.ref[0], data.ref[1]]] };
          nodeCounter += extraNodes;
          data.ref = [snapshotNumber, nodeCounter++];
          data.cached = values;
          return { equals: false, n };
        };
        if (nodeType === Node.TEXT_NODE) {
          const value = node.nodeValue || "";
          expectValue(value);
          return checkAndReturn(value);
        }
        if (nodeName === "STYLE") {
          const sheet = node.sheet;
          let cssText;
          if (sheet)
            cssText = this._updateStyleElementStyleSheetTextIfNeeded(sheet);
          cssText = cssText || node.textContent || "";
          expectValue(cssText);
          extraNodes++;
          return checkAndReturn([nodeName, {}, cssText]);
        }
        const attrs = {};
        const result2 = [nodeName, attrs];
        const visitChild = (child) => {
          const snapshot = visitNode(child);
          if (snapshot) {
            result2.push(snapshot.n);
            expectValue(child);
            equals = equals && snapshot.equals;
          }
        };
        const visitChildStyleSheet = (child) => {
          const snapshot = visitStyleSheet(child);
          if (snapshot) {
            result2.push(snapshot.n);
            expectValue(child);
            equals = equals && snapshot.equals;
          }
        };
        if (nodeType === Node.DOCUMENT_FRAGMENT_NODE)
          attrs[kShadowAttribute] = "open";
        if (nodeType === Node.ELEMENT_NODE) {
          const element = node;
          if (element.localName.includes("-") && window.customElements?.get(element.localName))
            definedCustomElements.add(element.localName);
          if (nodeName === "INPUT" || nodeName === "TEXTAREA") {
            const value = element.value;
            expectValue(kValueAttribute);
            expectValue(value);
            attrs[kValueAttribute] = value;
          }
          if (nodeName === "INPUT" && ["checkbox", "radio"].includes(element.type)) {
            const value = element.checked ? "true" : "false";
            expectValue(kCheckedAttribute);
            expectValue(value);
            attrs[kCheckedAttribute] = value;
          }
          if (nodeName === "OPTION") {
            const value = element.selected ? "true" : "false";
            expectValue(kSelectedAttribute);
            expectValue(value);
            attrs[kSelectedAttribute] = value;
          }
          if (nodeName === "CANVAS" || nodeName === "IFRAME" || nodeName === "FRAME") {
            const boundingRect = element.getBoundingClientRect();
            const value = JSON.stringify({
              left: boundingRect.left,
              top: boundingRect.top,
              right: boundingRect.right,
              bottom: boundingRect.bottom
            });
            expectValue(kBoundingRectAttribute);
            expectValue(value);
            attrs[kBoundingRectAttribute] = value;
          }
          if (element.popover && element.matches && element.matches(":popover-open")) {
            const value = "true";
            expectValue(kPopoverOpenAttribute);
            expectValue(value);
            attrs[kPopoverOpenAttribute] = value;
          }
          if (nodeName === "DIALOG" && element.open) {
            const value = element.matches(":modal") ? "modal" : "true";
            expectValue(kDialogOpenAttribute);
            expectValue(value);
            attrs[kDialogOpenAttribute] = value;
          }
          if (element.scrollTop) {
            expectValue(kScrollTopAttribute);
            expectValue(element.scrollTop);
            attrs[kScrollTopAttribute] = "" + element.scrollTop;
          }
          if (element.scrollLeft) {
            expectValue(kScrollLeftAttribute);
            expectValue(element.scrollLeft);
            attrs[kScrollLeftAttribute] = "" + element.scrollLeft;
          }
          if (element.shadowRoot) {
            ++shadowDomNesting;
            visitChild(element.shadowRoot);
            --shadowDomNesting;
          }
          if ("__playwright_target__" in element) {
            expectValue(kTargetAttribute);
            expectValue(element["__playwright_target__"]);
            attrs[kTargetAttribute] = element["__playwright_target__"];
          }
        }
        if (nodeName === "HEAD") {
          ++headNesting;
          this._fakeBase.setAttribute("href", document.baseURI);
          visitChild(this._fakeBase);
        }
        for (let child = node.firstChild; child; child = child.nextSibling)
          visitChild(child);
        if (nodeName === "HEAD")
          --headNesting;
        expectValue(kEndOfList);
        let documentOrShadowRoot = null;
        if (node.ownerDocument.documentElement === node)
          documentOrShadowRoot = node.ownerDocument;
        else if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE)
          documentOrShadowRoot = node;
        if (documentOrShadowRoot) {
          for (const sheet of documentOrShadowRoot.adoptedStyleSheets || [])
            visitChildStyleSheet(sheet);
          expectValue(kEndOfList);
        }
        if (nodeName === "IFRAME" || nodeName === "FRAME") {
          const element = node;
          const frameId = element[kSnapshotFrameId];
          const name = "src";
          const value = frameId ? `/snapshot/${frameId}` : "";
          expectValue(name);
          expectValue(value);
          attrs[name] = value;
        }
        if (nodeName === "BODY" && definedCustomElements.size) {
          const value = [...definedCustomElements].join(",");
          expectValue(kCustomElementsAttribute);
          expectValue(value);
          attrs[kCustomElementsAttribute] = value;
        }
        if (nodeName === "IMG" || nodeName === "PICTURE") {
          const value = nodeName === "PICTURE" ? "" : this._sanitizeUrl(node.currentSrc);
          expectValue(kCurrentSrcAttribute);
          expectValue(value);
          attrs[kCurrentSrcAttribute] = value;
        }
        if (equals && data.attributesCached && !shadowDomNesting)
          return checkAndReturn(result2);
        if (nodeType === Node.ELEMENT_NODE) {
          const element = node;
          for (let i = 0; i < element.attributes.length; i++) {
            const name = element.attributes[i].name;
            if (nodeName === "LINK" && name === "integrity")
              continue;
            if (nodeName === "IFRAME" && (name === "src" || name === "srcdoc" || name === "sandbox"))
              continue;
            if (nodeName === "FRAME" && name === "src")
              continue;
            if (nodeName === "DIALOG" && name === "open")
              continue;
            let value = element.attributes[i].value;
            if (nodeName === "META")
              value = this.__sanitizeMetaAttribute(name, value, node.httpEquiv);
            else if (name === "src" && nodeName === "IMG")
              value = this._sanitizeUrl(value);
            else if (name === "srcset" && nodeName === "IMG")
              value = this._sanitizeSrcSet(value);
            else if (name === "srcset" && nodeName === "SOURCE")
              value = this._sanitizeSrcSet(value);
            else if (name === "href" && nodeName === "LINK")
              value = this._sanitizeUrl(value);
            else if (name.startsWith("on"))
              value = "";
            expectValue(name);
            expectValue(value);
            attrs[name] = value;
          }
          expectValue(kEndOfList);
        }
        if (result2.length === 2 && !Object.keys(attrs).length)
          result2.pop();
        return checkAndReturn(result2);
      };
      const visitStyleSheet = (sheet) => {
        const data = ensureCachedData(sheet);
        const oldCSSText = data.cssText;
        const cssText = this._updateStyleElementStyleSheetTextIfNeeded(
          sheet,
          true
          /* forceText */
        );
        if (cssText === oldCSSText)
          return { equals: true, n: [[snapshotNumber - data.ref[0], data.ref[1]]] };
        data.ref = [snapshotNumber, nodeCounter++];
        return {
          equals: false,
          n: ["template", {
            [kStyleSheetAttribute]: cssText
          }]
        };
      };
      let html;
      if (document.documentElement) {
        const { n } = visitNode(document.documentElement);
        html = n;
      } else {
        html = ["html"];
      }
      const result = {
        html,
        doctype: document.doctype ? document.doctype.name : void 0,
        resourceOverrides: [],
        viewport: {
          width: window.innerWidth,
          height: window.innerHeight
        },
        url: location.href,
        wallTime: Date.now(),
        collectionTime: 0
      };
      for (const sheet of this._staleStyleSheets) {
        if (sheet.href === null)
          continue;
        const content = this._updateLinkStyleSheetTextIfNeeded(sheet, snapshotNumber);
        if (content === void 0) {
          continue;
        }
        const base = this._getSheetBase(sheet);
        const url = removeHash(this._resolveUrl(base, sheet.href));
        result.resourceOverrides.push({ url, content, contentType: "text/css" });
      }
      result.collectionTime = performance.now() - timestamp;
      return result;
    }
  }
  window[snapshotStreamer] = new Streamer();
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  frameSnapshotStreamer
});
