"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; 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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // packages/isomorphic/ariaSnapshot.ts function ariaNodesEqual(a, b) { if (a.role !== b.role || a.name !== b.name) return false; if (!ariaPropsEqual(a, b) || hasPointerCursor(a) !== hasPointerCursor(b)) return false; const aKeys = Object.keys(a.props); const bKeys = Object.keys(b.props); return aKeys.length === bKeys.length && aKeys.every((k) => a.props[k] === b.props[k]); } function hasPointerCursor(ariaNode) { return ariaNode.box.cursor === "pointer"; } function ariaPropsEqual(a, b) { return a.active === b.active && a.checked === b.checked && a.disabled === b.disabled && a.expanded === b.expanded && a.invalid === b.invalid && a.selected === b.selected && a.level === b.level && a.pressed === b.pressed; } function parseAriaSnapshotUnsafe(yaml3, text2, options = {}) { const result2 = parseAriaSnapshot(yaml3, text2, options); if (result2.errors.length) throw new Error(result2.errors[0].message); return result2.fragment; } function parseAriaSnapshot(yaml3, text2, options = {}) { const lineCounter = new yaml3.LineCounter(); const parseOptions = { keepSourceTokens: true, lineCounter, ...options }; const yamlDoc = yaml3.parseDocument(text2, parseOptions); const errors = []; const convertRange = (range) => { return [lineCounter.linePos(range[0]), lineCounter.linePos(range[1])]; }; const addError = (error) => { errors.push({ message: error.message, range: [lineCounter.linePos(error.pos[0]), lineCounter.linePos(error.pos[1])] }); }; const convertSeq = (container, seq) => { for (const item of seq.items) { const itemIsString = item instanceof yaml3.Scalar && typeof item.value === "string"; if (itemIsString) { const childNode = KeyParser.parse(item, parseOptions, errors); if (childNode) { container.children = container.children || []; container.children.push(childNode); } continue; } const itemIsMap = item instanceof yaml3.YAMLMap; if (itemIsMap) { convertMap(container, item); continue; } errors.push({ message: "Sequence items should be strings or maps", range: convertRange(item.range || seq.range) }); } }; const convertMap = (container, map) => { for (const entry of map.items) { container.children = container.children || []; const keyIsString = entry.key instanceof yaml3.Scalar && typeof entry.key.value === "string"; if (!keyIsString) { errors.push({ message: "Only string keys are supported", range: convertRange(entry.key.range || map.range) }); continue; } const key = entry.key; const value2 = entry.value; if (key.value === "text") { const valueIsString = value2 instanceof yaml3.Scalar && typeof value2.value === "string"; if (!valueIsString) { errors.push({ message: "Text value should be a string", range: convertRange(entry.value.range || map.range) }); continue; } container.children.push({ kind: "text", text: textValue(value2.value) }); continue; } if (key.value === "/children") { const valueIsString = value2 instanceof yaml3.Scalar && typeof value2.value === "string"; if (!valueIsString || value2.value !== "contain" && value2.value !== "equal" && value2.value !== "deep-equal") { errors.push({ message: 'Strict value should be "contain", "equal" or "deep-equal"', range: convertRange(entry.value.range || map.range) }); continue; } container.containerMode = value2.value; continue; } if (key.value.startsWith("/")) { const valueIsString = value2 instanceof yaml3.Scalar && typeof value2.value === "string"; if (!valueIsString) { errors.push({ message: "Property value should be a string", range: convertRange(entry.value.range || map.range) }); continue; } container.props = container.props ?? {}; container.props[key.value.slice(1)] = textValue(value2.value); continue; } const childNode = KeyParser.parse(key, parseOptions, errors); if (!childNode) continue; const valueIsScalar = value2 instanceof yaml3.Scalar; if (valueIsScalar) { const type3 = typeof value2.value; if (type3 !== "string" && type3 !== "number" && type3 !== "boolean") { errors.push({ message: "Node value should be a string or a sequence", range: convertRange(entry.value.range || map.range) }); continue; } container.children.push({ ...childNode, children: [{ kind: "text", text: textValue(String(value2.value)) }] }); continue; } const valueIsSequence = value2 instanceof yaml3.YAMLSeq; if (valueIsSequence) { container.children.push(childNode); convertSeq(childNode, value2); continue; } errors.push({ message: "Map values should be strings or sequences", range: convertRange(entry.value.range || map.range) }); } }; const fragment = { kind: "role", role: "fragment" }; yamlDoc.errors.forEach(addError); if (errors.length) return { errors, fragment }; if (!(yamlDoc.contents instanceof yaml3.YAMLSeq)) { errors.push({ message: 'Aria snapshot must be a YAML sequence, elements starting with " -"', range: yamlDoc.contents ? convertRange(yamlDoc.contents.range) : [{ line: 0, col: 0 }, { line: 0, col: 0 }] }); } if (errors.length) return { errors, fragment }; convertSeq(fragment, yamlDoc.contents); if (errors.length) return { errors, fragment: emptyFragment }; if (fragment.children?.length === 1 && (!fragment.containerMode || fragment.containerMode === "contain")) return { fragment: fragment.children[0], errors: [] }; return { fragment, errors: [] }; } function normalizeWhitespace(text2) { return text2.replace(/[\u200b\u00ad]/g, "").replace(/[\r\n\s\t]+/g, " ").trim(); } function textValue(value2) { return { raw: value2, normalized: normalizeWhitespace(value2) }; } function findNewNode(from, to) { function fillMap(root, map, position) { let size = 1; let childPosition = position + size; for (const child of root.children || []) { if (typeof child === "string") { size++; childPosition++; } else { size += fillMap(child, map, childPosition); childPosition += size; } } if (!["none", "presentation", "fragment", "iframe", "generic"].includes(root.role) && root.name) { let byRole = map.get(root.role); if (!byRole) { byRole = /* @__PURE__ */ new Map(); map.set(root.role, byRole); } const existing = byRole.get(root.name); const sizeAndPosition = size * 100 - position; if (!existing || existing.sizeAndPosition < sizeAndPosition) byRole.set(root.name, { node: root, sizeAndPosition }); } return size; } const fromMap = /* @__PURE__ */ new Map(); if (from) fillMap(from, fromMap, 0); const toMap = /* @__PURE__ */ new Map(); fillMap(to, toMap, 0); const result2 = []; for (const [role, byRole] of toMap) { for (const [name, byName] of byRole) { const inFrom = fromMap.get(role)?.get(name); if (!inFrom) result2.push(byName); } } result2.sort((a, b) => b.sizeAndPosition - a.sizeAndPosition); return result2[0]?.node; } var emptyFragment, KeyParser, ParserError; var init_ariaSnapshot = __esm({ "packages/isomorphic/ariaSnapshot.ts"() { "use strict"; emptyFragment = { kind: "role", role: "fragment" }; KeyParser = class _KeyParser { static parse(text2, options, errors) { try { return new _KeyParser(text2.value)._parse(); } catch (e) { if (e instanceof ParserError) { const message = options.prettyErrors === false ? e.message : e.message + ":\n\n" + text2.value + "\n" + " ".repeat(e.pos) + "^\n"; errors.push({ message, range: [options.lineCounter.linePos(text2.range[0]), options.lineCounter.linePos(text2.range[0] + e.pos)] }); return null; } throw e; } } constructor(input) { this._input = input; this._pos = 0; this._length = input.length; } _peek() { return this._input[this._pos] || ""; } _next() { if (this._pos < this._length) return this._input[this._pos++]; return null; } _eof() { return this._pos >= this._length; } _isWhitespace() { return !this._eof() && /\s/.test(this._peek()); } _skipWhitespace() { while (this._isWhitespace()) this._pos++; } _readIdentifier(type3) { if (this._eof()) this._throwError(`Unexpected end of input when expecting ${type3}`); const start3 = this._pos; while (!this._eof() && /[a-zA-Z]/.test(this._peek())) this._pos++; return this._input.slice(start3, this._pos); } _readString() { let result2 = ""; let escaped2 = false; while (!this._eof()) { const ch = this._next(); if (escaped2) { result2 += ch; escaped2 = false; } else if (ch === "\\") { escaped2 = true; } else if (ch === '"') { return result2; } else { result2 += ch; } } this._throwError("Unterminated string"); } _throwError(message, offset = 0) { throw new ParserError(message, offset || this._pos); } _readRegex() { let result2 = ""; let escaped2 = false; let insideClass = false; while (!this._eof()) { const ch = this._next(); if (escaped2) { result2 += ch; escaped2 = false; } else if (ch === "\\") { escaped2 = true; result2 += ch; } else if (ch === "/" && !insideClass) { return { pattern: result2 }; } else if (ch === "[") { insideClass = true; result2 += ch; } else if (ch === "]" && insideClass) { result2 += ch; insideClass = false; } else { result2 += ch; } } this._throwError("Unterminated regex"); } _readStringOrRegex() { const ch = this._peek(); if (ch === '"') { this._next(); return normalizeWhitespace(this._readString()); } if (ch === "/") { this._next(); return this._readRegex(); } return null; } _readAttributes(result2) { let errorPos = this._pos; while (true) { this._skipWhitespace(); if (this._peek() === "[") { this._next(); this._skipWhitespace(); errorPos = this._pos; const flagName = this._readIdentifier("attribute"); this._skipWhitespace(); let flagValue = ""; if (this._peek() === "=") { this._next(); this._skipWhitespace(); errorPos = this._pos; while (this._peek() !== "]" && !this._isWhitespace() && !this._eof()) flagValue += this._next(); } this._skipWhitespace(); if (this._peek() !== "]") this._throwError("Expected ]"); this._next(); this._applyAttribute(result2, flagName, flagValue || "true", errorPos); } else { break; } } } _parse() { this._skipWhitespace(); const role = this._readIdentifier("role"); this._skipWhitespace(); const name = this._readStringOrRegex() || ""; const result2 = { kind: "role", role, name }; this._readAttributes(result2); this._skipWhitespace(); if (!this._eof()) this._throwError("Unexpected input"); return result2; } _applyAttribute(node, key, value2, errorPos) { if (key === "checked") { this._assert(value2 === "true" || value2 === "false" || value2 === "mixed", 'Value of "checked" attribute must be a boolean or "mixed"', errorPos); node.checked = value2 === "true" ? true : value2 === "false" ? false : "mixed"; return; } if (key === "disabled") { this._assert(value2 === "true" || value2 === "false", 'Value of "disabled" attribute must be a boolean', errorPos); node.disabled = value2 === "true"; return; } if (key === "expanded") { this._assert(value2 === "true" || value2 === "false", 'Value of "expanded" attribute must be a boolean', errorPos); node.expanded = value2 === "true"; return; } if (key === "active") { this._assert(value2 === "true" || value2 === "false", 'Value of "active" attribute must be a boolean', errorPos); node.active = value2 === "true"; return; } if (key === "invalid") { this._assert(value2 === "true" || value2 === "false" || value2 === "grammar" || value2 === "spelling", 'Value of "invalid" attribute must be a boolean, "grammar" or "spelling"', errorPos); node.invalid = value2 === "true" ? true : value2 === "false" ? false : value2; return; } if (key === "level") { this._assert(!isNaN(Number(value2)), 'Value of "level" attribute must be a number', errorPos); node.level = Number(value2); return; } if (key === "pressed") { this._assert(value2 === "true" || value2 === "false" || value2 === "mixed", 'Value of "pressed" attribute must be a boolean or "mixed"', errorPos); node.pressed = value2 === "true" ? true : value2 === "false" ? false : "mixed"; return; } if (key === "selected") { this._assert(value2 === "true" || value2 === "false", 'Value of "selected" attribute must be a boolean', errorPos); node.selected = value2 === "true"; return; } this._assert(false, `Unsupported attribute [${key}]`, errorPos); } _assert(value2, message, valuePos) { if (!value2) this._throwError(message || "Assertion error", valuePos); } }; ParserError = class extends Error { constructor(message, pos) { super(message); this.pos = pos; } }; } }); // packages/isomorphic/stringUtils.ts function escapeWithQuotes(text2, char = "'") { const stringified = JSON.stringify(text2); const escapedText = stringified.substring(1, stringified.length - 1).replace(/\\"/g, '"'); if (char === "'") return char + escapedText.replace(/[']/g, "\\'") + char; if (char === '"') return char + escapedText.replace(/["]/g, '\\"') + char; if (char === "`") return char + escapedText.replace(/[`]/g, "\\`") + char; throw new Error("Invalid escape char"); } function escapeTemplateString(text2) { return text2.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${"); } function isString(obj) { return typeof obj === "string" || obj instanceof String; } function toTitleCase(name) { return name.charAt(0).toUpperCase() + name.substring(1); } function toSnakeCase(name) { return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase(); } function formatObject(value2, indent = " ", mode = "multiline") { if (typeof value2 === "string") return escapeWithQuotes(value2, "'"); if (Array.isArray(value2)) return `[${value2.map((o) => formatObject(o)).join(", ")}]`; if (typeof value2 === "object") { const keys = Object.keys(value2).filter((key) => key !== "timeout" && value2[key] !== void 0).sort(); if (!keys.length) return "{}"; const tokens = []; for (const key of keys) tokens.push(`${key}: ${formatObject(value2[key])}`); if (mode === "multiline") return `{ ${tokens.map((t) => indent + t).join(`, `)} }`; return `{ ${tokens.join(", ")} }`; } return String(value2); } function formatObjectOrVoid(value2, indent = " ") { const result2 = formatObject(value2, indent); return result2 === "{}" ? "" : result2; } function quoteCSSAttributeValue(text2) { return `"${text2.replace(/["\\]/g, (char) => "\\" + char)}"`; } function cacheNormalizedWhitespaces() { normalizedWhitespaceCache = /* @__PURE__ */ new Map(); } function normalizeWhiteSpace(text2) { let result2 = normalizedWhitespaceCache?.get(text2); if (result2 === void 0) { result2 = text2.replace(/[\u200b\u00ad]/g, "").trim().replace(/\s+/g, " "); normalizedWhitespaceCache?.set(text2, result2); } return result2; } function normalizeEscapedRegexQuotes(source11) { return source11.replace(/(^|[^\\])(\\\\)*\\(['"`])/g, "$1$2$3"); } function escapeRegexForSelector(re2) { if (re2.unicode || re2.unicodeSets) return String(re2); return String(re2).replace(/(^|[^\\])(\\\\)*(["'`])/g, "$1$2\\$3").replace(/>>/g, "\\>\\>"); } function escapeForTextSelector(text2, exact) { if (typeof text2 !== "string") return escapeRegexForSelector(text2); return `${JSON.stringify(text2)}${exact ? "s" : "i"}`; } function escapeForAttributeSelector(value2, exact) { if (typeof value2 !== "string") return escapeRegexForSelector(value2); return `"${value2.replace(/\\/g, "\\\\").replace(/["]/g, '\\"')}"${exact ? "s" : "i"}`; } function trimString(input, cap, suffix = "") { if (input.length <= cap) return input; const chars = [...input]; if (chars.length > cap) return chars.slice(0, cap - suffix.length).join("") + suffix; return chars.join(""); } function trimStringWithEllipsis(input, cap) { return trimString(input, cap, "\u2026"); } function escapeRegExp(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } function escapeHTMLAttribute(s) { return s.replace(/[&<>"']/ug, (char) => escaped[char]); } function escapeHTML(s) { return s.replace(/[&<]/ug, (char) => escaped[char]); } function longestCommonSubstring(s1, s2) { const n = s1.length; const m = s2.length; let maxLen = 0; let endingIndex = 0; const dp = Array(n + 1).fill(null).map(() => Array(m + 1).fill(0)); for (let i = 1; i <= n; i++) { for (let j = 1; j <= m; j++) { if (s1[i - 1] === s2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; if (dp[i][j] > maxLen) { maxLen = dp[i][j]; endingIndex = i; } } } } return s1.slice(endingIndex - maxLen, endingIndex); } function parseRegex(regex) { if (regex[0] !== "/") throw new Error(`Invalid regex, must start with '/': ${regex}`); const lastSlash = regex.lastIndexOf("/"); if (lastSlash <= 0) throw new Error(`Invalid regex, must end with '/' followed by optional flags: ${regex}`); const source11 = regex.slice(1, lastSlash); const flags = regex.slice(lastSlash + 1); return new RegExp(source11, flags); } function tomlBasicString(value2) { return JSON.stringify(value2); } function tomlArray(values) { return `[${values.map((value2) => tomlBasicString(value2)).join(", ")}]`; } function tomlMultilineBasicString(value2) { const escaped2 = value2.replace(/\\/g, "\\\\").replace(/"""/g, '\\"\\"\\"'); return `""" ${escaped2} """`; } function stripAnsiEscapes(str) { return str.replace(ansiRegex, ""); } var normalizedWhitespaceCache, escaped, ansiRegex; var init_stringUtils = __esm({ "packages/isomorphic/stringUtils.ts"() { "use strict"; escaped = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }; ansiRegex = new RegExp("([\\u001B\\u009B][[\\]()#?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)|(?:(?:\\d{0,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~])))", "g"); } }); // packages/isomorphic/rtti.ts function isRegExp(obj) { return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]"; } function isRegexString(value2) { try { new RegExp(value2); return true; } catch { return false; } } function isObject(obj) { return typeof obj === "object" && obj !== null; } function isError(obj) { return obj instanceof Error || obj && Object.getPrototypeOf(obj)?.name === "Error"; } var init_rtti = __esm({ "packages/isomorphic/rtti.ts"() { "use strict"; init_stringUtils(); } }); // packages/isomorphic/expectUtils.ts function serializeExpectedTextValues(items, options = {}) { return items.map((i) => ({ string: isString(i) ? i : void 0, regexSource: isRegExp(i) ? i.source : void 0, regexFlags: isRegExp(i) ? i.flags : void 0, matchSubstring: options.matchSubstring, ignoreCase: options.ignoreCase, normalizeWhiteSpace: options.normalizeWhiteSpace })); } var init_expectUtils = __esm({ "packages/isomorphic/expectUtils.ts"() { "use strict"; init_rtti(); } }); // packages/isomorphic/assert.ts function assert(value2, message) { if (!value2) throw new Error(message || "Assertion error"); } var init_assert = __esm({ "packages/isomorphic/assert.ts"() { "use strict"; } }); // packages/isomorphic/base64.ts function base64ByteLength(data) { if (!data) return 0; const padding = data[data.length - 2] === "=" ? 2 : data[data.length - 1] === "=" ? 1 : 0; return Math.max(0, Math.floor(data.length * 3 / 4) - padding); } var init_base64 = __esm({ "packages/isomorphic/base64.ts"() { "use strict"; } }); // packages/isomorphic/colors.ts var webColors, noColors, applyStyle; var init_colors = __esm({ "packages/isomorphic/colors.ts"() { "use strict"; webColors = { enabled: true, reset: (text2) => applyStyle(0, 0, text2), bold: (text2) => applyStyle(1, 22, text2), dim: (text2) => applyStyle(2, 22, text2), italic: (text2) => applyStyle(3, 23, text2), underline: (text2) => applyStyle(4, 24, text2), inverse: (text2) => applyStyle(7, 27, text2), hidden: (text2) => applyStyle(8, 28, text2), strikethrough: (text2) => applyStyle(9, 29, text2), black: (text2) => applyStyle(30, 39, text2), red: (text2) => applyStyle(31, 39, text2), green: (text2) => applyStyle(32, 39, text2), yellow: (text2) => applyStyle(33, 39, text2), blue: (text2) => applyStyle(34, 39, text2), magenta: (text2) => applyStyle(35, 39, text2), cyan: (text2) => applyStyle(36, 39, text2), white: (text2) => applyStyle(37, 39, text2), gray: (text2) => applyStyle(90, 39, text2), grey: (text2) => applyStyle(90, 39, text2) }; noColors = { enabled: false, reset: (t) => t, bold: (t) => t, dim: (t) => t, italic: (t) => t, underline: (t) => t, inverse: (t) => t, hidden: (t) => t, strikethrough: (t) => t, black: (t) => t, red: (t) => t, green: (t) => t, yellow: (t) => t, blue: (t) => t, magenta: (t) => t, cyan: (t) => t, white: (t) => t, gray: (t) => t, grey: (t) => t }; applyStyle = (open5, close3, text2) => `\x1B[${open5}m${text2}\x1B[${close3}m`; } }); // packages/isomorphic/headers.ts function headersObjectToArray(headers, separator, setCookieSeparator) { if (!setCookieSeparator) setCookieSeparator = separator; const result2 = []; for (const name in headers) { const values = headers[name]; if (values === void 0) continue; if (separator) { const sep = name.toLowerCase() === "set-cookie" ? setCookieSeparator : separator; for (const value2 of values.split(sep)) result2.push({ name, value: value2.trim() }); } else { result2.push({ name, value: values }); } } return result2; } function headersArrayToObject(headers, lowerCase) { const result2 = {}; for (const { name, value: value2 } of headers) result2[lowerCase ? name.toLowerCase() : name] = value2; return result2; } var init_headers = __esm({ "packages/isomorphic/headers.ts"() { "use strict"; } }); // packages/isomorphic/imageUtils.ts function padImageToSize(image, size) { if (image.width === size.width && image.height === size.height) return image; const buffer = new Uint8Array(size.width * size.height * 4); for (let y = 0; y < size.height; y++) { for (let x = 0; x < size.width; x++) { const to = (y * size.width + x) * 4; if (y < image.height && x < image.width) { const from = (y * image.width + x) * 4; buffer[to] = image.data[from]; buffer[to + 1] = image.data[from + 1]; buffer[to + 2] = image.data[from + 2]; buffer[to + 3] = image.data[from + 3]; } else { buffer[to] = 0; buffer[to + 1] = 0; buffer[to + 2] = 0; buffer[to + 3] = 0; } } } return { data: Buffer.from(buffer), width: size.width, height: size.height }; } function scaleImageToSize(image, size) { const { data: src, width: w1, height: h1 } = image; const w2 = Math.max(1, Math.floor(size.width)); const h2 = Math.max(1, Math.floor(size.height)); if (w1 === w2 && h1 === h2) return image; if (w1 <= 0 || h1 <= 0) throw new Error("Invalid input image"); if (size.width <= 0 || size.height <= 0 || !isFinite(size.width) || !isFinite(size.height)) throw new Error("Invalid output dimensions"); const clamp = (v, lo, hi) => v < lo ? lo : v > hi ? hi : v; const weights = (t, o) => { const t2 = t * t; const t3 = t2 * t; o[0] = -0.5 * t + 1 * t2 - 0.5 * t3; o[1] = 1 - 2.5 * t2 + 1.5 * t3; o[2] = 0.5 * t + 2 * t2 - 1.5 * t3; o[3] = -0.5 * t2 + 0.5 * t3; }; const srcRowStride = w1 * 4; const dstRowStride = w2 * 4; const xOff = new Int32Array(w2 * 4); const xW = new Float32Array(w2 * 4); const wx = new Float32Array(4); const xScale = w1 / w2; for (let x = 0; x < w2; x++) { const sx = (x + 0.5) * xScale - 0.5; const sxi = Math.floor(sx); const t = sx - sxi; weights(t, wx); const b = x * 4; const i0 = clamp(sxi - 1, 0, w1 - 1); const i1 = clamp(sxi + 0, 0, w1 - 1); const i2 = clamp(sxi + 1, 0, w1 - 1); const i3 = clamp(sxi + 2, 0, w1 - 1); xOff[b + 0] = i0 << 2; xOff[b + 1] = i1 << 2; xOff[b + 2] = i2 << 2; xOff[b + 3] = i3 << 2; xW[b + 0] = wx[0]; xW[b + 1] = wx[1]; xW[b + 2] = wx[2]; xW[b + 3] = wx[3]; } const yRow = new Int32Array(h2 * 4); const yW = new Float32Array(h2 * 4); const wy = new Float32Array(4); const yScale = h1 / h2; for (let y = 0; y < h2; y++) { const sy = (y + 0.5) * yScale - 0.5; const syi = Math.floor(sy); const t = sy - syi; weights(t, wy); const b = y * 4; const j0 = clamp(syi - 1, 0, h1 - 1); const j1 = clamp(syi + 0, 0, h1 - 1); const j2 = clamp(syi + 1, 0, h1 - 1); const j3 = clamp(syi + 2, 0, h1 - 1); yRow[b + 0] = j0 * srcRowStride; yRow[b + 1] = j1 * srcRowStride; yRow[b + 2] = j2 * srcRowStride; yRow[b + 3] = j3 * srcRowStride; yW[b + 0] = wy[0]; yW[b + 1] = wy[1]; yW[b + 2] = wy[2]; yW[b + 3] = wy[3]; } const dst = new Uint8Array(w2 * h2 * 4); for (let y = 0; y < h2; y++) { const yb = y * 4; const rb0 = yRow[yb + 0]; const rb1 = yRow[yb + 1]; const rb2 = yRow[yb + 2]; const rb3 = yRow[yb + 3]; const wy0 = yW[yb + 0]; const wy1 = yW[yb + 1]; const wy2 = yW[yb + 2]; const wy3 = yW[yb + 3]; const dstBase = y * dstRowStride; for (let x = 0; x < w2; x++) { const xb = x * 4; const xo0 = xOff[xb + 0]; const xo1 = xOff[xb + 1]; const xo2 = xOff[xb + 2]; const xo3 = xOff[xb + 3]; const wx0 = xW[xb + 0]; const wx1 = xW[xb + 1]; const wx2 = xW[xb + 2]; const wx3 = xW[xb + 3]; const di = dstBase + (x << 2); for (let c = 0; c < 4; c++) { const r0 = src[rb0 + xo0 + c] * wx0 + src[rb0 + xo1 + c] * wx1 + src[rb0 + xo2 + c] * wx2 + src[rb0 + xo3 + c] * wx3; const r1 = src[rb1 + xo0 + c] * wx0 + src[rb1 + xo1 + c] * wx1 + src[rb1 + xo2 + c] * wx2 + src[rb1 + xo3 + c] * wx3; const r2 = src[rb2 + xo0 + c] * wx0 + src[rb2 + xo1 + c] * wx1 + src[rb2 + xo2 + c] * wx2 + src[rb2 + xo3 + c] * wx3; const r3 = src[rb3 + xo0 + c] * wx0 + src[rb3 + xo1 + c] * wx1 + src[rb3 + xo2 + c] * wx2 + src[rb3 + xo3 + c] * wx3; const v = r0 * wy0 + r1 * wy1 + r2 * wy2 + r3 * wy3; dst[di + c] = v < 0 ? 0 : v > 255 ? 255 : v | 0; } } } return { data: Buffer.from(dst.buffer), width: w2, height: h2 }; } var init_imageUtils = __esm({ "packages/isomorphic/imageUtils.ts"() { "use strict"; } }); // packages/isomorphic/jsonSchema.ts function validate(value2, schema, path59) { const errors = []; if (schema.oneOf) { let bestErrors; for (const variant of schema.oneOf) { const variantErrors = validate(value2, variant, path59); if (variantErrors.length === 0) return []; if (!bestErrors || variantErrors.length < bestErrors.length) bestErrors = variantErrors; } if (bestErrors.length === 1 && bestErrors[0].startsWith(`${path59}: expected `)) return [`${path59}: does not match any of the expected types`]; return bestErrors; } if (schema.type === "string") { if (typeof value2 !== "string") { errors.push(`${path59}: expected string, got ${typeof value2}`); return errors; } if (schema.pattern && !cachedRegex(schema.pattern).test(value2)) errors.push(schema.patternError || `${path59}: must match pattern "${schema.pattern}"`); return errors; } if (schema.type === "array") { if (!Array.isArray(value2)) { errors.push(`${path59}: expected array, got ${typeof value2}`); return errors; } if (schema.items) { for (let i = 0; i < value2.length; i++) errors.push(...validate(value2[i], schema.items, `${path59}[${i}]`)); } return errors; } if (schema.type === "object") { if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) { errors.push(`${path59}: expected object, got ${Array.isArray(value2) ? "array" : typeof value2}`); return errors; } const obj = value2; for (const key of schema.required || []) { if (obj[key] === void 0) errors.push(`${path59}.${key}: required`); } for (const [key, propSchema] of Object.entries(schema.properties || {})) { if (obj[key] !== void 0) errors.push(...validate(obj[key], propSchema, `${path59}.${key}`)); } return errors; } return errors; } function cachedRegex(pattern) { let regex = regexCache.get(pattern); if (!regex) { regex = new RegExp(pattern); regexCache.set(pattern, regex); } return regex; } var regexCache; var init_jsonSchema = __esm({ "packages/isomorphic/jsonSchema.ts"() { "use strict"; regexCache = /* @__PURE__ */ new Map(); } }); // packages/isomorphic/cssTokenizer.ts function digit(code) { return between(code, 48, 57); } function hexdigit(code) { return digit(code) || between(code, 65, 70) || between(code, 97, 102); } function uppercaseletter(code) { return between(code, 65, 90); } function lowercaseletter(code) { return between(code, 97, 122); } function letter(code) { return uppercaseletter(code) || lowercaseletter(code); } function nonascii(code) { return code >= 128; } function namestartchar(code) { return letter(code) || nonascii(code) || code === 95; } function namechar(code) { return namestartchar(code) || digit(code) || code === 45; } function nonprintable(code) { return between(code, 0, 8) || code === 11 || between(code, 14, 31) || code === 127; } function newline(code) { return code === 10; } function whitespace(code) { return newline(code) || code === 9 || code === 32; } function preprocess(str) { const codepoints = []; for (let i = 0; i < str.length; i++) { let code = str.charCodeAt(i); if (code === 13 && str.charCodeAt(i + 1) === 10) { code = 10; i++; } if (code === 13 || code === 12) code = 10; if (code === 0) code = 65533; if (between(code, 55296, 56319) && between(str.charCodeAt(i + 1), 56320, 57343)) { const lead = code - 55296; const trail = str.charCodeAt(i + 1) - 56320; code = Math.pow(2, 16) + lead * Math.pow(2, 10) + trail; i++; } codepoints.push(code); } return codepoints; } function stringFromCode(code) { if (code <= 65535) return String.fromCharCode(code); code -= Math.pow(2, 16); const lead = Math.floor(code / Math.pow(2, 10)) + 55296; const trail = code % Math.pow(2, 10) + 56320; return String.fromCharCode(lead) + String.fromCharCode(trail); } function tokenize(str1) { const str = preprocess(str1); let i = -1; const tokens = []; let code; let line = 0; let column = 0; let lastLineLength = 0; const incrLineno = function() { line += 1; lastLineLength = column; column = 0; }; const locStart = { line, column }; const codepoint = function(i2) { if (i2 >= str.length) return -1; return str[i2]; }; const next = function(num) { if (num === void 0) num = 1; if (num > 3) throw "Spec Error: no more than three codepoints of lookahead."; return codepoint(i + num); }; const consume = function(num) { if (num === void 0) num = 1; i += num; code = codepoint(i); if (newline(code)) incrLineno(); else column += num; return true; }; const reconsume = function() { i -= 1; if (newline(code)) { line -= 1; column = lastLineLength; } else { column -= 1; } locStart.line = line; locStart.column = column; return true; }; const eof = function(codepoint2) { if (codepoint2 === void 0) codepoint2 = code; return codepoint2 === -1; }; const donothing = function() { }; const parseerror = function() { }; const consumeAToken = function() { consumeComments(); consume(); if (whitespace(code)) { while (whitespace(next())) consume(); return new WhitespaceToken(); } else if (code === 34) { return consumeAStringToken(); } else if (code === 35) { if (namechar(next()) || areAValidEscape(next(1), next(2))) { const token = new HashToken(""); if (wouldStartAnIdentifier(next(1), next(2), next(3))) token.type = "id"; token.value = consumeAName(); return token; } else { return new DelimToken(code); } } else if (code === 36) { if (next() === 61) { consume(); return new SuffixMatchToken(); } else { return new DelimToken(code); } } else if (code === 39) { return consumeAStringToken(); } else if (code === 40) { return new OpenParenToken(); } else if (code === 41) { return new CloseParenToken(); } else if (code === 42) { if (next() === 61) { consume(); return new SubstringMatchToken(); } else { return new DelimToken(code); } } else if (code === 43) { if (startsWithANumber()) { reconsume(); return consumeANumericToken(); } else { return new DelimToken(code); } } else if (code === 44) { return new CommaToken(); } else if (code === 45) { if (startsWithANumber()) { reconsume(); return consumeANumericToken(); } else if (next(1) === 45 && next(2) === 62) { consume(2); return new CDCToken(); } else if (startsWithAnIdentifier()) { reconsume(); return consumeAnIdentlikeToken(); } else { return new DelimToken(code); } } else if (code === 46) { if (startsWithANumber()) { reconsume(); return consumeANumericToken(); } else { return new DelimToken(code); } } else if (code === 58) { return new ColonToken(); } else if (code === 59) { return new SemicolonToken(); } else if (code === 60) { if (next(1) === 33 && next(2) === 45 && next(3) === 45) { consume(3); return new CDOToken(); } else { return new DelimToken(code); } } else if (code === 64) { if (wouldStartAnIdentifier(next(1), next(2), next(3))) return new AtKeywordToken(consumeAName()); else return new DelimToken(code); } else if (code === 91) { return new OpenSquareToken(); } else if (code === 92) { if (startsWithAValidEscape()) { reconsume(); return consumeAnIdentlikeToken(); } else { parseerror(); return new DelimToken(code); } } else if (code === 93) { return new CloseSquareToken(); } else if (code === 94) { if (next() === 61) { consume(); return new PrefixMatchToken(); } else { return new DelimToken(code); } } else if (code === 123) { return new OpenCurlyToken(); } else if (code === 124) { if (next() === 61) { consume(); return new DashMatchToken(); } else if (next() === 124) { consume(); return new ColumnToken(); } else { return new DelimToken(code); } } else if (code === 125) { return new CloseCurlyToken(); } else if (code === 126) { if (next() === 61) { consume(); return new IncludeMatchToken(); } else { return new DelimToken(code); } } else if (digit(code)) { reconsume(); return consumeANumericToken(); } else if (namestartchar(code)) { reconsume(); return consumeAnIdentlikeToken(); } else if (eof()) { return new EOFToken(); } else { return new DelimToken(code); } }; const consumeComments = function() { while (next(1) === 47 && next(2) === 42) { consume(2); while (true) { consume(); if (code === 42 && next() === 47) { consume(); break; } else if (eof()) { parseerror(); return; } } } }; const consumeANumericToken = function() { const num = consumeANumber(); if (wouldStartAnIdentifier(next(1), next(2), next(3))) { const token = new DimensionToken(); token.value = num.value; token.repr = num.repr; token.type = num.type; token.unit = consumeAName(); return token; } else if (next() === 37) { consume(); const token = new PercentageToken(); token.value = num.value; token.repr = num.repr; return token; } else { const token = new NumberToken(); token.value = num.value; token.repr = num.repr; token.type = num.type; return token; } }; const consumeAnIdentlikeToken = function() { const str2 = consumeAName(); if (str2.toLowerCase() === "url" && next() === 40) { consume(); while (whitespace(next(1)) && whitespace(next(2))) consume(); if (next() === 34 || next() === 39) return new FunctionToken(str2); else if (whitespace(next()) && (next(2) === 34 || next(2) === 39)) return new FunctionToken(str2); else return consumeAURLToken(); } else if (next() === 40) { consume(); return new FunctionToken(str2); } else { return new IdentToken(str2); } }; const consumeAStringToken = function(endingCodePoint) { if (endingCodePoint === void 0) endingCodePoint = code; let string = ""; while (consume()) { if (code === endingCodePoint || eof()) { return new StringToken(string); } else if (newline(code)) { parseerror(); reconsume(); return new BadStringToken(); } else if (code === 92) { if (eof(next())) donothing(); else if (newline(next())) consume(); else string += stringFromCode(consumeEscape()); } else { string += stringFromCode(code); } } throw new Error("Internal error"); }; const consumeAURLToken = function() { const token = new URLToken(""); while (whitespace(next())) consume(); if (eof(next())) return token; while (consume()) { if (code === 41 || eof()) { return token; } else if (whitespace(code)) { while (whitespace(next())) consume(); if (next() === 41 || eof(next())) { consume(); return token; } else { consumeTheRemnantsOfABadURL(); return new BadURLToken(); } } else if (code === 34 || code === 39 || code === 40 || nonprintable(code)) { parseerror(); consumeTheRemnantsOfABadURL(); return new BadURLToken(); } else if (code === 92) { if (startsWithAValidEscape()) { token.value += stringFromCode(consumeEscape()); } else { parseerror(); consumeTheRemnantsOfABadURL(); return new BadURLToken(); } } else { token.value += stringFromCode(code); } } throw new Error("Internal error"); }; const consumeEscape = function() { consume(); if (hexdigit(code)) { const digits = [code]; for (let total = 0; total < 5; total++) { if (hexdigit(next())) { consume(); digits.push(code); } else { break; } } if (whitespace(next())) consume(); let value2 = parseInt(digits.map(function(x) { return String.fromCharCode(x); }).join(""), 16); if (value2 > maximumallowedcodepoint) value2 = 65533; return value2; } else if (eof()) { return 65533; } else { return code; } }; const areAValidEscape = function(c1, c2) { if (c1 !== 92) return false; if (newline(c2)) return false; return true; }; const startsWithAValidEscape = function() { return areAValidEscape(code, next()); }; const wouldStartAnIdentifier = function(c1, c2, c3) { if (c1 === 45) return namestartchar(c2) || c2 === 45 || areAValidEscape(c2, c3); else if (namestartchar(c1)) return true; else if (c1 === 92) return areAValidEscape(c1, c2); else return false; }; const startsWithAnIdentifier = function() { return wouldStartAnIdentifier(code, next(1), next(2)); }; const wouldStartANumber = function(c1, c2, c3) { if (c1 === 43 || c1 === 45) { if (digit(c2)) return true; if (c2 === 46 && digit(c3)) return true; return false; } else if (c1 === 46) { if (digit(c2)) return true; return false; } else if (digit(c1)) { return true; } else { return false; } }; const startsWithANumber = function() { return wouldStartANumber(code, next(1), next(2)); }; const consumeAName = function() { let result2 = ""; while (consume()) { if (namechar(code)) { result2 += stringFromCode(code); } else if (startsWithAValidEscape()) { result2 += stringFromCode(consumeEscape()); } else { reconsume(); return result2; } } throw new Error("Internal parse error"); }; const consumeANumber = function() { let repr = ""; let type3 = "integer"; if (next() === 43 || next() === 45) { consume(); repr += stringFromCode(code); } while (digit(next())) { consume(); repr += stringFromCode(code); } if (next(1) === 46 && digit(next(2))) { consume(); repr += stringFromCode(code); consume(); repr += stringFromCode(code); type3 = "number"; while (digit(next())) { consume(); repr += stringFromCode(code); } } const c1 = next(1); const c2 = next(2); const c3 = next(3); if ((c1 === 69 || c1 === 101) && digit(c2)) { consume(); repr += stringFromCode(code); consume(); repr += stringFromCode(code); type3 = "number"; while (digit(next())) { consume(); repr += stringFromCode(code); } } else if ((c1 === 69 || c1 === 101) && (c2 === 43 || c2 === 45) && digit(c3)) { consume(); repr += stringFromCode(code); consume(); repr += stringFromCode(code); consume(); repr += stringFromCode(code); type3 = "number"; while (digit(next())) { consume(); repr += stringFromCode(code); } } const value2 = convertAStringToANumber(repr); return { type: type3, value: value2, repr }; }; const convertAStringToANumber = function(string) { return +string; }; const consumeTheRemnantsOfABadURL = function() { while (consume()) { if (code === 41 || eof()) { return; } else if (startsWithAValidEscape()) { consumeEscape(); donothing(); } else { donothing(); } } }; let iterationCount = 0; while (!eof(next())) { tokens.push(consumeAToken()); iterationCount++; if (iterationCount > str.length * 2) throw new Error("I'm infinite-looping!"); } return tokens; } function escapeIdent(string) { string = "" + string; let result2 = ""; const firstcode = string.charCodeAt(0); for (let i = 0; i < string.length; i++) { const code = string.charCodeAt(i); if (code === 0) throw new InvalidCharacterError("Invalid character: the input contains U+0000."); if (between(code, 1, 31) || code === 127 || i === 0 && between(code, 48, 57) || i === 1 && between(code, 48, 57) && firstcode === 45) result2 += "\\" + code.toString(16) + " "; else if (code >= 128 || code === 45 || code === 95 || between(code, 48, 57) || between(code, 65, 90) || between(code, 97, 122)) result2 += string[i]; else result2 += "\\" + string[i]; } return result2; } function escapeHash(string) { string = "" + string; let result2 = ""; for (let i = 0; i < string.length; i++) { const code = string.charCodeAt(i); if (code === 0) throw new InvalidCharacterError("Invalid character: the input contains U+0000."); if (code >= 128 || code === 45 || code === 95 || between(code, 48, 57) || between(code, 65, 90) || between(code, 97, 122)) result2 += string[i]; else result2 += "\\" + code.toString(16) + " "; } return result2; } function escapeString(string) { string = "" + string; let result2 = ""; for (let i = 0; i < string.length; i++) { const code = string.charCodeAt(i); if (code === 0) throw new InvalidCharacterError("Invalid character: the input contains U+0000."); if (between(code, 1, 31) || code === 127) result2 += "\\" + code.toString(16) + " "; else if (code === 34 || code === 92) result2 += "\\" + string[i]; else result2 += string[i]; } return result2; } var between, maximumallowedcodepoint, InvalidCharacterError, CSSParserToken, BadStringToken, BadURLToken, WhitespaceToken, CDOToken, CDCToken, ColonToken, SemicolonToken, CommaToken, GroupingToken, OpenCurlyToken, CloseCurlyToken, OpenSquareToken, CloseSquareToken, OpenParenToken, CloseParenToken, IncludeMatchToken, DashMatchToken, PrefixMatchToken, SuffixMatchToken, SubstringMatchToken, ColumnToken, EOFToken, DelimToken, StringValuedToken, IdentToken, FunctionToken, AtKeywordToken, HashToken, StringToken, URLToken, NumberToken, PercentageToken, DimensionToken; var init_cssTokenizer = __esm({ "packages/isomorphic/cssTokenizer.ts"() { "use strict"; between = function(num, first, last) { return num >= first && num <= last; }; maximumallowedcodepoint = 1114111; InvalidCharacterError = class extends Error { constructor(message) { super(message); this.name = "InvalidCharacterError"; } }; CSSParserToken = class { constructor() { this.tokenType = ""; } toJSON() { return { token: this.tokenType }; } toString() { return this.tokenType; } toSource() { return "" + this; } }; BadStringToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "BADSTRING"; } }; BadURLToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "BADURL"; } }; WhitespaceToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "WHITESPACE"; } toString() { return "WS"; } toSource() { return " "; } }; CDOToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "CDO"; } toSource() { return ""; } }; ColonToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = ":"; } }; SemicolonToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = ";"; } }; CommaToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = ","; } }; GroupingToken = class extends CSSParserToken { constructor() { super(...arguments); this.value = ""; this.mirror = ""; } }; OpenCurlyToken = class extends GroupingToken { constructor() { super(); this.tokenType = "{"; this.value = "{"; this.mirror = "}"; } }; CloseCurlyToken = class extends GroupingToken { constructor() { super(); this.tokenType = "}"; this.value = "}"; this.mirror = "{"; } }; OpenSquareToken = class extends GroupingToken { constructor() { super(); this.tokenType = "["; this.value = "["; this.mirror = "]"; } }; CloseSquareToken = class extends GroupingToken { constructor() { super(); this.tokenType = "]"; this.value = "]"; this.mirror = "["; } }; OpenParenToken = class extends GroupingToken { constructor() { super(); this.tokenType = "("; this.value = "("; this.mirror = ")"; } }; CloseParenToken = class extends GroupingToken { constructor() { super(); this.tokenType = ")"; this.value = ")"; this.mirror = "("; } }; IncludeMatchToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "~="; } }; DashMatchToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "|="; } }; PrefixMatchToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "^="; } }; SuffixMatchToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "$="; } }; SubstringMatchToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "*="; } }; ColumnToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "||"; } }; EOFToken = class extends CSSParserToken { constructor() { super(...arguments); this.tokenType = "EOF"; } toSource() { return ""; } }; DelimToken = class extends CSSParserToken { constructor(code) { super(); this.tokenType = "DELIM"; this.value = ""; this.value = stringFromCode(code); } toString() { return "DELIM(" + this.value + ")"; } toJSON() { const json = this.constructor.prototype.constructor.prototype.toJSON.call(this); json.value = this.value; return json; } toSource() { if (this.value === "\\") return "\\\n"; else return this.value; } }; StringValuedToken = class extends CSSParserToken { constructor() { super(...arguments); this.value = ""; } ASCIIMatch(str) { return this.value.toLowerCase() === str.toLowerCase(); } toJSON() { const json = this.constructor.prototype.constructor.prototype.toJSON.call(this); json.value = this.value; return json; } }; IdentToken = class extends StringValuedToken { constructor(val) { super(); this.tokenType = "IDENT"; this.value = val; } toString() { return "IDENT(" + this.value + ")"; } toSource() { return escapeIdent(this.value); } }; FunctionToken = class extends StringValuedToken { constructor(val) { super(); this.tokenType = "FUNCTION"; this.value = val; this.mirror = ")"; } toString() { return "FUNCTION(" + this.value + ")"; } toSource() { return escapeIdent(this.value) + "("; } }; AtKeywordToken = class extends StringValuedToken { constructor(val) { super(); this.tokenType = "AT-KEYWORD"; this.value = val; } toString() { return "AT(" + this.value + ")"; } toSource() { return "@" + escapeIdent(this.value); } }; HashToken = class extends StringValuedToken { constructor(val) { super(); this.tokenType = "HASH"; this.value = val; this.type = "unrestricted"; } toString() { return "HASH(" + this.value + ")"; } toJSON() { const json = this.constructor.prototype.constructor.prototype.toJSON.call(this); json.value = this.value; json.type = this.type; return json; } toSource() { if (this.type === "id") return "#" + escapeIdent(this.value); else return "#" + escapeHash(this.value); } }; StringToken = class extends StringValuedToken { constructor(val) { super(); this.tokenType = "STRING"; this.value = val; } toString() { return '"' + escapeString(this.value) + '"'; } }; URLToken = class extends StringValuedToken { constructor(val) { super(); this.tokenType = "URL"; this.value = val; } toString() { return "URL(" + this.value + ")"; } toSource() { return 'url("' + escapeString(this.value) + '")'; } }; NumberToken = class extends CSSParserToken { constructor() { super(); this.tokenType = "NUMBER"; this.type = "integer"; this.repr = ""; } toString() { if (this.type === "integer") return "INT(" + this.value + ")"; return "NUMBER(" + this.value + ")"; } toJSON() { const json = super.toJSON(); json.value = this.value; json.type = this.type; json.repr = this.repr; return json; } toSource() { return this.repr; } }; PercentageToken = class extends CSSParserToken { constructor() { super(); this.tokenType = "PERCENTAGE"; this.repr = ""; } toString() { return "PERCENTAGE(" + this.value + ")"; } toJSON() { const json = this.constructor.prototype.constructor.prototype.toJSON.call(this); json.value = this.value; json.repr = this.repr; return json; } toSource() { return this.repr + "%"; } }; DimensionToken = class extends CSSParserToken { constructor() { super(); this.tokenType = "DIMENSION"; this.type = "integer"; this.repr = ""; this.unit = ""; } toString() { return "DIM(" + this.value + "," + this.unit + ")"; } toJSON() { const json = this.constructor.prototype.constructor.prototype.toJSON.call(this); json.value = this.value; json.type = this.type; json.repr = this.repr; json.unit = this.unit; return json; } toSource() { const source11 = this.repr; let unit = escapeIdent(this.unit); if (unit[0].toLowerCase() === "e" && (unit[1] === "-" || between(unit.charCodeAt(1), 48, 57))) { unit = "\\65 " + unit.slice(1, unit.length); } return source11 + unit; } }; } }); // packages/isomorphic/cssParser.ts function isInvalidSelectorError(error) { return error instanceof InvalidSelectorError; } function parseCSS(selector, customNames) { let tokens; try { tokens = tokenize(selector); if (!(tokens[tokens.length - 1] instanceof EOFToken)) tokens.push(new EOFToken()); } catch (e) { const newMessage = e.message + ` while parsing css selector "${selector}". Did you mean to CSS.escape it?`; const index = (e.stack || "").indexOf(e.message); if (index !== -1) e.stack = e.stack.substring(0, index) + newMessage + e.stack.substring(index + e.message.length); e.message = newMessage; throw e; } const unsupportedToken = tokens.find((token) => { return token instanceof AtKeywordToken || token instanceof BadStringToken || token instanceof BadURLToken || token instanceof ColumnToken || token instanceof CDOToken || token instanceof CDCToken || token instanceof SemicolonToken || // TODO: Consider using these for something, e.g. to escape complex strings. // For example :xpath{ (//div/bar[@attr="foo"])[2]/baz } // Or this way :xpath( {complex-xpath-goes-here("hello")} ) token instanceof OpenCurlyToken || token instanceof CloseCurlyToken || // TODO: Consider treating these as strings? token instanceof URLToken || token instanceof PercentageToken; }); if (unsupportedToken) throw new InvalidSelectorError(`Unsupported token "${unsupportedToken.toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`); let pos = 0; const names = /* @__PURE__ */ new Set(); function unexpected() { return new InvalidSelectorError(`Unexpected token "${tokens[pos].toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`); } function skipWhitespace() { while (tokens[pos] instanceof WhitespaceToken) pos++; } function isIdent(p = pos) { return tokens[p] instanceof IdentToken; } function isString2(p = pos) { return tokens[p] instanceof StringToken; } function isNumber(p = pos) { return tokens[p] instanceof NumberToken; } function isComma(p = pos) { return tokens[p] instanceof CommaToken; } function isOpenParen(p = pos) { return tokens[p] instanceof OpenParenToken; } function isCloseParen(p = pos) { return tokens[p] instanceof CloseParenToken; } function isFunction2(p = pos) { return tokens[p] instanceof FunctionToken; } function isStar(p = pos) { return tokens[p] instanceof DelimToken && tokens[p].value === "*"; } function isEOF(p = pos) { return tokens[p] instanceof EOFToken; } function isClauseCombinator(p = pos) { return tokens[p] instanceof DelimToken && [">", "+", "~"].includes(tokens[p].value); } function isSelectorClauseEnd(p = pos) { return isComma(p) || isCloseParen(p) || isEOF(p) || isClauseCombinator(p) || tokens[p] instanceof WhitespaceToken; } function consumeFunctionArguments() { const result3 = [consumeArgument()]; while (true) { skipWhitespace(); if (!isComma()) break; pos++; result3.push(consumeArgument()); } return result3; } function consumeArgument() { skipWhitespace(); if (isNumber()) return tokens[pos++].value; if (isString2()) return tokens[pos++].value; return consumeComplexSelector(); } function consumeComplexSelector() { const result3 = { simples: [] }; skipWhitespace(); if (isClauseCombinator()) { result3.simples.push({ selector: { functions: [{ name: "scope", args: [] }] }, combinator: "" }); } else { result3.simples.push({ selector: consumeSimpleSelector(), combinator: "" }); } while (true) { skipWhitespace(); if (isClauseCombinator()) { result3.simples[result3.simples.length - 1].combinator = tokens[pos++].value; skipWhitespace(); } else if (isSelectorClauseEnd()) { break; } result3.simples.push({ combinator: "", selector: consumeSimpleSelector() }); } return result3; } function consumeSimpleSelector() { let rawCSSString = ""; const functions = []; while (!isSelectorClauseEnd()) { if (isIdent() || isStar()) { rawCSSString += tokens[pos++].toSource(); } else if (tokens[pos] instanceof HashToken) { rawCSSString += tokens[pos++].toSource(); } else if (tokens[pos] instanceof DelimToken && tokens[pos].value === ".") { pos++; if (isIdent()) rawCSSString += "." + tokens[pos++].toSource(); else throw unexpected(); } else if (tokens[pos] instanceof ColonToken) { pos++; if (isIdent()) { if (!customNames.has(tokens[pos].value.toLowerCase())) { rawCSSString += ":" + tokens[pos++].toSource(); } else { const name = tokens[pos++].value.toLowerCase(); functions.push({ name, args: [] }); names.add(name); } } else if (isFunction2()) { const name = tokens[pos++].value.toLowerCase(); if (!customNames.has(name)) { rawCSSString += `:${name}(${consumeBuiltinFunctionArguments()})`; } else { functions.push({ name, args: consumeFunctionArguments() }); names.add(name); } skipWhitespace(); if (!isCloseParen()) throw unexpected(); pos++; } else { throw unexpected(); } } else if (tokens[pos] instanceof OpenSquareToken) { rawCSSString += "["; pos++; while (!(tokens[pos] instanceof CloseSquareToken) && !isEOF()) rawCSSString += tokens[pos++].toSource(); if (!(tokens[pos] instanceof CloseSquareToken)) throw unexpected(); rawCSSString += "]"; pos++; } else { throw unexpected(); } } if (!rawCSSString && !functions.length) throw unexpected(); return { css: rawCSSString || void 0, functions }; } function consumeBuiltinFunctionArguments() { let s = ""; let balance = 1; while (!isEOF()) { if (isOpenParen() || isFunction2()) balance++; if (isCloseParen()) balance--; if (!balance) break; s += tokens[pos++].toSource(); } return s; } const result2 = consumeFunctionArguments(); if (!isEOF()) throw unexpected(); if (result2.some((arg) => typeof arg !== "object" || !("simples" in arg))) throw new InvalidSelectorError(`Error while parsing css selector "${selector}". Did you mean to CSS.escape it?`); return { selector: result2, names: Array.from(names) }; } function serializeSelector(args) { return args.map((arg) => { if (typeof arg === "string") return `"${arg}"`; if (typeof arg === "number") return String(arg); return arg.simples.map(({ selector, combinator }) => { let s = selector.css || ""; s = s + selector.functions.map((func) => `:${func.name}(${serializeSelector(func.args)})`).join(""); if (combinator) s += " " + combinator; return s; }).join(" "); }).join(", "); } var InvalidSelectorError; var init_cssParser = __esm({ "packages/isomorphic/cssParser.ts"() { "use strict"; init_cssTokenizer(); InvalidSelectorError = class extends Error { }; } }); // packages/isomorphic/selectorParser.ts function parseSelector(selector) { const parsedStrings = parseSelectorString(selector); const parts = []; for (const part of parsedStrings.parts) { if (part.name === "css" || part.name === "css:light") { if (part.name === "css:light") part.body = ":light(" + part.body + ")"; const parsedCSS = parseCSS(part.body, customCSSNames); parts.push({ name: "css", body: parsedCSS.selector, source: part.body }); continue; } if (kNestedSelectorNames.has(part.name)) { let innerSelector; let distance; try { const unescaped = JSON.parse("[" + part.body + "]"); if (!Array.isArray(unescaped) || unescaped.length < 1 || unescaped.length > 2 || typeof unescaped[0] !== "string") throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body); innerSelector = unescaped[0]; if (unescaped.length === 2) { if (typeof unescaped[1] !== "number" || !kNestedSelectorNamesWithDistance.has(part.name)) throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body); distance = unescaped[1]; } } catch (e) { throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body); } const nested = { name: part.name, source: part.body, body: { parsed: parseSelector(innerSelector), distance } }; const lastFrame = [...nested.body.parsed.parts].reverse().find((part2) => part2.name === "internal:control" && part2.body === "enter-frame"); const lastFrameIndex = lastFrame ? nested.body.parsed.parts.indexOf(lastFrame) : -1; if (lastFrameIndex !== -1 && selectorPartsEqual(nested.body.parsed.parts.slice(0, lastFrameIndex + 1), parts.slice(0, lastFrameIndex + 1))) nested.body.parsed.parts.splice(0, lastFrameIndex + 1); parts.push(nested); continue; } parts.push({ ...part, source: part.body }); } if (kNestedSelectorNames.has(parts[0].name)) throw new InvalidSelectorError(`"${parts[0].name}" selector cannot be first`); return { capture: parsedStrings.capture, parts }; } function splitSelectorByFrame(selectorText) { const selector = parseSelector(selectorText); const result2 = []; let chunk = { parts: [] }; let chunkStartIndex = 0; for (let i = 0; i < selector.parts.length; ++i) { const part = selector.parts[i]; if (part.name === "internal:control" && part.body === "enter-frame") { if (!chunk.parts.length) throw new InvalidSelectorError("Selector cannot start with entering frame, select the iframe first"); result2.push(chunk); chunk = { parts: [] }; chunkStartIndex = i + 1; continue; } if (selector.capture === i) chunk.capture = i - chunkStartIndex; chunk.parts.push(part); } if (!chunk.parts.length) throw new InvalidSelectorError(`Selector cannot end with entering frame, while parsing selector ${selectorText}`); result2.push(chunk); if (typeof selector.capture === "number" && typeof result2[result2.length - 1].capture !== "number") throw new InvalidSelectorError(`Can not capture the selector before diving into the frame. Only use * after the last frame has been selected`); return result2; } function selectorPartsEqual(list1, list2) { return stringifySelector({ parts: list1 }) === stringifySelector({ parts: list2 }); } function stringifySelector(selector, forceEngineName) { if (typeof selector === "string") return selector; return selector.parts.map((p, i) => { let includeEngine = true; if (!forceEngineName && i !== selector.capture) { if (p.name === "css") includeEngine = false; else if (p.name === "xpath" && p.source.startsWith("//") || p.source.startsWith("..")) includeEngine = false; } const prefix = includeEngine ? p.name + "=" : ""; return `${i === selector.capture ? "*" : ""}${prefix}${p.source}`; }).join(" >> "); } function visitAllSelectorParts(selector, visitor) { const visit = (selector2, nested) => { for (const part of selector2.parts) { visitor(part, nested); if (kNestedSelectorNames.has(part.name)) visit(part.body.parsed, true); } }; visit(selector, false); } function parseSelectorString(selector) { let index = 0; let quote5; let start3 = 0; const result2 = { parts: [] }; const append = () => { const part = selector.substring(start3, index).trim(); const eqIndex = part.indexOf("="); let name; let body; if (eqIndex !== -1 && part.substring(0, eqIndex).trim().match(/^[a-zA-Z_0-9-+:*]+$/)) { name = part.substring(0, eqIndex).trim(); body = part.substring(eqIndex + 1); } else if (part.length > 1 && part[0] === '"' && part[part.length - 1] === '"') { name = "text"; body = part; } else if (part.length > 1 && part[0] === "'" && part[part.length - 1] === "'") { name = "text"; body = part; } else if (/^\(*\/\//.test(part) || part.startsWith("..")) { name = "xpath"; body = part; } else { name = "css"; body = part; } let capture = false; if (name[0] === "*") { capture = true; name = name.substring(1); } result2.parts.push({ name, body }); if (capture) { if (result2.capture !== void 0) throw new InvalidSelectorError(`Only one of the selectors can capture using * modifier`); result2.capture = result2.parts.length - 1; } }; if (!selector.includes(">>")) { index = selector.length; append(); return result2; } const shouldIgnoreTextSelectorQuote = () => { const prefix = selector.substring(start3, index); const match = prefix.match(/^\s*text\s*=(.*)$/); return !!match && !!match[1]; }; while (index < selector.length) { const c = selector[index]; if (c === "\\" && index + 1 < selector.length) { index += 2; } else if (c === quote5) { quote5 = void 0; index++; } else if (!quote5 && (c === '"' || c === "'" || c === "`") && !shouldIgnoreTextSelectorQuote()) { quote5 = c; index++; } else if (!quote5 && c === ">" && selector[index + 1] === ">") { append(); index += 2; start3 = index; } else { index++; } } append(); return result2; } function parseAttributeSelector(selector, allowUnquotedStrings) { let wp = 0; let EOL = selector.length === 0; const next = () => selector[wp] || ""; const eat1 = () => { const result3 = next(); ++wp; EOL = wp >= selector.length; return result3; }; const syntaxError = (stage) => { if (EOL) throw new InvalidSelectorError(`Unexpected end of selector while parsing selector \`${selector}\``); throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - unexpected symbol "${next()}" at position ${wp}` + (stage ? " during " + stage : "")); }; function skipSpaces() { while (!EOL && /\s/.test(next())) eat1(); } function isCSSNameChar(char) { return char >= "\x80" || char >= "0" && char <= "9" || char >= "A" && char <= "Z" || char >= "a" && char <= "z" || char >= "0" && char <= "9" || char === "_" || char === "-"; } function readIdentifier() { let result3 = ""; skipSpaces(); while (!EOL && isCSSNameChar(next())) result3 += eat1(); return result3; } function readQuotedString(quote5) { let result3 = eat1(); if (result3 !== quote5) syntaxError("parsing quoted string"); while (!EOL && next() !== quote5) { if (next() === "\\") eat1(); result3 += eat1(); } if (next() !== quote5) syntaxError("parsing quoted string"); result3 += eat1(); return result3; } function readRegularExpression() { if (eat1() !== "/") syntaxError("parsing regular expression"); let source11 = ""; let inClass = false; while (!EOL) { if (next() === "\\") { source11 += eat1(); if (EOL) syntaxError("parsing regular expression"); } else if (inClass && next() === "]") { inClass = false; } else if (!inClass && next() === "[") { inClass = true; } else if (!inClass && next() === "/") { break; } source11 += eat1(); } if (eat1() !== "/") syntaxError("parsing regular expression"); let flags = ""; while (!EOL && next().match(/[dgimsuy]/)) flags += eat1(); try { return new RegExp(source11, flags); } catch (e) { throw new InvalidSelectorError(`Error while parsing selector \`${selector}\`: ${e.message}`); } } function readAttributeToken() { let token = ""; skipSpaces(); if (next() === `'` || next() === `"`) token = readQuotedString(next()).slice(1, -1); else token = readIdentifier(); if (!token) syntaxError("parsing property path"); return token; } function readOperator() { skipSpaces(); let op = ""; if (!EOL) op += eat1(); if (!EOL && op !== "=") op += eat1(); if (!["=", "*=", "^=", "$=", "|=", "~="].includes(op)) syntaxError("parsing operator"); return op; } function readAttribute() { eat1(); const jsonPath = []; jsonPath.push(readAttributeToken()); skipSpaces(); while (next() === ".") { eat1(); jsonPath.push(readAttributeToken()); skipSpaces(); } if (next() === "]") { eat1(); return { name: jsonPath.join("."), jsonPath, op: "", value: null, caseSensitive: false }; } const operator = readOperator(); let value2 = void 0; let caseSensitive = true; skipSpaces(); if (next() === "/") { if (operator !== "=") throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - cannot use ${operator} in attribute with regular expression`); value2 = readRegularExpression(); } else if (next() === `'` || next() === `"`) { value2 = readQuotedString(next()).slice(1, -1); skipSpaces(); if (next() === "i" || next() === "I") { caseSensitive = false; eat1(); } else if (next() === "s" || next() === "S") { caseSensitive = true; eat1(); } } else { value2 = ""; while (!EOL && (isCSSNameChar(next()) || next() === "+" || next() === ".")) value2 += eat1(); if (value2 === "true") { value2 = true; } else if (value2 === "false") { value2 = false; } else { if (!allowUnquotedStrings) { value2 = +value2; if (Number.isNaN(value2)) syntaxError("parsing attribute value"); } } } skipSpaces(); if (next() !== "]") syntaxError("parsing attribute value"); eat1(); if (operator !== "=" && typeof value2 !== "string") throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - cannot use ${operator} in attribute with non-string matching value - ${value2}`); return { name: jsonPath.join("."), jsonPath, op: operator, value: value2, caseSensitive }; } const result2 = { name: "", attributes: [] }; result2.name = readIdentifier(); skipSpaces(); while (next() === "[") { result2.attributes.push(readAttribute()); skipSpaces(); } if (!EOL) syntaxError(void 0); if (!result2.name && !result2.attributes.length) throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - selector cannot be empty`); return result2; } var kNestedSelectorNames, kNestedSelectorNamesWithDistance, customCSSNames; var init_selectorParser = __esm({ "packages/isomorphic/selectorParser.ts"() { "use strict"; init_cssParser(); init_cssParser(); kNestedSelectorNames = /* @__PURE__ */ new Set(["internal:has", "internal:has-not", "internal:and", "internal:or", "internal:chain", "left-of", "right-of", "above", "below", "near"]); kNestedSelectorNamesWithDistance = /* @__PURE__ */ new Set(["left-of", "right-of", "above", "below", "near"]); customCSSNames = /* @__PURE__ */ new Set(["not", "is", "where", "has", "scope", "light", "visible", "text", "text-matches", "text-is", "has-text", "above", "below", "right-of", "left-of", "near", "nth-match"]); } }); // packages/isomorphic/locatorGenerators.ts function asLocatorDescription(lang, selector) { try { const parsed = parseSelector(selector); const customDescription = parseCustomDescription(parsed); if (customDescription) return customDescription; return innerAsLocators(new generators[lang](), parsed, false, 1)[0]; } catch (e) { return selector; } } function locatorCustomDescription(selector) { try { const parsed = parseSelector(selector); return parseCustomDescription(parsed); } catch (e) { return void 0; } } function parseCustomDescription(parsed) { const lastPart = parsed.parts[parsed.parts.length - 1]; if (lastPart?.name === "internal:describe") { const description = JSON.parse(lastPart.body); if (typeof description === "string") return description; } return void 0; } function asLocator(lang, selector, isFrameLocator = false) { return asLocators(lang, selector, isFrameLocator, 1)[0]; } function asLocators(lang, selector, isFrameLocator = false, maxOutputSize = 20, preferredQuote) { try { return innerAsLocators(new generators[lang](preferredQuote), parseSelector(selector), isFrameLocator, maxOutputSize); } catch (e) { return [selector]; } } function innerAsLocators(factory, parsed, isFrameLocator = false, maxOutputSize = 20) { const parts = [...parsed.parts]; const tokens = []; let nextBase = isFrameLocator ? "frame-locator" : "page"; for (let index = 0; index < parts.length; index++) { const part = parts[index]; const base = nextBase; nextBase = "locator"; if (part.name === "internal:describe") continue; if (part.name === "nth") { if (part.body === "0") tokens.push([factory.generateLocator(base, "first", ""), factory.generateLocator(base, "nth", "0")]); else if (part.body === "-1") tokens.push([factory.generateLocator(base, "last", ""), factory.generateLocator(base, "nth", "-1")]); else tokens.push([factory.generateLocator(base, "nth", part.body)]); continue; } if (part.name === "visible") { tokens.push([factory.generateLocator(base, "visible", part.body), factory.generateLocator(base, "default", `visible=${part.body}`)]); continue; } if (part.name === "internal:text") { const { exact, text: text2 } = detectExact(part.body); tokens.push([factory.generateLocator(base, "text", text2, { exact })]); continue; } if (part.name === "internal:has-text") { const { exact, text: text2 } = detectExact(part.body); if (!exact) { tokens.push([factory.generateLocator(base, "has-text", text2, { exact })]); continue; } } if (part.name === "internal:has-not-text") { const { exact, text: text2 } = detectExact(part.body); if (!exact) { tokens.push([factory.generateLocator(base, "has-not-text", text2, { exact })]); continue; } } if (part.name === "internal:has") { const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize); tokens.push(inners.map((inner) => factory.generateLocator(base, "has", inner))); continue; } if (part.name === "internal:has-not") { const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize); tokens.push(inners.map((inner) => factory.generateLocator(base, "hasNot", inner))); continue; } if (part.name === "internal:and") { const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize); tokens.push(inners.map((inner) => factory.generateLocator(base, "and", inner))); continue; } if (part.name === "internal:or") { const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize); tokens.push(inners.map((inner) => factory.generateLocator(base, "or", inner))); continue; } if (part.name === "internal:chain") { const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize); tokens.push(inners.map((inner) => factory.generateLocator(base, "chain", inner))); continue; } if (part.name === "internal:label") { const { exact, text: text2 } = detectExact(part.body); tokens.push([factory.generateLocator(base, "label", text2, { exact })]); continue; } if (part.name === "internal:role") { const attrSelector = parseAttributeSelector(part.body, true); const options = { attrs: [] }; for (const attr of attrSelector.attributes) { if (attr.name === "name") { if (options.exact !== void 0 && options.exact !== attr.caseSensitive) throw new Error(`Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}`); options.exact = attr.caseSensitive; options.name = attr.value; } else if (attr.name === "description") { if (options.exact !== void 0 && options.exact !== attr.caseSensitive) throw new Error(`Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}`); options.exact = attr.caseSensitive; options.description = attr.value; } else { if (attr.name === "level" && typeof attr.value === "string") attr.value = +attr.value; options.attrs.push({ name: attr.name === "include-hidden" ? "includeHidden" : attr.name, value: attr.value }); } } tokens.push([factory.generateLocator(base, "role", attrSelector.name, options)]); continue; } if (part.name === "internal:testid") { const attrSelector = parseAttributeSelector(part.body, true); const { value: value2 } = attrSelector.attributes[0]; tokens.push([factory.generateLocator(base, "test-id", value2)]); continue; } if (part.name === "internal:attr") { const attrSelector = parseAttributeSelector(part.body, true); const { name, value: value2, caseSensitive } = attrSelector.attributes[0]; const text2 = value2; const exact = !!caseSensitive; if (name === "placeholder") { tokens.push([factory.generateLocator(base, "placeholder", text2, { exact })]); continue; } if (name === "alt") { tokens.push([factory.generateLocator(base, "alt", text2, { exact })]); continue; } if (name === "title") { tokens.push([factory.generateLocator(base, "title", text2, { exact })]); continue; } } if (part.name === "internal:control" && part.body === "enter-frame") { const lastTokens = tokens[tokens.length - 1]; const lastPart = parts[index - 1]; const transformed = lastTokens.map((token) => factory.chainLocators([token, factory.generateLocator(base, "frame", "")])); if (["xpath", "css"].includes(lastPart.name)) { transformed.push( factory.generateLocator(base, "frame-locator", stringifySelector({ parts: [lastPart] })), factory.generateLocator(base, "frame-locator", stringifySelector({ parts: [lastPart] }, true)) ); } lastTokens.splice(0, lastTokens.length, ...transformed); nextBase = "frame-locator"; continue; } const nextPart = parts[index + 1]; const selectorPart = stringifySelector({ parts: [part] }); const locatorPart = factory.generateLocator(base, "default", selectorPart); if (nextPart && ["internal:has-text", "internal:has-not-text"].includes(nextPart.name)) { const { exact, text: text2 } = detectExact(nextPart.body); if (!exact) { const nextLocatorPart = factory.generateLocator("locator", nextPart.name === "internal:has-text" ? "has-text" : "has-not-text", text2, { exact }); const options = {}; if (nextPart.name === "internal:has-text") options.hasText = text2; else options.hasNotText = text2; const combinedPart = factory.generateLocator(base, "default", selectorPart, options); tokens.push([factory.chainLocators([locatorPart, nextLocatorPart]), combinedPart]); index++; continue; } } let locatorPartWithEngine; if (["xpath", "css"].includes(part.name)) { const selectorPart2 = stringifySelector( { parts: [part] }, /* forceEngineName */ true ); locatorPartWithEngine = factory.generateLocator(base, "default", selectorPart2); } tokens.push([locatorPart, locatorPartWithEngine].filter(Boolean)); } return combineTokens(factory, tokens, maxOutputSize); } function combineTokens(factory, tokens, maxOutputSize) { const currentTokens = tokens.map(() => ""); const result2 = []; const visit = (index) => { if (index === tokens.length) { result2.push(factory.chainLocators(currentTokens)); return result2.length < maxOutputSize; } for (const taken of tokens[index]) { currentTokens[index] = taken; if (!visit(index + 1)) return false; } return true; }; visit(0); return result2; } function detectExact(text2) { let exact = false; const match = text2.match(/^\/(.*)\/([igm]*)$/); if (match) return { text: new RegExp(match[1], match[2]) }; if (text2.endsWith('"')) { text2 = JSON.parse(text2); exact = true; } else if (text2.endsWith('"s')) { text2 = JSON.parse(text2.substring(0, text2.length - 1)); exact = true; } else if (text2.endsWith('"i')) { text2 = JSON.parse(text2.substring(0, text2.length - 1)); exact = false; } return { exact, text: text2 }; } function isRegExp2(obj) { return obj instanceof RegExp; } var JavaScriptLocatorFactory, PythonLocatorFactory, JavaLocatorFactory, CSharpLocatorFactory, JsonlLocatorFactory, generators; var init_locatorGenerators = __esm({ "packages/isomorphic/locatorGenerators.ts"() { "use strict"; init_selectorParser(); init_stringUtils(); JavaScriptLocatorFactory = class { constructor(preferredQuote) { this.preferredQuote = preferredQuote; } generateLocator(base, kind, body, options = {}) { switch (kind) { case "default": if (options.hasText !== void 0) return `locator(${this.quote(body)}, { hasText: ${this.toHasText(options.hasText)} })`; if (options.hasNotText !== void 0) return `locator(${this.quote(body)}, { hasNotText: ${this.toHasText(options.hasNotText)} })`; return `locator(${this.quote(body)})`; case "frame-locator": return `frameLocator(${this.quote(body)})`; case "frame": return `contentFrame()`; case "nth": return `nth(${body})`; case "first": return `first()`; case "last": return `last()`; case "visible": return `filter({ visible: ${body === "true" ? "true" : "false"} })`; case "role": const attrs = []; if (isRegExp2(options.name)) attrs.push(`name: ${this.regexToSourceString(options.name)}`); else if (typeof options.name === "string") attrs.push(`name: ${this.quote(options.name)}`); if (isRegExp2(options.description)) attrs.push(`description: ${this.regexToSourceString(options.description)}`); else if (typeof options.description === "string") attrs.push(`description: ${this.quote(options.description)}`); if (options.exact && (typeof options.name === "string" || typeof options.description === "string")) attrs.push(`exact: true`); for (const { name, value: value2 } of options.attrs) attrs.push(`${name}: ${typeof value2 === "string" ? this.quote(value2) : value2}`); const attrString = attrs.length ? `, { ${attrs.join(", ")} }` : ""; return `getByRole(${this.quote(body)}${attrString})`; case "has-text": return `filter({ hasText: ${this.toHasText(body)} })`; case "has-not-text": return `filter({ hasNotText: ${this.toHasText(body)} })`; case "has": return `filter({ has: ${body} })`; case "hasNot": return `filter({ hasNot: ${body} })`; case "and": return `and(${body})`; case "or": return `or(${body})`; case "chain": return `locator(${body})`; case "test-id": return `getByTestId(${this.toTestIdValue(body)})`; case "text": return this.toCallWithExact("getByText", body, !!options.exact); case "alt": return this.toCallWithExact("getByAltText", body, !!options.exact); case "placeholder": return this.toCallWithExact("getByPlaceholder", body, !!options.exact); case "label": return this.toCallWithExact("getByLabel", body, !!options.exact); case "title": return this.toCallWithExact("getByTitle", body, !!options.exact); default: throw new Error("Unknown selector kind " + kind); } } chainLocators(locators) { return locators.join("."); } regexToSourceString(re2) { return normalizeEscapedRegexQuotes(String(re2)); } toCallWithExact(method, body, exact) { if (isRegExp2(body)) return `${method}(${this.regexToSourceString(body)})`; return exact ? `${method}(${this.quote(body)}, { exact: true })` : `${method}(${this.quote(body)})`; } toHasText(body) { if (isRegExp2(body)) return this.regexToSourceString(body); return this.quote(body); } toTestIdValue(value2) { if (isRegExp2(value2)) return this.regexToSourceString(value2); return this.quote(value2); } quote(text2) { return escapeWithQuotes(text2, this.preferredQuote ?? "'"); } }; PythonLocatorFactory = class { generateLocator(base, kind, body, options = {}) { switch (kind) { case "default": if (options.hasText !== void 0) return `locator(${this.quote(body)}, has_text=${this.toHasText(options.hasText)})`; if (options.hasNotText !== void 0) return `locator(${this.quote(body)}, has_not_text=${this.toHasText(options.hasNotText)})`; return `locator(${this.quote(body)})`; case "frame-locator": return `frame_locator(${this.quote(body)})`; case "frame": return `content_frame`; case "nth": return `nth(${body})`; case "first": return `first`; case "last": return `last`; case "visible": return `filter(visible=${body === "true" ? "True" : "False"})`; case "role": const attrs = []; if (isRegExp2(options.name)) attrs.push(`name=${this.regexToString(options.name)}`); else if (typeof options.name === "string") attrs.push(`name=${this.quote(options.name)}`); if (isRegExp2(options.description)) attrs.push(`description=${this.regexToString(options.description)}`); else if (typeof options.description === "string") attrs.push(`description=${this.quote(options.description)}`); if (options.exact && (typeof options.name === "string" || typeof options.description === "string")) attrs.push(`exact=True`); for (const { name, value: value2 } of options.attrs) { let valueString = typeof value2 === "string" ? this.quote(value2) : value2; if (typeof value2 === "boolean") valueString = value2 ? "True" : "False"; attrs.push(`${toSnakeCase(name)}=${valueString}`); } const attrString = attrs.length ? `, ${attrs.join(", ")}` : ""; return `get_by_role(${this.quote(body)}${attrString})`; case "has-text": return `filter(has_text=${this.toHasText(body)})`; case "has-not-text": return `filter(has_not_text=${this.toHasText(body)})`; case "has": return `filter(has=${body})`; case "hasNot": return `filter(has_not=${body})`; case "and": return `and_(${body})`; case "or": return `or_(${body})`; case "chain": return `locator(${body})`; case "test-id": return `get_by_test_id(${this.toTestIdValue(body)})`; case "text": return this.toCallWithExact("get_by_text", body, !!options.exact); case "alt": return this.toCallWithExact("get_by_alt_text", body, !!options.exact); case "placeholder": return this.toCallWithExact("get_by_placeholder", body, !!options.exact); case "label": return this.toCallWithExact("get_by_label", body, !!options.exact); case "title": return this.toCallWithExact("get_by_title", body, !!options.exact); default: throw new Error("Unknown selector kind " + kind); } } chainLocators(locators) { return locators.join("."); } regexToString(body) { const suffix = body.flags.includes("i") ? ", re.IGNORECASE" : ""; return `re.compile(r"${normalizeEscapedRegexQuotes(body.source).replace(/\\\//, "/").replace(/"/g, '\\"')}"${suffix})`; } toCallWithExact(method, body, exact) { if (isRegExp2(body)) return `${method}(${this.regexToString(body)})`; if (exact) return `${method}(${this.quote(body)}, exact=True)`; return `${method}(${this.quote(body)})`; } toHasText(body) { if (isRegExp2(body)) return this.regexToString(body); return `${this.quote(body)}`; } toTestIdValue(value2) { if (isRegExp2(value2)) return this.regexToString(value2); return this.quote(value2); } quote(text2) { return escapeWithQuotes(text2, '"'); } }; JavaLocatorFactory = class { generateLocator(base, kind, body, options = {}) { let clazz; switch (base) { case "page": clazz = "Page"; break; case "frame-locator": clazz = "FrameLocator"; break; case "locator": clazz = "Locator"; break; } switch (kind) { case "default": if (options.hasText !== void 0) return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasText(${this.toHasText(options.hasText)}))`; if (options.hasNotText !== void 0) return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasNotText(${this.toHasText(options.hasNotText)}))`; return `locator(${this.quote(body)})`; case "frame-locator": return `frameLocator(${this.quote(body)})`; case "frame": return `contentFrame()`; case "nth": return `nth(${body})`; case "first": return `first()`; case "last": return `last()`; case "visible": return `filter(new ${clazz}.FilterOptions().setVisible(${body === "true" ? "true" : "false"}))`; case "role": const attrs = []; if (isRegExp2(options.name)) attrs.push(`.setName(${this.regexToString(options.name)})`); else if (typeof options.name === "string") attrs.push(`.setName(${this.quote(options.name)})`); if (isRegExp2(options.description)) attrs.push(`.setDescription(${this.regexToString(options.description)})`); else if (typeof options.description === "string") attrs.push(`.setDescription(${this.quote(options.description)})`); if (options.exact && (typeof options.name === "string" || typeof options.description === "string")) attrs.push(`.setExact(true)`); for (const { name, value: value2 } of options.attrs) attrs.push(`.set${toTitleCase(name)}(${typeof value2 === "string" ? this.quote(value2) : value2})`); const attrString = attrs.length ? `, new ${clazz}.GetByRoleOptions()${attrs.join("")}` : ""; return `getByRole(AriaRole.${toSnakeCase(body).toUpperCase()}${attrString})`; case "has-text": return `filter(new ${clazz}.FilterOptions().setHasText(${this.toHasText(body)}))`; case "has-not-text": return `filter(new ${clazz}.FilterOptions().setHasNotText(${this.toHasText(body)}))`; case "has": return `filter(new ${clazz}.FilterOptions().setHas(${body}))`; case "hasNot": return `filter(new ${clazz}.FilterOptions().setHasNot(${body}))`; case "and": return `and(${body})`; case "or": return `or(${body})`; case "chain": return `locator(${body})`; case "test-id": return `getByTestId(${this.toTestIdValue(body)})`; case "text": return this.toCallWithExact(clazz, "getByText", body, !!options.exact); case "alt": return this.toCallWithExact(clazz, "getByAltText", body, !!options.exact); case "placeholder": return this.toCallWithExact(clazz, "getByPlaceholder", body, !!options.exact); case "label": return this.toCallWithExact(clazz, "getByLabel", body, !!options.exact); case "title": return this.toCallWithExact(clazz, "getByTitle", body, !!options.exact); default: throw new Error("Unknown selector kind " + kind); } } chainLocators(locators) { return locators.join("."); } regexToString(body) { const suffix = body.flags.includes("i") ? ", Pattern.CASE_INSENSITIVE" : ""; return `Pattern.compile(${this.quote(normalizeEscapedRegexQuotes(body.source))}${suffix})`; } toCallWithExact(clazz, method, body, exact) { if (isRegExp2(body)) return `${method}(${this.regexToString(body)})`; if (exact) return `${method}(${this.quote(body)}, new ${clazz}.${toTitleCase(method)}Options().setExact(true))`; return `${method}(${this.quote(body)})`; } toHasText(body) { if (isRegExp2(body)) return this.regexToString(body); return this.quote(body); } toTestIdValue(value2) { if (isRegExp2(value2)) return this.regexToString(value2); return this.quote(value2); } quote(text2) { return escapeWithQuotes(text2, '"'); } }; CSharpLocatorFactory = class { generateLocator(base, kind, body, options = {}) { switch (kind) { case "default": if (options.hasText !== void 0) return `Locator(${this.quote(body)}, new() { ${this.toHasText(options.hasText)} })`; if (options.hasNotText !== void 0) return `Locator(${this.quote(body)}, new() { ${this.toHasNotText(options.hasNotText)} })`; return `Locator(${this.quote(body)})`; case "frame-locator": return `FrameLocator(${this.quote(body)})`; case "frame": return `ContentFrame`; case "nth": return `Nth(${body})`; case "first": return `First`; case "last": return `Last`; case "visible": return `Filter(new() { Visible = ${body === "true" ? "true" : "false"} })`; case "role": const attrs = []; if (isRegExp2(options.name)) attrs.push(`NameRegex = ${this.regexToString(options.name)}`); else if (typeof options.name === "string") attrs.push(`Name = ${this.quote(options.name)}`); if (isRegExp2(options.description)) attrs.push(`DescriptionRegex = ${this.regexToString(options.description)}`); else if (typeof options.description === "string") attrs.push(`Description = ${this.quote(options.description)}`); if (options.exact && (typeof options.name === "string" || typeof options.description === "string")) attrs.push(`Exact = true`); for (const { name, value: value2 } of options.attrs) attrs.push(`${toTitleCase(name)} = ${typeof value2 === "string" ? this.quote(value2) : value2}`); const attrString = attrs.length ? `, new() { ${attrs.join(", ")} }` : ""; return `GetByRole(AriaRole.${toTitleCase(body)}${attrString})`; case "has-text": return `Filter(new() { ${this.toHasText(body)} })`; case "has-not-text": return `Filter(new() { ${this.toHasNotText(body)} })`; case "has": return `Filter(new() { Has = ${body} })`; case "hasNot": return `Filter(new() { HasNot = ${body} })`; case "and": return `And(${body})`; case "or": return `Or(${body})`; case "chain": return `Locator(${body})`; case "test-id": return `GetByTestId(${this.toTestIdValue(body)})`; case "text": return this.toCallWithExact("GetByText", body, !!options.exact); case "alt": return this.toCallWithExact("GetByAltText", body, !!options.exact); case "placeholder": return this.toCallWithExact("GetByPlaceholder", body, !!options.exact); case "label": return this.toCallWithExact("GetByLabel", body, !!options.exact); case "title": return this.toCallWithExact("GetByTitle", body, !!options.exact); default: throw new Error("Unknown selector kind " + kind); } } chainLocators(locators) { return locators.join("."); } regexToString(body) { const suffix = body.flags.includes("i") ? ", RegexOptions.IgnoreCase" : ""; return `new Regex(${this.quote(normalizeEscapedRegexQuotes(body.source))}${suffix})`; } toCallWithExact(method, body, exact) { if (isRegExp2(body)) return `${method}(${this.regexToString(body)})`; if (exact) return `${method}(${this.quote(body)}, new() { Exact = true })`; return `${method}(${this.quote(body)})`; } toHasText(body) { if (isRegExp2(body)) return `HasTextRegex = ${this.regexToString(body)}`; return `HasText = ${this.quote(body)}`; } toTestIdValue(value2) { if (isRegExp2(value2)) return this.regexToString(value2); return this.quote(value2); } toHasNotText(body) { if (isRegExp2(body)) return `HasNotTextRegex = ${this.regexToString(body)}`; return `HasNotText = ${this.quote(body)}`; } quote(text2) { return escapeWithQuotes(text2, '"'); } }; JsonlLocatorFactory = class { generateLocator(base, kind, body, options = {}) { return JSON.stringify({ kind, body, options }); } chainLocators(locators) { const objects = locators.map((l) => JSON.parse(l)); for (let i = 0; i < objects.length - 1; ++i) objects[i].next = objects[i + 1]; return JSON.stringify(objects[0]); } }; generators = { javascript: JavaScriptLocatorFactory, python: PythonLocatorFactory, java: JavaLocatorFactory, csharp: CSharpLocatorFactory, jsonl: JsonlLocatorFactory }; } }); // packages/isomorphic/stackTrace.ts function captureRawStack() { const stackTraceLimit = Error.stackTraceLimit; Error.stackTraceLimit = 50; const error = new Error(); const stack = error.stack || ""; Error.stackTraceLimit = stackTraceLimit; return stack.split("\n"); } function parseStackFrame(text2, pathSeparator, showInternalStackFrames) { const match = text2 && text2.match(re); if (!match) return null; let fname = match[2]; let file = match[7]; if (!file) return null; if (!showInternalStackFrames && (file.startsWith("internal") || file.startsWith("node:"))) return null; const line = match[8]; const column = match[9]; const closeParen = match[11] === ")"; const frame = { file: "", line: 0, column: 0 }; if (line) frame.line = Number(line); if (column) frame.column = Number(column); if (closeParen && file) { let closes = 0; for (let i = file.length - 1; i > 0; i--) { if (file.charAt(i) === ")") { closes++; } else if (file.charAt(i) === "(" && file.charAt(i - 1) === " ") { closes--; if (closes === -1 && file.charAt(i - 1) === " ") { const before = file.slice(0, i - 1); const after = file.slice(i + 1); file = after; fname += ` (${before}`; break; } } } } if (fname) { const methodMatch = fname.match(methodRe); if (methodMatch) fname = methodMatch[1]; } if (file) { if (file.startsWith("file://")) file = fileURLToPath(file, pathSeparator); frame.file = file; } if (fname) frame.function = fname; return frame; } function rewriteErrorMessage(e, newMessage) { const lines = (e.stack?.split("\n") || []).filter((l) => l.startsWith(" at ")); e.message = newMessage; const errorTitle = `${e.name}: ${e.message}`; if (lines.length) e.stack = `${errorTitle} ${lines.join("\n")}`; return e; } function stringifyStackFrames(frames) { const stackLines = []; for (const frame of frames) { if (frame.function) stackLines.push(` at ${frame.function} (${frame.file}:${frame.line}:${frame.column})`); else stackLines.push(` at ${frame.file}:${frame.line}:${frame.column}`); } return stackLines; } function splitErrorMessage(message) { const separationIdx = message.indexOf(":"); return { name: separationIdx !== -1 ? message.slice(0, separationIdx) : "", message: separationIdx !== -1 && separationIdx + 2 <= message.length ? message.substring(separationIdx + 2) : message }; } function parseErrorStack(stack, pathSeparator, showInternalStackFrames = false) { const lines = stack.split("\n"); let firstStackLine = lines.findIndex((line) => line.startsWith(" at ")); if (firstStackLine === -1) firstStackLine = lines.length; const message = lines.slice(0, firstStackLine).join("\n"); const stackLines = lines.slice(firstStackLine); let location2; for (const line of stackLines) { const frame = parseStackFrame(line, pathSeparator, showInternalStackFrames); if (!frame || !frame.file) continue; if (belongsToNodeModules(frame.file, pathSeparator)) continue; location2 = { file: frame.file, column: frame.column || 0, line: frame.line || 0 }; break; } return { message, stackLines, location: location2 }; } function belongsToNodeModules(file, pathSeparator) { return file.includes(`${pathSeparator}node_modules${pathSeparator}`); } function fileURLToPath(fileUrl, pathSeparator) { if (!fileUrl.startsWith("file://")) return fileUrl; let path59 = decodeURIComponent(fileUrl.slice(7)); if (path59.startsWith("/") && /^[a-zA-Z]:/.test(path59.slice(1))) path59 = path59.slice(1); return path59.replace(/\//g, pathSeparator); } var re, methodRe; var init_stackTrace = __esm({ "packages/isomorphic/stackTrace.ts"() { "use strict"; re = new RegExp( "^(?:\\s*at )?(?:(new) )?(?:(.*?) \\()?(?:eval at ([^ ]+) \\((.+?):(\\d+):(\\d+)\\), )?(?:(.+?):(\\d+):(\\d+)|(native))(\\)?)$" ); methodRe = /^(.*?) \[as (.*?)\]$/; } }); // packages/isomorphic/manualPromise.ts function signalToPromise(signal) { if (signal.aborted) return { promise: Promise.resolve(), dispose: () => { } }; let dispose; const promise = new Promise((resolve) => { const onAbort = () => resolve(); signal.addEventListener("abort", onAbort, { once: true }); dispose = () => signal.removeEventListener("abort", onAbort); }); return { promise, dispose }; } function cloneError(error, frames) { const clone = new Error(); clone.name = error.name; clone.message = error.message; clone.stack = [error.name + ":" + error.message, ...frames].join("\n"); return clone; } var ManualPromise, LongStandingScope; var init_manualPromise = __esm({ "packages/isomorphic/manualPromise.ts"() { "use strict"; init_stackTrace(); ManualPromise = class extends Promise { constructor() { let resolve; let reject; super((f, r) => { resolve = f; reject = r; }); this._isDone = false; this._resolve = resolve; this._reject = reject; } isDone() { return this._isDone; } resolve(t) { this._isDone = true; this._resolve(t); } reject(e) { this._isDone = true; this._reject(e); } static get [Symbol.species]() { return Promise; } get [Symbol.toStringTag]() { return "ManualPromise"; } }; LongStandingScope = class { constructor() { this._terminatePromises = /* @__PURE__ */ new Map(); this._isClosed = false; } reject(error) { this._isClosed = true; this._terminateError = error; for (const p of this._terminatePromises.keys()) p.resolve(error); } close(error) { this._isClosed = true; this._closeError = error; for (const [p, frames] of this._terminatePromises) p.resolve(cloneError(error, frames)); } isClosed() { return this._isClosed; } static async raceMultiple(scopes, promise) { return Promise.race(scopes.map((s) => s.race(promise))); } async race(promise) { return this._race(Array.isArray(promise) ? promise : [promise], false); } async safeRace(promise, defaultValue) { return this._race([promise], true, defaultValue); } async _race(promises, safe, defaultValue) { const terminatePromise = new ManualPromise(); const frames = captureRawStack(); if (this._terminateError) terminatePromise.resolve(this._terminateError); if (this._closeError) terminatePromise.resolve(cloneError(this._closeError, frames)); this._terminatePromises.set(terminatePromise, frames); try { return await Promise.race([ terminatePromise.then((e) => safe ? defaultValue : Promise.reject(e)), ...promises ]); } finally { this._terminatePromises.delete(terminatePromise); } } }; } }); // packages/isomorphic/mimeType.ts function isJsonMimeType(mimeType) { return !!mimeType.match(/^(application\/json|application\/.*?\+json|text\/(x-)?json)(;\s*charset=.*)?$/); } function isXmlMimeType(mimeType) { return !!mimeType.match(/^(application\/xml|application\/.*?\+xml|text\/xml)(;\s*charset=.*)?$/); } function isTextualMimeType(mimeType) { return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/); } function getMimeTypeForPath(path59) { const dotIndex = path59.lastIndexOf("."); if (dotIndex === -1) return null; const extension = path59.substring(dotIndex + 1); return types.get(extension) || null; } function getExtensionForMimeType(contentType) { const subtype = (contentType ?? "").split(";")[0].split("/")[1]?.trim().toLowerCase() ?? ""; if (!subtype) return "bin"; const tail = subtype.includes("+") ? subtype.split("+").pop() : subtype; if (tail === "plain") return "txt"; if (tail === "javascript" || tail === "ecmascript") return "js"; if (tail === "jpeg") return "jpg"; return tail.replace(/[^a-z0-9]/g, "") || "bin"; } var types; var init_mimeType = __esm({ "packages/isomorphic/mimeType.ts"() { "use strict"; types = /* @__PURE__ */ new Map([ ["ez", "application/andrew-inset"], ["aw", "application/applixware"], ["atom", "application/atom+xml"], ["atomcat", "application/atomcat+xml"], ["atomdeleted", "application/atomdeleted+xml"], ["atomsvc", "application/atomsvc+xml"], ["dwd", "application/atsc-dwd+xml"], ["held", "application/atsc-held+xml"], ["rsat", "application/atsc-rsat+xml"], ["bdoc", "application/bdoc"], ["xcs", "application/calendar+xml"], ["ccxml", "application/ccxml+xml"], ["cdfx", "application/cdfx+xml"], ["cdmia", "application/cdmi-capability"], ["cdmic", "application/cdmi-container"], ["cdmid", "application/cdmi-domain"], ["cdmio", "application/cdmi-object"], ["cdmiq", "application/cdmi-queue"], ["cu", "application/cu-seeme"], ["mpd", "application/dash+xml"], ["davmount", "application/davmount+xml"], ["dbk", "application/docbook+xml"], ["dssc", "application/dssc+der"], ["xdssc", "application/dssc+xml"], ["ecma", "application/ecmascript"], ["es", "application/ecmascript"], ["emma", "application/emma+xml"], ["emotionml", "application/emotionml+xml"], ["epub", "application/epub+zip"], ["exi", "application/exi"], ["exp", "application/express"], ["fdt", "application/fdt+xml"], ["pfr", "application/font-tdpfr"], ["geojson", "application/geo+json"], ["gml", "application/gml+xml"], ["gpx", "application/gpx+xml"], ["gxf", "application/gxf"], ["gz", "application/gzip"], ["hjson", "application/hjson"], ["stk", "application/hyperstudio"], ["ink", "application/inkml+xml"], ["inkml", "application/inkml+xml"], ["ipfix", "application/ipfix"], ["its", "application/its+xml"], ["ear", "application/java-archive"], ["jar", "application/java-archive"], ["war", "application/java-archive"], ["ser", "application/java-serialized-object"], ["class", "application/java-vm"], ["js", "application/javascript"], ["mjs", "application/javascript"], ["json", "application/json"], ["map", "application/json"], ["json5", "application/json5"], ["jsonml", "application/jsonml+json"], ["jsonld", "application/ld+json"], ["lgr", "application/lgr+xml"], ["lostxml", "application/lost+xml"], ["hqx", "application/mac-binhex40"], ["cpt", "application/mac-compactpro"], ["mads", "application/mads+xml"], ["webmanifest", "application/manifest+json"], ["mrc", "application/marc"], ["mrcx", "application/marcxml+xml"], ["ma", "application/mathematica"], ["mb", "application/mathematica"], ["nb", "application/mathematica"], ["mathml", "application/mathml+xml"], ["mbox", "application/mbox"], ["mscml", "application/mediaservercontrol+xml"], ["metalink", "application/metalink+xml"], ["meta4", "application/metalink4+xml"], ["mets", "application/mets+xml"], ["maei", "application/mmt-aei+xml"], ["musd", "application/mmt-usd+xml"], ["mods", "application/mods+xml"], ["m21", "application/mp21"], ["mp21", "application/mp21"], ["m4p", "application/mp4"], ["mp4s", "application/mp4"], ["doc", "application/msword"], ["dot", "application/msword"], ["mxf", "application/mxf"], ["nq", "application/n-quads"], ["nt", "application/n-triples"], ["cjs", "application/node"], ["bin", "application/octet-stream"], ["bpk", "application/octet-stream"], ["buffer", "application/octet-stream"], ["deb", "application/octet-stream"], ["deploy", "application/octet-stream"], ["dist", "application/octet-stream"], ["distz", "application/octet-stream"], ["dll", "application/octet-stream"], ["dmg", "application/octet-stream"], ["dms", "application/octet-stream"], ["dump", "application/octet-stream"], ["elc", "application/octet-stream"], ["exe", "application/octet-stream"], ["img", "application/octet-stream"], ["iso", "application/octet-stream"], ["lrf", "application/octet-stream"], ["mar", "application/octet-stream"], ["msi", "application/octet-stream"], ["msm", "application/octet-stream"], ["msp", "application/octet-stream"], ["pkg", "application/octet-stream"], ["so", "application/octet-stream"], ["oda", "application/oda"], ["opf", "application/oebps-package+xml"], ["ogx", "application/ogg"], ["omdoc", "application/omdoc+xml"], ["onepkg", "application/onenote"], ["onetmp", "application/onenote"], ["onetoc", "application/onenote"], ["onetoc2", "application/onenote"], ["oxps", "application/oxps"], ["relo", "application/p2p-overlay+xml"], ["xer", "application/patch-ops-error+xml"], ["pdf", "application/pdf"], ["pgp", "application/pgp-encrypted"], ["asc", "application/pgp-signature"], ["sig", "application/pgp-signature"], ["prf", "application/pics-rules"], ["p10", "application/pkcs10"], ["p7c", "application/pkcs7-mime"], ["p7m", "application/pkcs7-mime"], ["p7s", "application/pkcs7-signature"], ["p8", "application/pkcs8"], ["ac", "application/pkix-attr-cert"], ["cer", "application/pkix-cert"], ["crl", "application/pkix-crl"], ["pkipath", "application/pkix-pkipath"], ["pki", "application/pkixcmp"], ["pls", "application/pls+xml"], ["ai", "application/postscript"], ["eps", "application/postscript"], ["ps", "application/postscript"], ["provx", "application/provenance+xml"], ["pskcxml", "application/pskc+xml"], ["raml", "application/raml+yaml"], ["owl", "application/rdf+xml"], ["rdf", "application/rdf+xml"], ["rif", "application/reginfo+xml"], ["rnc", "application/relax-ng-compact-syntax"], ["rl", "application/resource-lists+xml"], ["rld", "application/resource-lists-diff+xml"], ["rs", "application/rls-services+xml"], ["rapd", "application/route-apd+xml"], ["sls", "application/route-s-tsid+xml"], ["rusd", "application/route-usd+xml"], ["gbr", "application/rpki-ghostbusters"], ["mft", "application/rpki-manifest"], ["roa", "application/rpki-roa"], ["rsd", "application/rsd+xml"], ["rss", "application/rss+xml"], ["rtf", "application/rtf"], ["sbml", "application/sbml+xml"], ["scq", "application/scvp-cv-request"], ["scs", "application/scvp-cv-response"], ["spq", "application/scvp-vp-request"], ["spp", "application/scvp-vp-response"], ["sdp", "application/sdp"], ["senmlx", "application/senml+xml"], ["sensmlx", "application/sensml+xml"], ["setpay", "application/set-payment-initiation"], ["setreg", "application/set-registration-initiation"], ["shf", "application/shf+xml"], ["sieve", "application/sieve"], ["siv", "application/sieve"], ["smi", "application/smil+xml"], ["smil", "application/smil+xml"], ["rq", "application/sparql-query"], ["srx", "application/sparql-results+xml"], ["gram", "application/srgs"], ["grxml", "application/srgs+xml"], ["sru", "application/sru+xml"], ["ssdl", "application/ssdl+xml"], ["ssml", "application/ssml+xml"], ["swidtag", "application/swid+xml"], ["tei", "application/tei+xml"], ["teicorpus", "application/tei+xml"], ["tfi", "application/thraud+xml"], ["tsd", "application/timestamped-data"], ["toml", "application/toml"], ["trig", "application/trig"], ["ttml", "application/ttml+xml"], ["ubj", "application/ubjson"], ["rsheet", "application/urc-ressheet+xml"], ["td", "application/urc-targetdesc+xml"], ["vxml", "application/voicexml+xml"], ["wasm", "application/wasm"], ["wgt", "application/widget"], ["hlp", "application/winhlp"], ["wsdl", "application/wsdl+xml"], ["wspolicy", "application/wspolicy+xml"], ["xaml", "application/xaml+xml"], ["xav", "application/xcap-att+xml"], ["xca", "application/xcap-caps+xml"], ["xdf", "application/xcap-diff+xml"], ["xel", "application/xcap-el+xml"], ["xns", "application/xcap-ns+xml"], ["xenc", "application/xenc+xml"], ["xht", "application/xhtml+xml"], ["xhtml", "application/xhtml+xml"], ["xlf", "application/xliff+xml"], ["rng", "application/xml"], ["xml", "application/xml"], ["xsd", "application/xml"], ["xsl", "application/xml"], ["dtd", "application/xml-dtd"], ["xop", "application/xop+xml"], ["xpl", "application/xproc+xml"], ["*xsl", "application/xslt+xml"], ["xslt", "application/xslt+xml"], ["xspf", "application/xspf+xml"], ["mxml", "application/xv+xml"], ["xhvml", "application/xv+xml"], ["xvm", "application/xv+xml"], ["xvml", "application/xv+xml"], ["yang", "application/yang"], ["yin", "application/yin+xml"], ["zip", "application/zip"], ["*3gpp", "audio/3gpp"], ["adp", "audio/adpcm"], ["amr", "audio/amr"], ["au", "audio/basic"], ["snd", "audio/basic"], ["kar", "audio/midi"], ["mid", "audio/midi"], ["midi", "audio/midi"], ["rmi", "audio/midi"], ["mxmf", "audio/mobile-xmf"], ["*mp3", "audio/mp3"], ["m4a", "audio/mp4"], ["mp4a", "audio/mp4"], ["m2a", "audio/mpeg"], ["m3a", "audio/mpeg"], ["mp2", "audio/mpeg"], ["mp2a", "audio/mpeg"], ["mp3", "audio/mpeg"], ["mpga", "audio/mpeg"], ["oga", "audio/ogg"], ["ogg", "audio/ogg"], ["opus", "audio/ogg"], ["spx", "audio/ogg"], ["s3m", "audio/s3m"], ["sil", "audio/silk"], ["wav", "audio/wav"], ["*wav", "audio/wave"], ["weba", "audio/webm"], ["xm", "audio/xm"], ["ttc", "font/collection"], ["otf", "font/otf"], ["ttf", "font/ttf"], ["woff", "font/woff"], ["woff2", "font/woff2"], ["exr", "image/aces"], ["apng", "image/apng"], ["avif", "image/avif"], ["bmp", "image/bmp"], ["cgm", "image/cgm"], ["drle", "image/dicom-rle"], ["emf", "image/emf"], ["fits", "image/fits"], ["g3", "image/g3fax"], ["gif", "image/gif"], ["heic", "image/heic"], ["heics", "image/heic-sequence"], ["heif", "image/heif"], ["heifs", "image/heif-sequence"], ["hej2", "image/hej2k"], ["hsj2", "image/hsj2"], ["ief", "image/ief"], ["jls", "image/jls"], ["jp2", "image/jp2"], ["jpg2", "image/jp2"], ["jpe", "image/jpeg"], ["jpeg", "image/jpeg"], ["jpg", "image/jpeg"], ["jph", "image/jph"], ["jhc", "image/jphc"], ["jpm", "image/jpm"], ["jpf", "image/jpx"], ["jpx", "image/jpx"], ["jxr", "image/jxr"], ["jxra", "image/jxra"], ["jxrs", "image/jxrs"], ["jxs", "image/jxs"], ["jxsc", "image/jxsc"], ["jxsi", "image/jxsi"], ["jxss", "image/jxss"], ["ktx", "image/ktx"], ["ktx2", "image/ktx2"], ["png", "image/png"], ["sgi", "image/sgi"], ["svg", "image/svg+xml"], ["svgz", "image/svg+xml"], ["t38", "image/t38"], ["tif", "image/tiff"], ["tiff", "image/tiff"], ["tfx", "image/tiff-fx"], ["webp", "image/webp"], ["wmf", "image/wmf"], ["disposition-notification", "message/disposition-notification"], ["u8msg", "message/global"], ["u8dsn", "message/global-delivery-status"], ["u8mdn", "message/global-disposition-notification"], ["u8hdr", "message/global-headers"], ["eml", "message/rfc822"], ["mime", "message/rfc822"], ["3mf", "model/3mf"], ["gltf", "model/gltf+json"], ["glb", "model/gltf-binary"], ["iges", "model/iges"], ["igs", "model/iges"], ["mesh", "model/mesh"], ["msh", "model/mesh"], ["silo", "model/mesh"], ["mtl", "model/mtl"], ["obj", "model/obj"], ["stpx", "model/step+xml"], ["stpz", "model/step+zip"], ["stpxz", "model/step-xml+zip"], ["stl", "model/stl"], ["vrml", "model/vrml"], ["wrl", "model/vrml"], ["*x3db", "model/x3d+binary"], ["x3dbz", "model/x3d+binary"], ["x3db", "model/x3d+fastinfoset"], ["*x3dv", "model/x3d+vrml"], ["x3dvz", "model/x3d+vrml"], ["x3d", "model/x3d+xml"], ["x3dz", "model/x3d+xml"], ["x3dv", "model/x3d-vrml"], ["appcache", "text/cache-manifest"], ["manifest", "text/cache-manifest"], ["ics", "text/calendar"], ["ifb", "text/calendar"], ["coffee", "text/coffeescript"], ["litcoffee", "text/coffeescript"], ["css", "text/css"], ["csv", "text/csv"], ["htm", "text/html"], ["html", "text/html"], ["shtml", "text/html"], ["jade", "text/jade"], ["jsx", "text/jsx"], ["less", "text/less"], ["markdown", "text/markdown"], ["md", "text/markdown"], ["mml", "text/mathml"], ["mdx", "text/mdx"], ["n3", "text/n3"], ["conf", "text/plain"], ["def", "text/plain"], ["in", "text/plain"], ["ini", "text/plain"], ["list", "text/plain"], ["log", "text/plain"], ["text", "text/plain"], ["txt", "text/plain"], ["rtx", "text/richtext"], ["*rtf", "text/rtf"], ["sgm", "text/sgml"], ["sgml", "text/sgml"], ["shex", "text/shex"], ["slim", "text/slim"], ["slm", "text/slim"], ["spdx", "text/spdx"], ["styl", "text/stylus"], ["stylus", "text/stylus"], ["tsv", "text/tab-separated-values"], ["man", "text/troff"], ["me", "text/troff"], ["ms", "text/troff"], ["roff", "text/troff"], ["t", "text/troff"], ["tr", "text/troff"], ["ttl", "text/turtle"], ["uri", "text/uri-list"], ["uris", "text/uri-list"], ["urls", "text/uri-list"], ["vcard", "text/vcard"], ["vtt", "text/vtt"], ["*xml", "text/xml"], ["yaml", "text/yaml"], ["yml", "text/yaml"], ["3gp", "video/3gpp"], ["3gpp", "video/3gpp"], ["3g2", "video/3gpp2"], ["h261", "video/h261"], ["h263", "video/h263"], ["h264", "video/h264"], ["m4s", "video/iso.segment"], ["jpgv", "video/jpeg"], ["jpm", "video/jpm"], ["jpgm", "video/jpm"], ["mj2", "video/mj2"], ["mjp2", "video/mj2"], ["ts", "application/typescript"], ["mp4", "video/mp4"], ["mp4v", "video/mp4"], ["mpg4", "video/mp4"], ["m1v", "video/mpeg"], ["m2v", "video/mpeg"], ["mpe", "video/mpeg"], ["mpeg", "video/mpeg"], ["mpg", "video/mpeg"], ["ogv", "video/ogg"], ["mov", "video/quicktime"], ["qt", "video/quicktime"], ["webm", "video/webm"] ]); } }); // packages/isomorphic/multimap.ts var MultiMap; var init_multimap = __esm({ "packages/isomorphic/multimap.ts"() { "use strict"; MultiMap = class { constructor() { this._map = /* @__PURE__ */ new Map(); } set(key, value2) { let values = this._map.get(key); if (!values) { values = []; this._map.set(key, values); } values.push(value2); } get(key) { return this._map.get(key) || []; } has(key) { return this._map.has(key); } delete(key, value2) { const values = this._map.get(key); if (!values) return; if (values.includes(value2)) this._map.set(key, values.filter((v) => value2 !== v)); } deleteAll(key) { this._map.delete(key); } hasValue(key, value2) { const values = this._map.get(key); if (!values) return false; return values.includes(value2); } get size() { return this._map.size; } [Symbol.iterator]() { return this._map[Symbol.iterator](); } keys() { return this._map.keys(); } values() { const result2 = []; for (const key of this.keys()) result2.push(...this.get(key)); return result2; } clear() { this._map.clear(); } }; } }); // packages/isomorphic/protocolMetainfo.ts function getMetainfo(metadata) { return methodMetainfo.get(metadata.type + "." + metadata.method); } var methodMetainfo; var init_protocolMetainfo = __esm({ "packages/isomorphic/protocolMetainfo.ts"() { "use strict"; methodMetainfo = /* @__PURE__ */ new Map([ ["Android.devices", { internal: true }], ["AndroidSocket.write", { internal: true }], ["AndroidSocket.close", { internal: true }], ["AndroidDevice.wait", { title: "Wait" }], ["AndroidDevice.fill", { title: 'Fill "{text}"' }], ["AndroidDevice.tap", { title: "Tap" }], ["AndroidDevice.drag", { title: "Drag" }], ["AndroidDevice.fling", { title: "Fling" }], ["AndroidDevice.longTap", { title: "Long tap" }], ["AndroidDevice.pinchClose", { title: "Pinch close" }], ["AndroidDevice.pinchOpen", { title: "Pinch open" }], ["AndroidDevice.scroll", { title: "Scroll" }], ["AndroidDevice.swipe", { title: "Swipe" }], ["AndroidDevice.info", { internal: true }], ["AndroidDevice.screenshot", { title: "Screenshot" }], ["AndroidDevice.inputType", { title: "Type" }], ["AndroidDevice.inputPress", { title: "Press" }], ["AndroidDevice.inputTap", { title: "Tap" }], ["AndroidDevice.inputSwipe", { title: "Swipe" }], ["AndroidDevice.inputDrag", { title: "Drag" }], ["AndroidDevice.launchBrowser", { title: "Launch browser" }], ["AndroidDevice.open", { title: "Open app" }], ["AndroidDevice.shell", { title: "Execute shell command", group: "configuration" }], ["AndroidDevice.installApk", { title: "Install apk" }], ["AndroidDevice.push", { title: "Push" }], ["AndroidDevice.connectToWebView", { title: "Connect to Web View" }], ["AndroidDevice.close", { internal: true }], ["APIRequestContext.fetch", { title: '{method} "{url}"' }], ["APIRequestContext.fetchResponseBody", { title: "Get response body", group: "getter" }], ["APIRequestContext.fetchLog", { internal: true }], ["APIRequestContext.storageState", { title: "Get storage state", group: "configuration" }], ["APIRequestContext.disposeAPIResponse", { internal: true }], ["APIRequestContext.dispose", { internal: true, potentiallyClosesScope: true }], ["Artifact.pathAfterFinished", { internal: true }], ["Artifact.saveAs", { internal: true }], ["Artifact.saveAsStream", { internal: true }], ["Artifact.failure", { internal: true }], ["Artifact.stream", { internal: true }], ["Artifact.cancel", { internal: true }], ["Artifact.delete", { internal: true, potentiallyClosesScope: true }], ["Stream.read", { internal: true }], ["Stream.close", { internal: true }], ["WritableStream.write", { internal: true }], ["WritableStream.close", { internal: true }], ["Browser.startServer", { title: "Start server" }], ["Browser.stopServer", { title: "Stop server" }], ["Browser.close", { title: "Close browser", pause: true, potentiallyClosesScope: true }], ["Browser.killForTests", { internal: true, potentiallyClosesScope: true }], ["Browser.defaultUserAgentForTest", { internal: true }], ["Browser.newContext", { title: "Create context" }], ["Browser.newContextForReuse", { internal: true }], ["Browser.disconnectFromReusedContext", { internal: true }], ["Browser.newBrowserCDPSession", { title: "Create CDP session", group: "configuration" }], ["Browser.startTracing", { title: "Start browser tracing", group: "configuration" }], ["Browser.stopTracing", { title: "Stop browser tracing", group: "configuration" }], ["BrowserContext.addCookies", { title: "Add cookies", group: "configuration" }], ["BrowserContext.addInitScript", { title: "Add init script", group: "configuration" }], ["BrowserContext.clearCookies", { title: "Clear cookies", group: "configuration" }], ["BrowserContext.clearPermissions", { title: "Clear permissions", group: "configuration" }], ["BrowserContext.close", { title: "Close context", pause: true, potentiallyClosesScope: true }], ["BrowserContext.cookies", { title: "Get cookies", group: "getter" }], ["BrowserContext.exposeBinding", { title: "Expose binding", group: "configuration" }], ["BrowserContext.grantPermissions", { title: "Grant permissions", group: "configuration" }], ["BrowserContext.newPage", { title: "Create page" }], ["BrowserContext.registerSelectorEngine", { internal: true }], ["BrowserContext.setTestIdAttributeName", { internal: true }], ["BrowserContext.setExtraHTTPHeaders", { title: "Set extra HTTP headers", group: "configuration" }], ["BrowserContext.setGeolocation", { title: "Set geolocation", group: "configuration" }], ["BrowserContext.setHTTPCredentials", { title: "Set HTTP credentials", group: "configuration" }], ["BrowserContext.setNetworkInterceptionPatterns", { title: "Route requests", group: "route" }], ["BrowserContext.setWebSocketInterceptionPatterns", { title: "Route WebSockets", group: "route" }], ["BrowserContext.setOffline", { title: "Set offline mode" }], ["BrowserContext.storageState", { title: "Get storage state", group: "configuration" }], ["BrowserContext.setStorageState", { title: "Set storage state", group: "configuration" }], ["BrowserContext.pause", { title: "Pause" }], ["BrowserContext.enableRecorder", { internal: true }], ["BrowserContext.disableRecorder", { internal: true }], ["BrowserContext.exposeConsoleApi", { internal: true }], ["BrowserContext.newCDPSession", { title: "Create CDP session", group: "configuration" }], ["BrowserContext.createTempFiles", { internal: true }], ["BrowserContext.updateSubscription", { internal: true }], ["BrowserContext.clockFastForward", { title: 'Fast forward clock "{ticksNumber|ticksString}"' }], ["BrowserContext.clockInstall", { title: 'Install clock "{timeNumber|timeString}"' }], ["BrowserContext.clockPauseAt", { title: 'Pause clock "{timeNumber|timeString}"' }], ["BrowserContext.clockResume", { title: "Resume clock" }], ["BrowserContext.clockRunFor", { title: 'Run clock "{ticksNumber|ticksString}"' }], ["BrowserContext.clockSetFixedTime", { title: 'Set fixed time "{timeNumber|timeString}"' }], ["BrowserContext.clockSetSystemTime", { title: 'Set system time "{timeNumber|timeString}"' }], ["BrowserContext.credentialsInstall", { title: "Install virtual WebAuthn authenticator", group: "configuration" }], ["BrowserContext.credentialsCreate", { title: 'Create virtual credential for "{rpId}"', group: "configuration" }], ["BrowserContext.credentialsGet", { title: "Get virtual credentials", group: "configuration" }], ["BrowserContext.credentialsDelete", { title: "Delete virtual credential", group: "configuration" }], ["BrowserType.launch", { title: "Launch browser" }], ["BrowserType.launchPersistentContext", { title: "Launch persistent context" }], ["BrowserType.connectOverCDP", { title: "Connect over CDP" }], ["BrowserType.connectToWorker", { title: "Connect to worker" }], ["Disposable.dispose", { internal: true, potentiallyClosesScope: true }], ["Electron.launch", { title: "Launch electron" }], ["ElectronApplication.browserWindow", { internal: true }], ["ElectronApplication.evaluateExpression", { title: "Evaluate" }], ["ElectronApplication.evaluateExpressionHandle", { title: "Evaluate" }], ["ElectronApplication.updateSubscription", { internal: true }], ["Frame.evalOnSelector", { title: "Evaluate", snapshot: true, pause: true }], ["Frame.evalOnSelectorAll", { title: "Evaluate", snapshot: true, pause: true }], ["Frame.addScriptTag", { title: "Add script tag", snapshot: true, pause: true }], ["Frame.addStyleTag", { title: "Add style tag", snapshot: true, pause: true }], ["Frame.ariaSnapshot", { title: "Aria snapshot", group: "getter" }], ["Frame.blur", { title: "Blur", slowMo: true, snapshot: true, pause: true }], ["Frame.check", { title: "Check", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.click", { title: "Click", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true, potentiallyClosesScope: true }], ["Frame.content", { title: "Get content", snapshot: true, pause: true }], ["Frame.dragAndDrop", { title: "Drag and drop", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.drop", { title: "Drop files or data onto an element", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.dblclick", { title: "Double click", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.dispatchEvent", { title: 'Dispatch "{type}"', slowMo: true, snapshot: true, pause: true }], ["Frame.evaluateExpression", { title: "Evaluate", snapshot: true, pause: true }], ["Frame.evaluateExpressionHandle", { title: "Evaluate", snapshot: true, pause: true }], ["Frame.fill", { title: 'Fill "{value}"', slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.focus", { title: "Focus", slowMo: true, snapshot: true, pause: true }], ["Frame.frameElement", { title: "Get frame element", group: "getter" }], ["Frame.resolveSelector", { internal: true }], ["Frame.highlight", { internal: true }], ["Frame.hideHighlight", { internal: true }], ["Frame.getAttribute", { title: 'Get attribute "{name}"', snapshot: true, pause: true, group: "getter" }], ["Frame.goto", { title: 'Navigate to "{url}"', slowMo: true, snapshot: true, pause: true }], ["Frame.hover", { title: "Hover", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.innerHTML", { title: "Get HTML", snapshot: true, pause: true, group: "getter" }], ["Frame.innerText", { title: "Get inner text", snapshot: true, pause: true, group: "getter" }], ["Frame.inputValue", { title: "Get input value", snapshot: true, pause: true, group: "getter" }], ["Frame.isChecked", { title: "Is checked", snapshot: true, pause: true, group: "getter" }], ["Frame.isDisabled", { title: "Is disabled", snapshot: true, pause: true, group: "getter" }], ["Frame.isEnabled", { title: "Is enabled", snapshot: true, pause: true, group: "getter" }], ["Frame.isHidden", { title: "Is hidden", snapshot: true, pause: true, group: "getter" }], ["Frame.isVisible", { title: "Is visible", snapshot: true, pause: true, group: "getter" }], ["Frame.isEditable", { title: "Is editable", snapshot: true, pause: true, group: "getter" }], ["Frame.press", { title: 'Press "{key}"', slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.querySelector", { title: "Query selector", snapshot: true }], ["Frame.querySelectorAll", { title: "Query selector all", snapshot: true }], ["Frame.queryCount", { title: "Query count", snapshot: true, pause: true }], ["Frame.selectOption", { title: "Select option", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.setContent", { title: "Set content", snapshot: true, pause: true }], ["Frame.setInputFiles", { title: "Set input files", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.tap", { title: "Tap", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.textContent", { title: "Get text content", snapshot: true, pause: true, group: "getter" }], ["Frame.title", { title: "Get page title", group: "getter" }], ["Frame.type", { title: 'Type "{text}"', slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.uncheck", { title: "Uncheck", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["Frame.waitForTimeout", { title: "Wait for timeout", snapshot: true }], ["Frame.waitForFunction", { title: "Wait for function", snapshot: true, pause: true }], ["Frame.waitForSelector", { title: "Wait for selector", snapshot: true }], ["Frame.expect", { title: 'Expect "{expression}"', snapshot: true, pause: true }], ["JSHandle.dispose", { internal: true, potentiallyClosesScope: true }], ["ElementHandle.dispose", { internal: true, potentiallyClosesScope: true }], ["JSHandle.evaluateExpression", { title: "Evaluate", snapshot: true, pause: true }], ["ElementHandle.evaluateExpression", { title: "Evaluate", snapshot: true, pause: true }], ["JSHandle.evaluateExpressionHandle", { title: "Evaluate", snapshot: true, pause: true }], ["ElementHandle.evaluateExpressionHandle", { title: "Evaluate", snapshot: true, pause: true }], ["JSHandle.getPropertyList", { title: "Get property list", group: "getter" }], ["ElementHandle.getPropertyList", { title: "Get property list", group: "getter" }], ["JSHandle.getProperty", { title: "Get JS property", group: "getter" }], ["ElementHandle.getProperty", { title: "Get JS property", group: "getter" }], ["JSHandle.jsonValue", { title: "Get JSON value", group: "getter" }], ["ElementHandle.jsonValue", { title: "Get JSON value", group: "getter" }], ["ElementHandle.evalOnSelector", { title: "Evaluate", snapshot: true, pause: true }], ["ElementHandle.evalOnSelectorAll", { title: "Evaluate", snapshot: true, pause: true }], ["ElementHandle.boundingBox", { title: "Get bounding box", snapshot: true, pause: true }], ["ElementHandle.check", { title: "Check", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.click", { title: "Click", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.contentFrame", { title: "Get content frame", group: "getter" }], ["ElementHandle.dblclick", { title: "Double click", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.dispatchEvent", { title: "Dispatch event", slowMo: true, snapshot: true, pause: true }], ["ElementHandle.fill", { title: 'Fill "{value}"', slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.focus", { title: "Focus", slowMo: true, snapshot: true, pause: true }], ["ElementHandle.getAttribute", { title: "Get attribute", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.hover", { title: "Hover", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.innerHTML", { title: "Get HTML", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.innerText", { title: "Get inner text", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.inputValue", { title: "Get input value", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.isChecked", { title: "Is checked", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.isDisabled", { title: "Is disabled", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.isEditable", { title: "Is editable", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.isEnabled", { title: "Is enabled", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.isHidden", { title: "Is hidden", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.isVisible", { title: "Is visible", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.ownerFrame", { title: "Get owner frame", group: "getter" }], ["ElementHandle.press", { title: 'Press "{key}"', slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.querySelector", { title: "Query selector", snapshot: true }], ["ElementHandle.querySelectorAll", { title: "Query selector all", snapshot: true }], ["ElementHandle.screenshot", { title: "Screenshot", snapshot: true, pause: true }], ["ElementHandle.scrollIntoViewIfNeeded", { title: "Scroll into view", slowMo: true, snapshot: true, pause: true }], ["ElementHandle.selectOption", { title: "Select option", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.selectText", { title: "Select text", slowMo: true, snapshot: true, pause: true }], ["ElementHandle.setInputFiles", { title: "Set input files", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.tap", { title: "Tap", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.textContent", { title: "Get text content", snapshot: true, pause: true, group: "getter" }], ["ElementHandle.type", { title: "Type", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.uncheck", { title: "Uncheck", slowMo: true, snapshot: true, pause: true, input: true, isAutoWaiting: true }], ["ElementHandle.waitForElementState", { title: "Wait for state", snapshot: true, pause: true }], ["ElementHandle.waitForSelector", { title: "Wait for selector", snapshot: true }], ["LocalUtils.zip", { internal: true }], ["LocalUtils.harOpen", { internal: true }], ["LocalUtils.harLookup", { internal: true }], ["LocalUtils.harClose", { internal: true }], ["LocalUtils.harUnzip", { internal: true }], ["LocalUtils.connect", { internal: true }], ["LocalUtils.tracingStarted", { internal: true }], ["LocalUtils.addStackToTracingNoReply", { internal: true }], ["LocalUtils.traceDiscarded", { internal: true }], ["LocalUtils.globToRegex", { internal: true }], ["Request.response", { internal: true }], ["Request.rawRequestHeaders", { internal: true }], ["Route.redirectNavigationRequest", { internal: true }], ["Route.abort", { title: "Abort request", group: "route" }], ["Route.continue", { title: "Continue request", group: "route" }], ["Route.fulfill", { title: "Fulfill request", group: "route" }], ["WebSocketRoute.connect", { title: "Connect WebSocket to server", group: "route" }], ["WebSocketRoute.ensureOpened", { internal: true }], ["WebSocketRoute.sendToPage", { title: "Send WebSocket message", group: "route" }], ["WebSocketRoute.sendToServer", { title: "Send WebSocket message", group: "route" }], ["WebSocketRoute.closePage", { internal: true }], ["WebSocketRoute.closeServer", { internal: true }], ["Response.body", { title: "Get response body", group: "getter" }], ["Response.securityDetails", { internal: true }], ["Response.serverAddr", { internal: true }], ["Response.rawResponseHeaders", { internal: true }], ["Response.httpVersion", { internal: true }], ["Response.sizes", { internal: true }], ["Page.addInitScript", { title: "Add init script", group: "configuration" }], ["Page.close", { title: "Close page", pause: true, potentiallyClosesScope: true }], ["Page.runBeforeUnload", { title: "Run beforeunload", pause: true }], ["Page.clearConsoleMessages", { title: "Clear console messages" }], ["Page.consoleMessages", { title: "Get console messages", group: "getter" }], ["Page.emulateMedia", { title: "Emulate media", snapshot: true, pause: true }], ["Page.exposeBinding", { title: "Expose binding", group: "configuration" }], ["Page.goBack", { title: "Go back", slowMo: true, snapshot: true, pause: true }], ["Page.goForward", { title: "Go forward", slowMo: true, snapshot: true, pause: true }], ["Page.requestGC", { title: "Request garbage collection", group: "configuration" }], ["Page.registerLocatorHandler", { title: "Register locator handler" }], ["Page.resolveLocatorHandlerNoReply", { internal: true }], ["Page.unregisterLocatorHandler", { title: "Unregister locator handler" }], ["Page.reload", { title: "Reload", slowMo: true, snapshot: true, pause: true }], ["Page.expectScreenshot", { title: "Expect screenshot", snapshot: true, pause: true }], ["Page.screenshot", { title: "Screenshot", snapshot: true, pause: true }], ["Page.setExtraHTTPHeaders", { title: "Set extra HTTP headers", group: "configuration" }], ["Page.setNetworkInterceptionPatterns", { title: "Route requests", group: "route" }], ["Page.setWebSocketInterceptionPatterns", { title: "Route WebSockets", group: "route" }], ["Page.setViewportSize", { title: "Set viewport size", snapshot: true, pause: true }], ["Page.keyboardDown", { title: 'Key down "{key}"', slowMo: true, snapshot: true, pause: true, input: true }], ["Page.keyboardUp", { title: 'Key up "{key}"', slowMo: true, snapshot: true, pause: true, input: true }], ["Page.keyboardInsertText", { title: 'Insert "{text}"', slowMo: true, snapshot: true, pause: true, input: true }], ["Page.keyboardType", { title: 'Type "{text}"', slowMo: true, snapshot: true, pause: true, input: true }], ["Page.keyboardPress", { title: 'Press "{key}"', slowMo: true, snapshot: true, pause: true, input: true }], ["Page.mouseMove", { title: "Mouse move", slowMo: true, snapshot: true, pause: true, input: true }], ["Page.mouseDown", { title: "Mouse down", slowMo: true, snapshot: true, pause: true, input: true }], ["Page.mouseUp", { title: "Mouse up", slowMo: true, snapshot: true, pause: true, input: true }], ["Page.mouseClick", { title: "Click", slowMo: true, snapshot: true, pause: true, input: true }], ["Page.mouseWheel", { title: "Mouse wheel", slowMo: true, snapshot: true, pause: true, input: true }], ["Page.touchscreenTap", { title: "Tap", slowMo: true, snapshot: true, pause: true, input: true }], ["Page.clearPageErrors", { title: "Clear page errors" }], ["Page.pageErrors", { title: "Get page errors", group: "getter" }], ["Page.pdf", { title: "PDF" }], ["Page.requests", { title: "Get network requests", group: "getter" }], ["Page.startJSCoverage", { title: "Start JS coverage", group: "configuration" }], ["Page.stopJSCoverage", { title: "Stop JS coverage", group: "configuration" }], ["Page.startCSSCoverage", { title: "Start CSS coverage", group: "configuration" }], ["Page.stopCSSCoverage", { title: "Stop CSS coverage", group: "configuration" }], ["Page.bringToFront", { title: "Bring to front" }], ["Page.pickLocator", { title: "Pick locator", group: "configuration" }], ["Page.cancelPickLocator", { title: "Cancel pick locator", group: "configuration" }], ["Page.hideHighlight", { title: "Hide all element highlights", group: "configuration" }], ["Page.screencastShowOverlay", { title: "Show overlay", group: "configuration" }], ["Page.screencastRemoveOverlay", { title: "Remove overlay", group: "configuration" }], ["Page.screencastChapter", { title: "Show chapter overlay", group: "configuration" }], ["Page.screencastSetOverlayVisible", { title: "Set overlay visibility", group: "configuration" }], ["Page.screencastShowActions", { title: "Show actions", group: "configuration" }], ["Page.screencastHideActions", { title: "Remove actions", group: "configuration" }], ["Page.screencastStart", { title: "Start screencast", group: "configuration" }], ["Page.screencastStop", { title: "Stop screencast", group: "configuration" }], ["Page.updateSubscription", { internal: true }], ["Page.setDockTile", { internal: true }], ["Page.webStorageItems", { title: "Get WebStorage items", group: "getter" }], ["Page.webStorageGetItem", { title: "Get WebStorage item", group: "getter" }], ["Page.webStorageSetItem", { title: "Set WebStorage item", group: "configuration" }], ["Page.webStorageRemoveItem", { title: "Remove WebStorage item", group: "configuration" }], ["Page.webStorageClear", { title: "Clear WebStorage", group: "configuration" }], ["Root.initialize", { internal: true }], ["Playwright.newRequest", { title: "Create request context" }], ["DebugController.initialize", { internal: true }], ["DebugController.setReportStateChanged", { internal: true }], ["DebugController.setRecorderMode", { internal: true }], ["DebugController.highlight", { internal: true }], ["DebugController.hideHighlight", { internal: true }], ["DebugController.resume", { internal: true }], ["DebugController.kill", { internal: true }], ["SocksSupport.socksConnected", { internal: true }], ["SocksSupport.socksFailed", { internal: true }], ["SocksSupport.socksData", { internal: true }], ["SocksSupport.socksError", { internal: true }], ["SocksSupport.socksEnd", { internal: true }], ["JsonPipe.send", { internal: true }], ["JsonPipe.close", { internal: true }], ["CDPSession.send", { title: "Send CDP command", group: "configuration" }], ["CDPSession.detach", { title: "Detach CDP session", potentiallyClosesScope: true, group: "configuration" }], ["BindingCall.reject", { internal: true }], ["BindingCall.resolve", { internal: true }], ["Debugger.requestPause", { title: "Pause on next call", group: "configuration" }], ["Debugger.resume", { title: "Resume", group: "configuration" }], ["Debugger.next", { title: "Step to next call", group: "configuration" }], ["Debugger.runTo", { title: "Run to location", group: "configuration" }], ["Dialog.accept", { title: "Accept dialog" }], ["Dialog.dismiss", { title: "Dismiss dialog" }], ["Tracing.tracingStart", { title: "Start tracing", group: "configuration" }], ["Tracing.tracingStartChunk", { title: "Start tracing", group: "configuration" }], ["Tracing.tracingGroup", { title: 'Trace "{name}"' }], ["Tracing.tracingGroupEnd", { title: "Group end" }], ["Tracing.tracingStopChunk", { title: "Stop tracing", group: "configuration" }], ["Tracing.tracingStop", { title: "Stop tracing", group: "configuration" }], ["Tracing.harStart", { internal: true }], ["Tracing.harExport", { internal: true }], ["Worker.disconnect", { title: "Disconnect from worker", potentiallyClosesScope: true }], ["Worker.evaluateExpression", { title: "Evaluate" }], ["Worker.evaluateExpressionHandle", { title: "Evaluate" }], ["Worker.updateSubscription", { internal: true }] ]); } }); // packages/isomorphic/protocolFormatter.ts function formatProtocolParam(params2, alternatives) { return _formatProtocolParam(params2, alternatives)?.replaceAll("\n", "\\n"); } function _formatProtocolParam(params2, alternatives) { if (!params2) return void 0; for (const name of alternatives.split("|")) { if (name === "url") { try { const urlObject = new URL(params2[name]); if (urlObject.protocol === "data:") return urlObject.protocol; if (["about:", "chrome:", "edge:"].includes(urlObject.protocol)) return params2[name]; return urlObject.pathname + urlObject.search; } catch (error) { if (params2[name] !== void 0) return params2[name]; } } if (name === "timeNumber" && params2[name] !== void 0) { return new Date(params2[name]).toString(); } const value2 = deepParam(params2, name); if (value2 !== void 0) return value2; } } function deepParam(params2, name) { const tokens = name.split("."); let current = params2; for (const token of tokens) { if (typeof current !== "object" || current === null) return void 0; current = current[token]; } if (current === void 0) return void 0; return String(current); } function renderTitleForCall(metadata) { const titleFormat = metadata.title ?? getMetainfo(metadata)?.title ?? metadata.method; return titleFormat.replace(/\{([^}]+)\}/g, (fullMatch, p1) => { return formatProtocolParam(metadata.params, p1) ?? fullMatch; }); } function getActionGroup(metadata) { return getMetainfo(metadata)?.group; } var init_protocolFormatter = __esm({ "packages/isomorphic/protocolFormatter.ts"() { "use strict"; init_protocolMetainfo(); } }); // packages/isomorphic/semaphore.ts var Semaphore; var init_semaphore = __esm({ "packages/isomorphic/semaphore.ts"() { "use strict"; init_manualPromise(); Semaphore = class { constructor(max) { this._acquired = 0; this._queue = []; this._max = max; } setMax(max) { this._max = max; } acquire() { const lock2 = new ManualPromise(); this._queue.push(lock2); this._flush(); return lock2; } release() { --this._acquired; this._flush(); } _flush() { while (this._acquired < this._max && this._queue.length) { ++this._acquired; this._queue.shift().resolve(); } } }; } }); // packages/isomorphic/formatUtils.ts function msToString(ms) { if (ms < 0 || !isFinite(ms)) return "-"; if (ms === 0) return "0ms"; if (ms < 1e3) return ms.toFixed(0) + "ms"; const seconds = ms / 1e3; if (seconds < 60) return seconds.toFixed(1) + "s"; const minutes = seconds / 60; if (minutes < 60) return minutes.toFixed(1) + "m"; const hours = minutes / 60; if (hours < 24) return hours.toFixed(1) + "h"; const days = hours / 24; return days.toFixed(1) + "d"; } function bytesToString(bytes) { if (bytes < 0 || !isFinite(bytes)) return "-"; if (bytes === 0) return "0"; if (bytes < 1e3) return bytes.toFixed(0); const kb = bytes / 1024; if (kb < 1e3) return kb.toFixed(1) + "K"; const mb = kb / 1024; if (mb < 1e3) return mb.toFixed(1) + "M"; const gb = mb / 1024; return gb.toFixed(1) + "G"; } var init_formatUtils = __esm({ "packages/isomorphic/formatUtils.ts"() { "use strict"; } }); // packages/isomorphic/time.ts function setTimeOrigin(origin) { _timeOrigin = origin; _timeShift = performance.timeOrigin - origin; } function timeOrigin() { return _timeOrigin; } function monotonicTime() { return Math.floor((performance.now() + _timeShift) * 1e3) / 1e3; } var _timeOrigin, _timeShift, DEFAULT_PLAYWRIGHT_TIMEOUT, DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT; var init_time = __esm({ "packages/isomorphic/time.ts"() { "use strict"; _timeOrigin = performance.timeOrigin; _timeShift = 0; DEFAULT_PLAYWRIGHT_TIMEOUT = 3e4; DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT = 3 * 60 * 1e3; } }); // packages/isomorphic/timeoutRunner.ts async function raceAgainstDeadline(cb, deadline) { let timer; return await Promise.race([ cb().then((result2) => { return { result: result2, timedOut: false }; }), new Promise((resolve) => { if (!deadline) return; timer = setTimeout(() => resolve({ timedOut: true }), deadline - monotonicTime()); }) ]).finally(() => { clearTimeout(timer); }); } async function pollAgainstDeadline(callback, deadline, pollIntervals = [100, 250, 500, 1e3]) { const lastPollInterval = pollIntervals.pop() ?? 1e3; let lastResult; const wrappedCallback = () => Promise.resolve().then(callback); while (true) { const time = monotonicTime(); if (deadline && time >= deadline) break; const received = await raceAgainstDeadline(wrappedCallback, deadline); if (received.timedOut) break; lastResult = received.result.result; if (!received.result.continuePolling) return { result: lastResult, timedOut: false }; const interval = pollIntervals.shift() ?? lastPollInterval; if (deadline && deadline <= monotonicTime() + interval) break; await new Promise((x) => setTimeout(x, interval)); } return { timedOut: true, result: lastResult }; } var init_timeoutRunner = __esm({ "packages/isomorphic/timeoutRunner.ts"() { "use strict"; init_time(); } }); // packages/isomorphic/trace/snapshotServer.ts function removeHash(url2) { try { const u = new URL(url2); u.hash = ""; return u.toString(); } catch (e) { return url2; } } var SnapshotServer; var init_snapshotServer = __esm({ "packages/isomorphic/trace/snapshotServer.ts"() { "use strict"; SnapshotServer = class { constructor(snapshotStorage, resourceLoader) { this._snapshotIds = /* @__PURE__ */ new Map(); this._snapshotStorage = snapshotStorage; this._resourceLoader = resourceLoader; } serveSnapshot(pageOrFrameId, searchParams, snapshotUrl) { const snapshot3 = this._snapshot(pageOrFrameId, searchParams); if (!snapshot3) return new Response(null, { status: 404 }); const renderedSnapshot = snapshot3.render(); this._snapshotIds.set(snapshotUrl, snapshot3); return new Response(renderedSnapshot.html, { status: 200, headers: { "Content-Type": "text/html; charset=utf-8" } }); } async serveClosestScreenshot(pageOrFrameId, searchParams) { const snapshot3 = this._snapshot(pageOrFrameId, searchParams); const sha1 = snapshot3?.closestScreenshot(); if (!sha1) return new Response(null, { status: 404 }); return new Response(await this._resourceLoader(sha1)); } serveSnapshotInfo(pageOrFrameId, searchParams) { const snapshot3 = this._snapshot(pageOrFrameId, searchParams); return this._respondWithJson(snapshot3 ? { viewport: snapshot3.viewport(), url: snapshot3.snapshot().frameUrl, timestamp: snapshot3.snapshot().timestamp, wallTime: snapshot3.snapshot().wallTime } : { error: "No snapshot found" }); } _snapshot(pageOrFrameId, params2) { const name = params2.get("name"); return this._snapshotStorage.snapshotByName(pageOrFrameId, name); } _respondWithJson(object) { return new Response(JSON.stringify(object), { status: 200, headers: { "Cache-Control": "public, max-age=31536000", "Content-Type": "application/json" } }); } async serveResource(requestUrlAlternatives, method, snapshotUrl) { let resource; const snapshot3 = this._snapshotIds.get(snapshotUrl); for (const requestUrl of requestUrlAlternatives) { resource = snapshot3?.resourceByUrl(removeHash(requestUrl), method); if (resource) break; } if (!resource) return new Response(null, { status: 404 }); const sha1 = resource.response.content._sha1; const content = sha1 ? await this._resourceLoader(sha1) || new Blob([]) : new Blob([]); let contentType = resource.response.content.mimeType; const isTextEncoding = /^text\/|^application\/(javascript|json)/.test(contentType); if (isTextEncoding && !contentType.includes("charset")) contentType = `${contentType}; charset=utf-8`; const headers = new Headers(); if (contentType !== "x-unknown") headers.set("Content-Type", contentType); for (const { name, value: value2 } of resource.response.headers) headers.set(name, value2); headers.delete("Content-Encoding"); headers.delete("Access-Control-Allow-Origin"); headers.set("Access-Control-Allow-Origin", "*"); headers.delete("Content-Length"); headers.set("Content-Length", String(content.size)); if (this._snapshotStorage.hasResourceOverride(resource.request.url)) headers.set("Cache-Control", "no-store, no-cache, max-age=0"); else headers.set("Cache-Control", "public, max-age=31536000"); const { status } = resource.response; const isNullBodyStatus = status === 101 || status === 204 || status === 205 || status === 304; return new Response(isNullBodyStatus ? null : content, { headers, status: resource.response.status, statusText: resource.response.statusText }); } }; } }); // packages/isomorphic/urlMatch.ts function isHttpUrl(url2, base) { try { return ["http:", "https:"].includes(new URL(url2, base).protocol); } catch { return false; } } function globToRegexPattern(glob) { const tokens = ["^"]; let inGroup = false; for (let i = 0; i < glob.length; ++i) { const c = glob[i]; if (c === "\\" && i + 1 < glob.length) { const char = glob[++i]; tokens.push(escapedChars.has(char) ? "\\" + char : char); continue; } if (c === "*") { const charBefore = glob[i - 1]; let starCount = 1; while (glob[i + 1] === "*") { starCount++; i++; } if (starCount > 1) { const charAfter = glob[i + 1]; if (charAfter === "/") { if (charBefore === "/") tokens.push("((.+/)|)"); else tokens.push("(.*/)"); ++i; } else { tokens.push("(.*)"); } } else { tokens.push("([^/]*)"); } continue; } switch (c) { case "{": if (inGroup) throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: nested '{' is not supported`); inGroup = true; tokens.push("("); break; case "}": if (!inGroup) throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: unmatched '}'`); inGroup = false; tokens.push(")"); break; case ",": if (inGroup) { tokens.push("|"); break; } tokens.push("\\" + c); break; default: tokens.push(escapedChars.has(c) ? "\\" + c : c); } } if (inGroup) throw new Error(`Invalid glob pattern ${JSON.stringify(glob)}: unmatched '{'`); tokens.push("$"); return tokens.join(""); } function isRegExp3(obj) { return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]"; } function serializeURLPattern(v) { return { hash: v.hash, hostname: v.hostname, password: v.password, pathname: v.pathname, port: v.port, protocol: v.protocol, search: v.search, username: v.username }; } function serializeURLMatch(match) { if (isString(match)) return { glob: match }; if (isRegExp3(match)) return { regexSource: match.source, regexFlags: match.flags }; if (isURLPattern(match)) return { urlPattern: serializeURLPattern(match) }; return void 0; } function deserializeURLPattern(v) { if (typeof globalThis.URLPattern !== "function") return () => true; return new globalThis.URLPattern({ hash: v.hash, hostname: v.hostname, password: v.password, pathname: v.pathname, port: v.port, protocol: v.protocol, search: v.search, username: v.username }); } function deserializeURLMatch(match) { if (match.regexSource) return new RegExp(match.regexSource, match.regexFlags); if (match.urlPattern) return deserializeURLPattern(match.urlPattern); return match.glob; } function urlMatchesEqual(match1, match2) { if (isRegExp3(match1) && isRegExp3(match2)) return match1.source === match2.source && match1.flags === match2.flags; return match1 === match2; } function urlMatches(baseURL, urlString, match, webSocketUrl) { if (match === void 0 || match === "") return true; if (isString(match)) match = new RegExp(resolveGlobToRegexPattern(baseURL, match, webSocketUrl)); if (isRegExp3(match)) { const r = match.test(urlString); return r; } const url2 = parseURL(urlString); if (!url2) return false; if (isURLPattern(match)) return match.test(url2.href); if (typeof match !== "function") throw new Error("url parameter should be string, RegExp, URLPattern or function"); return match(url2); } function resolveGlobToRegexPattern(baseURL, glob, webSocketUrl) { if (webSocketUrl) baseURL = toWebSocketBaseUrl(baseURL); glob = resolveGlobBase(baseURL, glob); return globToRegexPattern(glob); } function toWebSocketBaseUrl(baseURL) { if (baseURL && /^https?:\/\//.test(baseURL)) baseURL = baseURL.replace(/^http/, "ws"); return baseURL; } function resolveGlobBase(baseURL, match) { if (!match.startsWith("*")) { let mapToken2 = function(original, replacement) { if (original.length === 0) return ""; tokenMap.set(replacement, original); return replacement; }; var mapToken = mapToken2; const tokenMap = /* @__PURE__ */ new Map(); match = match.replaceAll(/\\\\\?/g, "?"); if (match.startsWith("about:") || match.startsWith("data:") || match.startsWith("chrome:") || match.startsWith("edge:") || match.startsWith("file:")) return match; const relativePath = match.split("/").map((token, index) => { if (token === "." || token === ".." || token === "") return token; if (index === 0 && token.endsWith(":")) { if (token.indexOf("*") !== -1 || token.indexOf("{") !== -1) return mapToken2(token, "http:"); return token; } const questionIndex = token.indexOf("?"); if (questionIndex === -1) return mapToken2(token, `$_${index}_$`); const newPrefix = mapToken2(token.substring(0, questionIndex), `$_${index}_$`); const newSuffix = mapToken2(token.substring(questionIndex), `?$_${index}_$`); return newPrefix + newSuffix; }).join("/"); const result2 = resolveBaseURL(baseURL, relativePath); let resolved = result2.resolved; for (const [token, original] of tokenMap) { const normalize = result2.caseInsensitivePart?.includes(token); resolved = resolved.replace(token, normalize ? original.toLowerCase() : original); } match = resolved; } return match; } function parseURL(url2) { try { return new URL(url2); } catch (e) { return null; } } function constructURLBasedOnBaseURL(baseURL, givenURL) { try { return resolveBaseURL(baseURL, givenURL).resolved; } catch (e) { return givenURL; } } function resolveBaseURL(baseURL, givenURL) { try { const url2 = new URL(givenURL, baseURL); const resolved = url2.toString(); const caseInsensitivePrefix = url2.origin; return { resolved, caseInsensitivePart: caseInsensitivePrefix }; } catch (e) { return { resolved: givenURL }; } } var escapedChars, isURLPattern; var init_urlMatch = __esm({ "packages/isomorphic/urlMatch.ts"() { "use strict"; init_stringUtils(); escapedChars = /* @__PURE__ */ new Set(["$", "^", "+", ".", "*", "(", ")", "|", "\\", "?", "{", "}", "[", "]"]); isURLPattern = (v) => typeof globalThis.URLPattern === "function" && v instanceof globalThis.URLPattern; } }); // packages/isomorphic/locatorUtils.ts function getByAttributeTextSelector(attrName, text2, options) { return `internal:attr=[${attrName}=${escapeForAttributeSelector(text2, options?.exact || false)}]`; } function encodeTestIdAttributeName(testIdAttributeName2) { return testIdAttributeName2.includes(",") ? JSON.stringify(testIdAttributeName2) : testIdAttributeName2; } function getByTestIdSelector(testIdAttributeName2, testId) { return `internal:testid=[${encodeTestIdAttributeName(testIdAttributeName2)}=${escapeForAttributeSelector(testId, true)}]`; } function getByLabelSelector(text2, options) { return "internal:label=" + escapeForTextSelector(text2, !!options?.exact); } function getByAltTextSelector(text2, options) { return getByAttributeTextSelector("alt", text2, options); } function getByTitleSelector(text2, options) { return getByAttributeTextSelector("title", text2, options); } function getByPlaceholderSelector(text2, options) { return getByAttributeTextSelector("placeholder", text2, options); } function getByTextSelector(text2, options) { return "internal:text=" + escapeForTextSelector(text2, !!options?.exact); } function getByRoleSelector(role, options = {}) { const props = []; if (options.checked !== void 0) props.push(["checked", String(options.checked)]); if (options.disabled !== void 0) props.push(["disabled", String(options.disabled)]); if (options.selected !== void 0) props.push(["selected", String(options.selected)]); if (options.expanded !== void 0) props.push(["expanded", String(options.expanded)]); if (options.includeHidden !== void 0) props.push(["include-hidden", String(options.includeHidden)]); if (options.level !== void 0) props.push(["level", String(options.level)]); if (options.name !== void 0) props.push(["name", escapeForAttributeSelector(options.name, !!options.exact)]); if (options.description !== void 0) props.push(["description", escapeForAttributeSelector(options.description, !!options.exact)]); if (options.pressed !== void 0) props.push(["pressed", String(options.pressed)]); return `internal:role=${role}${props.map(([n, v]) => `[${n}=${v}]`).join("")}`; } var init_locatorUtils = __esm({ "packages/isomorphic/locatorUtils.ts"() { "use strict"; init_stringUtils(); } }); // packages/isomorphic/locatorParser.ts function parseLocator(locator2, testIdAttributeName2) { locator2 = locator2.replace(/AriaRole\s*\.\s*([\w]+)/g, (_, group) => group.toLowerCase()).replace(/(get_by_role|getByRole)\s*\(\s*(?:["'`])([^'"`]+)['"`]/g, (_, group1, group2) => `${group1}(${group2.toLowerCase()}`); const params2 = []; let template = ""; for (let i = 0; i < locator2.length; ++i) { const quote5 = locator2[i]; if (quote5 !== '"' && quote5 !== "'" && quote5 !== "`" && quote5 !== "/") { template += quote5; continue; } const isRegexEscaping = locator2[i - 1] === "r" || locator2[i] === "/"; ++i; let text2 = ""; while (i < locator2.length) { if (locator2[i] === "\\") { if (isRegexEscaping) { if (locator2[i + 1] !== quote5) text2 += locator2[i]; ++i; text2 += locator2[i]; } else { ++i; if (locator2[i] === "n") text2 += "\n"; else if (locator2[i] === "r") text2 += "\r"; else if (locator2[i] === "t") text2 += " "; else text2 += locator2[i]; } ++i; continue; } if (locator2[i] !== quote5) { text2 += locator2[i++]; continue; } break; } params2.push({ quote: quote5, text: text2 }); template += (quote5 === "/" ? "r" : "") + "$" + params2.length; } template = template.toLowerCase().replace(/get_by_alt_text/g, "getbyalttext").replace(/get_by_test_id/g, "getbytestid").replace(/get_by_([\w]+)/g, "getby$1").replace(/has_not_text/g, "hasnottext").replace(/has_text/g, "hastext").replace(/has_not/g, "hasnot").replace(/frame_locator/g, "framelocator").replace(/content_frame/g, "contentframe").replace(/[{}\s]/g, "").replace(/new\(\)/g, "").replace(/new[\w]+\.[\w]+options\(\)/g, "").replace(/\.set/g, ",set").replace(/\.or_\(/g, "or(").replace(/\.and_\(/g, "and(").replace(/:/g, "=").replace(/,re\.ignorecase/g, "i").replace(/,pattern.case_insensitive/g, "i").replace(/,regexoptions.ignorecase/g, "i").replace(/re.compile\(([^)]+)\)/g, "$1").replace(/pattern.compile\(([^)]+)\)/g, "r$1").replace(/newregex\(([^)]+)\)/g, "r$1").replace(/string=/g, "=").replace(/regex=/g, "=").replace(/,,/g, ",").replace(/,\)/g, ")"); const preferredQuote = params2.map((p) => p.quote).filter((quote5) => "'\"`".includes(quote5))[0]; return { selector: transform(template, params2, testIdAttributeName2), preferredQuote }; } function countParams(template) { return [...template.matchAll(/\$\d+/g)].length; } function shiftParams(template, sub) { return template.replace(/\$(\d+)/g, (_, ordinal) => `$${ordinal - sub}`); } function transform(template, params2, testIdAttributeName2) { while (true) { const hasMatch = template.match(/filter\(,?(has=|hasnot=|sethas\(|sethasnot\()/); if (!hasMatch) break; const start3 = hasMatch.index + hasMatch[0].length; let balance = 0; let end = start3; for (; end < template.length; end++) { if (template[end] === "(") balance++; else if (template[end] === ")") balance--; if (balance < 0) break; } let prefix = template.substring(0, start3); let extraSymbol = 0; if (["sethas(", "sethasnot("].includes(hasMatch[1])) { extraSymbol = 1; prefix = prefix.replace(/sethas\($/, "has=").replace(/sethasnot\($/, "hasnot="); } const paramsCountBeforeHas = countParams(template.substring(0, start3)); const hasTemplate = shiftParams(template.substring(start3, end), paramsCountBeforeHas); const paramsCountInHas = countParams(hasTemplate); const hasParams = params2.slice(paramsCountBeforeHas, paramsCountBeforeHas + paramsCountInHas); const hasSelector = JSON.stringify(transform(hasTemplate, hasParams, testIdAttributeName2)); template = prefix.replace(/=$/, "2=") + `$${paramsCountBeforeHas + 1}` + shiftParams(template.substring(end + extraSymbol), paramsCountInHas - 1); const paramsBeforeHas = params2.slice(0, paramsCountBeforeHas); const paramsAfterHas = params2.slice(paramsCountBeforeHas + paramsCountInHas); params2 = paramsBeforeHas.concat([{ quote: '"', text: hasSelector }]).concat(paramsAfterHas); } template = template.replace(/\,set([\w]+)\(([^)]+)\)/g, (_, group1, group2) => "," + group1.toLowerCase() + "=" + group2.toLowerCase()).replace(/framelocator\(([^)]+)\)/g, "$1.internal:control=enter-frame").replace(/contentframe(\(\))?/g, "internal:control=enter-frame").replace(/locator\(([^)]+),hastext=([^),]+)\)/g, "locator($1).internal:has-text=$2").replace(/locator\(([^)]+),hasnottext=([^),]+)\)/g, "locator($1).internal:has-not-text=$2").replace(/locator\(([^)]+),hastext=([^),]+)\)/g, "locator($1).internal:has-text=$2").replace(/locator\(([^)]+)\)/g, "$1").replace(/getbyrole\(([^)]+)\)/g, "internal:role=$1").replace(/getbytext\(([^)]+)\)/g, "internal:text=$1").replace(/getbylabel\(([^)]+)\)/g, "internal:label=$1").replace(/getbytestid\(([^)]+)\)/g, `internal:testid=[${encodeTestIdAttributeName(testIdAttributeName2)}=$1]`).replace(/getby(placeholder|alt|title)(?:text)?\(([^)]+)\)/g, "internal:attr=[$1=$2]").replace(/first(\(\))?/g, "nth=0").replace(/last(\(\))?/g, "nth=-1").replace(/nth\(([^)]+)\)/g, "nth=$1").replace(/filter\(,?visible=true\)/g, "visible=true").replace(/filter\(,?visible=false\)/g, "visible=false").replace(/filter\(,?hastext=([^)]+)\)/g, "internal:has-text=$1").replace(/filter\(,?hasnottext=([^)]+)\)/g, "internal:has-not-text=$1").replace(/filter\(,?has2=([^)]+)\)/g, "internal:has=$1").replace(/filter\(,?hasnot2=([^)]+)\)/g, "internal:has-not=$1").replace(/,exact=false/g, "").replace(/(,name=\$\d+)(,description=\$\d+),exact=true/g, "$1s$2s").replace(/,exact=true/g, "s").replace(/,includehidden=/g, ",include-hidden=").replace(/\,/g, "]["); const parts = template.split("."); for (let index = 0; index < parts.length - 1; index++) { if (parts[index] === "internal:control=enter-frame" && parts[index + 1].startsWith("nth=")) { const [nth] = parts.splice(index, 1); parts.splice(index + 1, 0, nth); } } return parts.map((t) => { if (!t.startsWith("internal:") || t === "internal:control") return t.replace(/\$(\d+)/g, (_, ordinal) => { const param = params2[+ordinal - 1]; return param.text; }); t = t.includes("[") ? t.replace(/\]/, "") + "]" : t; t = t.replace(/(?:r)\$(\d+)(i)?/g, (_, ordinal, suffix) => { const param = params2[+ordinal - 1]; if (t.startsWith("internal:attr") || t.startsWith("internal:testid") || t.startsWith("internal:role")) return escapeForAttributeSelector(new RegExp(param.text), false) + (suffix || ""); return escapeForTextSelector(new RegExp(param.text, suffix), false); }).replace(/\$(\d+)(i|s)?/g, (_, ordinal, suffix) => { const param = params2[+ordinal - 1]; if (t.startsWith("internal:has=") || t.startsWith("internal:has-not=")) return param.text; if (t.startsWith("internal:testid")) return escapeForAttributeSelector(param.text, true); if (t.startsWith("internal:attr") || t.startsWith("internal:role")) return escapeForAttributeSelector(param.text, suffix === "s"); return escapeForTextSelector(param.text, suffix === "s"); }); return t; }).join(" >> "); } function locatorOrSelectorAsSelector(language, locator2, testIdAttributeName2 = "data-testid") { try { return unsafeLocatorOrSelectorAsSelector(language, locator2, testIdAttributeName2); } catch (e) { return ""; } } function unsafeLocatorOrSelectorAsSelector(language, locator2, testIdAttributeName2 = "data-testid") { try { parseSelector(locator2); return locator2; } catch (e) { } const { selector, preferredQuote } = parseLocator(locator2, testIdAttributeName2); const locators = asLocators(language, selector, void 0, void 0, preferredQuote); const digest = digestForComparison(language, locator2); if (locators.some((candidate) => digestForComparison(language, candidate) === digest)) return selector; return ""; } function digestForComparison(language, locator2) { locator2 = locator2.replace(/\s/g, ""); if (language === "javascript") locator2 = locator2.replace(/\\?["`]/g, "'").replace(/,{}/g, ""); return locator2; } var init_locatorParser = __esm({ "packages/isomorphic/locatorParser.ts"() { "use strict"; init_locatorGenerators(); init_locatorUtils(); init_selectorParser(); init_stringUtils(); } }); // packages/isomorphic/trace/snapshotRenderer.ts function findClosest(items, metric, target) { return items.find((item, index) => { if (index === items.length - 1) return true; const next = items[index + 1]; return Math.abs(metric(item) - target) < Math.abs(metric(next) - target); }); } function isNodeNameAttributesChildNodesSnapshot(n) { return Array.isArray(n) && typeof n[0] === "string"; } function isSubtreeReferenceSnapshot(n) { return Array.isArray(n) && Array.isArray(n[0]); } function snapshotNodes(snapshot3) { if (!snapshot3._nodes) { const nodes = []; const visit = (n) => { if (typeof n === "string") { nodes.push(n); } else if (isNodeNameAttributesChildNodesSnapshot(n)) { const [, , ...children] = n; for (const child of children) visit(child); nodes.push(n); } }; visit(snapshot3.html); snapshot3._nodes = nodes; } return snapshot3._nodes; } function snapshotScript(viewport, ...targetIds) { function applyPlaywrightAttributes(blankSnapshotUrl2, viewport2, ...targetIds2) { const win = window; const searchParams = new URLSearchParams(win.location.search); const shouldPopulateCanvasFromScreenshot = searchParams.has("shouldPopulateCanvasFromScreenshot"); const isUnderTest2 = searchParams.has("isUnderTest"); const frameBoundingRectsInfo = { viewport: viewport2, frames: /* @__PURE__ */ new WeakMap() }; win["__playwright_frame_bounding_rects__"] = frameBoundingRectsInfo; const kPointerWarningTitle = "Recorded click position in absolute coordinates did not match the center of the clicked element. This is either due to the use of provided offset, or due to a difference between the test runner and the trace viewer operating systems."; const scrollTops = []; const scrollLefts = []; const targetElements = []; const canvasElements = []; let topSnapshotWindow = win; while (topSnapshotWindow !== topSnapshotWindow.parent && !topSnapshotWindow.location.pathname.match(/\/page@[a-z0-9]+$/)) topSnapshotWindow = topSnapshotWindow.parent; const visit = (root) => { for (const e of root.querySelectorAll(`[__playwright_scroll_top_]`)) scrollTops.push(e); for (const e of root.querySelectorAll(`[__playwright_scroll_left_]`)) scrollLefts.push(e); for (const element2 of root.querySelectorAll(`[__playwright_value_]`)) { const inputElement = element2; if (inputElement.type !== "file") inputElement.value = inputElement.getAttribute("__playwright_value_"); element2.removeAttribute("__playwright_value_"); } for (const element2 of root.querySelectorAll(`[__playwright_checked_]`)) { element2.checked = element2.getAttribute("__playwright_checked_") === "true"; element2.removeAttribute("__playwright_checked_"); } for (const element2 of root.querySelectorAll(`[__playwright_selected_]`)) { element2.selected = element2.getAttribute("__playwright_selected_") === "true"; element2.removeAttribute("__playwright_selected_"); } for (const element2 of root.querySelectorAll(`[__playwright_popover_open_]`)) { try { element2.showPopover(); } catch { } element2.removeAttribute("__playwright_popover_open_"); } for (const element2 of root.querySelectorAll(`[__playwright_dialog_open_]`)) { try { if (element2.getAttribute("__playwright_dialog_open_") === "modal") element2.showModal(); else element2.show(); } catch { } element2.removeAttribute("__playwright_dialog_open_"); } const highlightTarget = (target) => { const style = target.style; style.outline = "2px solid #006ab1"; style.backgroundColor = "#6fa8dc7f"; targetElements.push(target); }; for (const target of root.querySelectorAll(`[__playwright_target__=""]`)) highlightTarget(target); for (const targetId of targetIds2) { if (!targetId) continue; for (const target of root.querySelectorAll(`[__playwright_target__="${targetId}"]`)) highlightTarget(target); } for (const iframe of root.querySelectorAll("iframe, frame")) { const boundingRectJson = iframe.getAttribute("__playwright_bounding_rect__"); iframe.removeAttribute("__playwright_bounding_rect__"); const boundingRect = boundingRectJson ? JSON.parse(boundingRectJson) : void 0; if (boundingRect) frameBoundingRectsInfo.frames.set(iframe, { boundingRect, scrollLeft: 0, scrollTop: 0 }); const src = iframe.getAttribute("__playwright_src__"); if (!src) { iframe.setAttribute("src", blankSnapshotUrl2); } else { const url2 = new URL(win.location.href); const index = url2.pathname.lastIndexOf("/snapshot/"); if (index !== -1) url2.pathname = url2.pathname.substring(0, index + 1); url2.pathname += src.substring(1); iframe.setAttribute("src", url2.toString()); } } { const body = root.querySelector(`body[__playwright_custom_elements__]`); if (body && win.customElements) { const customElements = (body.getAttribute("__playwright_custom_elements__") || "").split(","); for (const elementName of customElements) win.customElements.define(elementName, class extends HTMLElement { }); } } for (const element2 of root.querySelectorAll(`template[__playwright_shadow_root_]`)) { const template = element2; const shadowRoot = template.parentElement.attachShadow({ mode: "open" }); shadowRoot.appendChild(template.content); template.remove(); visit(shadowRoot); } for (const element2 of root.querySelectorAll("a")) element2.addEventListener("click", (event) => { event.preventDefault(); }); if ("adoptedStyleSheets" in root) { const adoptedSheets = [...root.adoptedStyleSheets]; for (const element2 of root.querySelectorAll(`template[__playwright_style_sheet_]`)) { const template = element2; const sheet = new CSSStyleSheet(); sheet.replaceSync(template.getAttribute("__playwright_style_sheet_")); adoptedSheets.push(sheet); } root.adoptedStyleSheets = adoptedSheets; } canvasElements.push(...root.querySelectorAll("canvas")); }; const onLoad = () => { win.removeEventListener("load", onLoad); for (const element2 of scrollTops) { element2.scrollTop = +element2.getAttribute("__playwright_scroll_top_"); element2.removeAttribute("__playwright_scroll_top_"); if (frameBoundingRectsInfo.frames.has(element2)) frameBoundingRectsInfo.frames.get(element2).scrollTop = element2.scrollTop; } for (const element2 of scrollLefts) { element2.scrollLeft = +element2.getAttribute("__playwright_scroll_left_"); element2.removeAttribute("__playwright_scroll_left_"); if (frameBoundingRectsInfo.frames.has(element2)) frameBoundingRectsInfo.frames.get(element2).scrollLeft = element2.scrollLeft; } win.document.styleSheets[0].disabled = true; const search = new URL(win.location.href).searchParams; const isTopFrame = win === topSnapshotWindow; if (isTopFrame && search.get("pointX") && search.get("pointY")) { const pointX = +search.get("pointX"); const pointY = +search.get("pointY"); const pointElement = win.document.createElement("x-pw-pointer"); pointElement.style.position = "fixed"; pointElement.style.backgroundColor = "#f44336"; pointElement.style.width = "20px"; pointElement.style.height = "20px"; pointElement.style.borderRadius = "10px"; pointElement.style.margin = "-10px 0 0 -10px"; pointElement.style.zIndex = "2147483646"; pointElement.style.display = "flex"; pointElement.style.alignItems = "center"; pointElement.style.justifyContent = "center"; const target = targetElements[0]; const targetBox = target?.getBoundingClientRect(); const targetCenter = target ? { x: targetBox.left + targetBox.width / 2, y: targetBox.top + targetBox.height / 2 } : null; pointElement.style.left = (targetCenter?.x ?? pointX) + "px"; pointElement.style.top = (targetCenter?.y ?? pointY) + "px"; const isAligned = !targetCenter || Math.abs(targetCenter.x - pointX) <= 10 && Math.abs(targetCenter.y - pointY) <= 10; if (!isAligned) { const warningElement = win.document.createElement("x-pw-pointer-warning"); warningElement.textContent = "\u26A0"; warningElement.style.fontSize = "19px"; warningElement.style.color = "white"; warningElement.style.marginTop = "-3.5px"; warningElement.style.userSelect = "none"; pointElement.appendChild(warningElement); pointElement.setAttribute("title", kPointerWarningTitle); } win.document.documentElement.appendChild(pointElement); } if (canvasElements.length > 0) { let drawCheckerboard2 = function(context2, canvas) { function createCheckerboardPattern() { const pattern = win.document.createElement("canvas"); pattern.width = pattern.width / Math.floor(pattern.width / 24); pattern.height = pattern.height / Math.floor(pattern.height / 24); const context3 = pattern.getContext("2d"); context3.fillStyle = "lightgray"; context3.fillRect(0, 0, pattern.width, pattern.height); context3.fillStyle = "white"; context3.fillRect(0, 0, pattern.width / 2, pattern.height / 2); context3.fillRect(pattern.width / 2, pattern.height / 2, pattern.width, pattern.height); return context3.createPattern(pattern, "repeat"); } context2.fillStyle = createCheckerboardPattern(); context2.fillRect(0, 0, canvas.width, canvas.height); }; var drawCheckerboard = drawCheckerboard2; const img = new Image(); img.onload = () => { for (const canvas of canvasElements) { const context2 = canvas.getContext("2d"); const boundingRectAttribute = canvas.getAttribute("__playwright_bounding_rect__"); canvas.removeAttribute("__playwright_bounding_rect__"); if (!boundingRectAttribute) continue; let boundingRect; try { boundingRect = JSON.parse(boundingRectAttribute); } catch (e) { continue; } let currWindow = win; while (currWindow !== topSnapshotWindow) { const iframe = currWindow.frameElement; currWindow = currWindow.parent; const iframeInfo = currWindow["__playwright_frame_bounding_rects__"]?.frames.get(iframe); if (!iframeInfo?.boundingRect) break; const leftOffset = iframeInfo.boundingRect.left - iframeInfo.scrollLeft; const topOffset = iframeInfo.boundingRect.top - iframeInfo.scrollTop; boundingRect.left += leftOffset; boundingRect.top += topOffset; boundingRect.right += leftOffset; boundingRect.bottom += topOffset; } const { width, height } = topSnapshotWindow["__playwright_frame_bounding_rects__"].viewport; boundingRect.left = boundingRect.left / width; boundingRect.top = boundingRect.top / height; boundingRect.right = boundingRect.right / width; boundingRect.bottom = boundingRect.bottom / height; const partiallyUncaptured = boundingRect.right > 1 || boundingRect.bottom > 1; const fullyUncaptured = boundingRect.left > 1 || boundingRect.top > 1; if (fullyUncaptured) { canvas.title = `Playwright couldn't capture canvas contents because it's located outside the viewport.`; continue; } drawCheckerboard2(context2, canvas); if (shouldPopulateCanvasFromScreenshot) { context2.drawImage(img, boundingRect.left * img.width, boundingRect.top * img.height, (boundingRect.right - boundingRect.left) * img.width, (boundingRect.bottom - boundingRect.top) * img.height, 0, 0, canvas.width, canvas.height); if (partiallyUncaptured) canvas.title = `Playwright couldn't capture full canvas contents because it's located partially outside the viewport.`; else canvas.title = `Canvas contents are displayed on a best-effort basis based on viewport screenshots taken during test execution.`; } else { canvas.title = "Canvas content display is disabled."; } if (isUnderTest2) console.log(`canvas drawn:`, JSON.stringify([boundingRect.left, boundingRect.top, boundingRect.right - boundingRect.left, boundingRect.bottom - boundingRect.top].map((v) => Math.floor(v * 100)))); } }; img.onerror = () => { for (const canvas of canvasElements) { const context2 = canvas.getContext("2d"); drawCheckerboard2(context2, canvas); canvas.title = `Playwright couldn't show canvas contents because the screenshot failed to load.`; } }; img.src = location.href.replace("/snapshot", "/closest-screenshot"); } }; const onDOMContentLoaded = () => visit(win.document); win.addEventListener("load", onLoad); win.addEventListener("DOMContentLoaded", onDOMContentLoaded); } const safe = (value2) => JSON.stringify(value2).replace(/ `, ${safe(String(id))}`).join("")})`; } function rewriteURLForCustomProtocol(href) { if (href.startsWith(kLegacyBlobPrefix)) href = href.substring(kLegacyBlobPrefix.length); try { const url2 = new URL(href); if (url2.protocol === "javascript:" || url2.protocol === "vbscript:") return "javascript:void(0)"; const isBlob = url2.protocol === "blob:"; const isFile = url2.protocol === "file:"; if (!isBlob && !isFile && schemas.includes(url2.protocol)) return href; const prefix = "pw-" + url2.protocol.slice(0, url2.protocol.length - 1); if (!isFile) url2.protocol = "https:"; url2.hostname = url2.hostname ? `${prefix}--${url2.hostname}` : prefix; if (isFile) { url2.protocol = "https:"; } return url2.toString(); } catch { return href; } } function rewriteURLsInStyleSheetForCustomProtocol(text2) { return text2.replace(urlInCSSRegex, (match, protocol) => { const isBlob = protocol === "blob:"; const isFile = protocol === "file:"; if (!isBlob && !isFile && schemas.includes(protocol)) return match; return match.replace(protocol + "//", `https://pw-${protocol.slice(0, -1)}--`); }); } function escapeURLsInStyleSheet(text2) { const replacer = (match, url2) => { if (url2.includes(" frame.frameSwapWallTime, wallTime) : findClosest(this._screencastFrames, (frame) => frame.timestamp, timestamp); return closestFrame?.sha1; } render() { const result2 = []; const visit = (n, snapshotIndex, parentTag, parentAttrs) => { if (typeof n === "string") { if (parentTag === "STYLE" || parentTag === "style") result2.push(escapeURLsInStyleSheet(rewriteURLsInStyleSheetForCustomProtocol(n))); else result2.push(escapeHTML(n)); return; } if (isSubtreeReferenceSnapshot(n)) { const referenceIndex = snapshotIndex - n[0][0]; if (referenceIndex >= 0 && referenceIndex <= snapshotIndex) { const nodes = snapshotNodes(this._snapshots[referenceIndex]); const nodeIndex = n[0][1]; if (nodeIndex >= 0 && nodeIndex < nodes.length) return visit(nodes[nodeIndex], referenceIndex, parentTag, parentAttrs); } } else if (isNodeNameAttributesChildNodesSnapshot(n)) { const [name, nodeAttrs, ...children] = n; if (name.toUpperCase() === "SCRIPT") return; const upperName = name.toUpperCase(); const nodeName = upperName === "NOSCRIPT" ? "X-NOSCRIPT" : name; const attrs = Object.entries(nodeAttrs || {}); result2.push("<", nodeName); const kCurrentSrcAttribute = "__playwright_current_src__"; const isFrame = upperName === "IFRAME" || upperName === "FRAME"; const isAnchor = upperName === "A"; const isImg = upperName === "IMG"; const isMeta = upperName === "META"; const isImgWithCurrentSrc = isImg && attrs.some((a) => a[0] === kCurrentSrcAttribute); const isSourceInsidePictureWithCurrentSrc = upperName === "SOURCE" && parentTag === "PICTURE" && parentAttrs?.some((a) => a[0] === kCurrentSrcAttribute); const hasUnsafeHttpEquiv = isMeta && attrs.some((a) => a[0].toLowerCase() === "http-equiv" && !kAllowedMetaHttpEquivs.has(a[1].trim().toLowerCase())); for (const [attr, value2] of attrs) { let attrName = attr; if (attr.toLowerCase().startsWith("on")) continue; if (isFrame && attr.toLowerCase() === "src") { attrName = "__playwright_src__"; } if (isFrame && (attr.toLowerCase() === "srcdoc" || attr.toLowerCase() === "sandbox")) { attrName = "__playwright_" + attr.toLowerCase() + "__"; } if (upperName === "OBJECT" && attr.toLowerCase() === "data") attrName = "__playwright_data__"; if (upperName === "EMBED" && attr.toLowerCase() === "src") attrName = "__playwright_src__"; if (isImg && attr === kCurrentSrcAttribute) { attrName = "src"; } if (["src", "srcset"].includes(attr.toLowerCase()) && (isImgWithCurrentSrc || isSourceInsidePictureWithCurrentSrc)) { attrName = "_" + attrName; } if (hasUnsafeHttpEquiv && (attr.toLowerCase() === "http-equiv" || attr.toLowerCase() === "content")) { attrName = "_" + attr; } let attrValue = value2; if (!isAnchor && (attr.toLowerCase() === "href" || attr.toLowerCase() === "src" || attr === kCurrentSrcAttribute)) attrValue = rewriteURLForCustomProtocol(value2); result2.push(" ", attrName, '="', escapeHTMLAttribute(attrValue), '"'); } result2.push(">"); for (const child of children) visit(child, snapshotIndex, nodeName, attrs); if (!autoClosing.has(nodeName)) result2.push(""); return; } else { return; } }; const snapshot3 = this._snapshot; const html = this._htmlCache.getOrCompute(this, () => { visit(snapshot3.html, this._index, void 0, void 0); const safeDoctype = snapshot3.doctype?.replace(/[^a-zA-Z0-9]/g, ""); const prefix = safeDoctype ? `` : ""; const html2 = prefix + [ // Hide the document in order to prevent flickering. We will unhide once script has processed shadow. "", `` ].join("") + result2.join(""); return { value: html2, size: html2.length }; }); return { html, pageId: snapshot3.pageId, frameId: snapshot3.frameId, index: this._index }; } resourceByUrl(url2, method) { const snapshot3 = this._snapshot; let sameFrameResource; let otherFrameResource; for (const resource of this._resources) { if (typeof resource._monotonicTime === "number" && resource._monotonicTime >= snapshot3.timestamp) break; if (resource.response.status === 304) { continue; } if (resource.request.url === url2 && resource.request.method === method) { if (resource._frameref === snapshot3.frameId) sameFrameResource = resource; else otherFrameResource = resource; } } let result2 = sameFrameResource ?? otherFrameResource; if (result2 && method.toUpperCase() === "GET") { let override = snapshot3.resourceOverrides.find((o) => o.url === url2); if (override?.ref) { const index = this._index - override.ref; if (index >= 0 && index < this._snapshots.length) override = this._snapshots[index].resourceOverrides.find((o) => o.url === url2); } if (override?.sha1) { result2 = { ...result2, response: { ...result2.response, content: { ...result2.response.content, _sha1: override.sha1 } } }; } } return result2; } }; autoClosing = /* @__PURE__ */ new Set(["AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "MENUITEM", "META", "PARAM", "SOURCE", "TRACK", "WBR"]); kAllowedMetaHttpEquivs = /* @__PURE__ */ new Set(["content-type", "content-language", "default-style", "x-ua-compatible"]); schemas = ["about:", "blob:", "data:", "file:", "ftp:", "http:", "https:", "mailto:", "sftp:", "ws:", "wss:"]; kLegacyBlobPrefix = "http://playwright.bloburl/#"; urlInCSSRegex = /url\(['"]?([\w-]+:)\/\//ig; urlToEscapeRegex1 = /url\(\s*'([^']*)'\s*\)/ig; urlToEscapeRegex2 = /url\(\s*"([^"]*)"\s*\)/ig; blankSnapshotUrl = "data:text/html;base64," + btoa(``); } }); // packages/isomorphic/lruCache.ts var LRUCache; var init_lruCache = __esm({ "packages/isomorphic/lruCache.ts"() { "use strict"; LRUCache = class { constructor(maxSize) { this._maxSize = maxSize; this._map = /* @__PURE__ */ new Map(); this._size = 0; } getOrCompute(key, compute) { if (this._map.has(key)) { const result3 = this._map.get(key); this._map.delete(key); this._map.set(key, result3); return result3.value; } const result2 = compute(); while (this._map.size && this._size + result2.size > this._maxSize) { const [firstKey, firstValue] = this._map.entries().next().value; this._size -= firstValue.size; this._map.delete(firstKey); } this._map.set(key, result2); this._size += result2.size; return result2.value; } }; } }); // packages/isomorphic/trace/snapshotStorage.ts var SnapshotStorage; var init_snapshotStorage = __esm({ "packages/isomorphic/trace/snapshotStorage.ts"() { "use strict"; init_snapshotRenderer(); init_lruCache(); SnapshotStorage = class { constructor() { this._frameSnapshots = /* @__PURE__ */ new Map(); this._cache = new LRUCache(1e8); // 100MB per each trace this._contextToResources = /* @__PURE__ */ new Map(); this._resourceUrlsWithOverrides = /* @__PURE__ */ new Set(); } addResource(contextId4, resource) { resource.request.url = rewriteURLForCustomProtocol(resource.request.url); this._ensureResourcesForContext(contextId4).push(resource); } addFrameSnapshot(contextId4, snapshot3, screencastFrames) { for (const override of snapshot3.resourceOverrides) override.url = rewriteURLForCustomProtocol(override.url); let frameSnapshots = this._frameSnapshots.get(snapshot3.frameId); if (!frameSnapshots) { frameSnapshots = { raw: [], renderers: [] }; this._frameSnapshots.set(snapshot3.frameId, frameSnapshots); if (snapshot3.isMainFrame) this._frameSnapshots.set(snapshot3.pageId, frameSnapshots); } frameSnapshots.raw.push(snapshot3); const resources = this._ensureResourcesForContext(contextId4); const renderer = new SnapshotRenderer(this._cache, resources, frameSnapshots.raw, screencastFrames, frameSnapshots.raw.length - 1); frameSnapshots.renderers.push(renderer); return renderer; } snapshotByName(pageOrFrameId, snapshotName) { const snapshot3 = this._frameSnapshots.get(pageOrFrameId); return snapshot3?.renderers.find((r) => r.snapshotName === snapshotName); } snapshotsForTest() { return [...this._frameSnapshots.keys()]; } finalize() { for (const resources of this._contextToResources.values()) resources.sort((a, b) => (a._monotonicTime || 0) - (b._monotonicTime || 0)); for (const frameSnapshots of this._frameSnapshots.values()) { for (const snapshot3 of frameSnapshots.raw) { for (const override of snapshot3.resourceOverrides) this._resourceUrlsWithOverrides.add(override.url); } } } hasResourceOverride(url2) { return this._resourceUrlsWithOverrides.has(url2); } _ensureResourcesForContext(contextId4) { let resources = this._contextToResources.get(contextId4); if (!resources) { resources = []; this._contextToResources.set(contextId4, resources); } return resources; } }; } }); // packages/isomorphic/trace/traceUtils.ts function parseClientSideCallMetadata(data) { const result2 = /* @__PURE__ */ new Map(); const { files, stacks } = data; for (const s of stacks) { const [id, ff] = s; result2.set(`call@${id}`, ff.map((f) => ({ file: files[f[0]], line: f[1], column: f[2], function: f[3] }))); } return result2; } function serializeClientSideCallMetadata(metadatas) { const fileNames = /* @__PURE__ */ new Map(); const stacks = []; for (const m of metadatas) { if (!m.stack || !m.stack.length) continue; const stack = []; for (const frame of m.stack) { let ordinal = fileNames.get(frame.file); if (typeof ordinal !== "number") { ordinal = fileNames.size; fileNames.set(frame.file, ordinal); } const stackFrame = [ordinal, frame.line || 0, frame.column || 0, frame.function || ""]; stack.push(stackFrame); } stacks.push([m.id, stack]); } return { files: [...fileNames.keys()], stacks }; } var init_traceUtils = __esm({ "packages/isomorphic/trace/traceUtils.ts"() { "use strict"; } }); // packages/isomorphic/trace/traceModernizer.ts var TraceVersionError, latestVersion, TraceModernizer; var init_traceModernizer = __esm({ "packages/isomorphic/trace/traceModernizer.ts"() { "use strict"; TraceVersionError = class extends Error { constructor(message) { super(message); this.name = "TraceVersionError"; } }; latestVersion = 8; TraceModernizer = class { constructor(contextEntry, snapshotStorage) { this._actionMap = /* @__PURE__ */ new Map(); this._pageEntries = /* @__PURE__ */ new Map(); this._jsHandles = /* @__PURE__ */ new Map(); this._consoleObjects = /* @__PURE__ */ new Map(); this._contextEntry = contextEntry; this._snapshotStorage = snapshotStorage; } appendTrace(trace) { for (const line of trace.split("\n")) this._appendEvent(line); } actions() { return [...this._actionMap.values()]; } _pageEntry(pageId4) { let pageEntry = this._pageEntries.get(pageId4); if (!pageEntry) { pageEntry = { pageId: pageId4, screencastFrames: [] }; this._pageEntries.set(pageId4, pageEntry); this._contextEntry.pages.push(pageEntry); } return pageEntry; } _appendEvent(line) { if (!line) return; const events = this._modernize(JSON.parse(line)); for (const event of events) this._innerAppendEvent(event); } _innerAppendEvent(event) { const contextEntry = this._contextEntry; switch (event.type) { case "context-options": { if (event.version > latestVersion) throw new TraceVersionError("The trace was created by a newer version of Playwright and is not supported by this version of the viewer. Please use latest Playwright to open the trace."); this._version = event.version; contextEntry.origin = event.origin; contextEntry.browserName = event.browserName; contextEntry.channel = event.channel; contextEntry.title = event.title; contextEntry.platform = event.platform; contextEntry.playwrightVersion = event.playwrightVersion; contextEntry.wallTime = event.wallTime; contextEntry.startTime = event.monotonicTime; contextEntry.sdkLanguage = event.sdkLanguage; contextEntry.options = event.options; contextEntry.testIdAttributeName = event.testIdAttributeName; contextEntry.contextId = event.contextId ?? ""; contextEntry.testTimeout = event.testTimeout; break; } case "screencast-frame": { this._pageEntry(event.pageId).screencastFrames.push(event); break; } case "before": { this._actionMap.set(event.callId, { ...event, type: "action", endTime: 0, log: [] }); break; } case "input": { const existing = this._actionMap.get(event.callId); existing.inputSnapshot = event.inputSnapshot; existing.point = event.point; break; } case "log": { const existing = this._actionMap.get(event.callId); if (!existing) return; existing.log.push({ time: event.time, message: event.message }); break; } case "after": { const existing = this._actionMap.get(event.callId); existing.afterSnapshot = event.afterSnapshot; existing.endTime = event.endTime; existing.result = event.result; existing.error = event.error; existing.attachments = event.attachments; existing.annotations = event.annotations; if (event.point) existing.point = event.point; break; } case "action": { this._actionMap.set(event.callId, { ...event, log: [] }); break; } case "event": { contextEntry.events.push(event); break; } case "stdout": { contextEntry.stdio.push(event); break; } case "stderr": { contextEntry.stdio.push(event); break; } case "error": { contextEntry.errors.push(event); break; } case "console": { contextEntry.events.push(event); break; } case "resource-snapshot": this._snapshotStorage.addResource(this._contextEntry.contextId, event.snapshot); contextEntry.resources.push(event.snapshot); break; case "frame-snapshot": this._snapshotStorage.addFrameSnapshot(this._contextEntry.contextId, event.snapshot, this._pageEntry(event.snapshot.pageId).screencastFrames); break; } if ("pageId" in event && event.pageId) this._pageEntry(event.pageId); if (event.type === "action" || event.type === "before") contextEntry.startTime = Math.min(contextEntry.startTime, event.startTime); if (event.type === "action" || event.type === "after") contextEntry.endTime = Math.max(contextEntry.endTime, event.endTime); if (event.type === "event") { contextEntry.startTime = Math.min(contextEntry.startTime, event.time); contextEntry.endTime = Math.max(contextEntry.endTime, event.time); } if (event.type === "screencast-frame") { contextEntry.startTime = Math.min(contextEntry.startTime, event.timestamp); contextEntry.endTime = Math.max(contextEntry.endTime, event.timestamp); } } _processedContextCreatedEvent() { return this._version !== void 0; } _modernize(event) { let version3 = this._version ?? event.version ?? 6; let events = [event]; for (; version3 < latestVersion; ++version3) events = this[`_modernize_${version3}_to_${version3 + 1}`].call(this, events); return events; } _modernize_0_to_1(events) { for (const event of events) { if (event.type !== "action") continue; if (typeof event.metadata.error === "string") event.metadata.error = { error: { name: "Error", message: event.metadata.error } }; } return events; } _modernize_1_to_2(events) { for (const event of events) { if (event.type !== "frame-snapshot" || !event.snapshot.isMainFrame) continue; event.snapshot.viewport = this._contextEntry.options?.viewport || { width: 1280, height: 720 }; } return events; } _modernize_2_to_3(events) { for (const event of events) { if (event.type !== "resource-snapshot" || event.snapshot.request) continue; const resource = event.snapshot; event.snapshot = { _frameref: resource.frameId, request: { url: resource.url, method: resource.method, headers: resource.requestHeaders, postData: resource.requestSha1 ? { _sha1: resource.requestSha1 } : void 0 }, response: { status: resource.status, headers: resource.responseHeaders, content: { mimeType: resource.contentType, _sha1: resource.responseSha1 } }, _monotonicTime: resource.timestamp }; } return events; } _modernize_3_to_4(events) { const result2 = []; for (const event of events) { const e = this._modernize_event_3_to_4(event); if (e) result2.push(e); } return result2; } _modernize_event_3_to_4(event) { if (event.type !== "action" && event.type !== "event") { return event; } const metadata = event.metadata; if (metadata.internal || metadata.method.startsWith("tracing")) return null; if (event.type === "event") { if (metadata.method === "__create__" && metadata.type === "ConsoleMessage") { return { type: "object", class: metadata.type, guid: metadata.params.guid, initializer: metadata.params.initializer }; } return { type: "event", time: metadata.startTime, class: metadata.type, method: metadata.method, params: metadata.params, pageId: metadata.pageId }; } return { type: "action", callId: metadata.id, startTime: metadata.startTime, endTime: metadata.endTime, apiName: metadata.apiName || metadata.type + "." + metadata.method, class: metadata.type, method: metadata.method, params: metadata.params, // eslint-disable-next-line no-restricted-globals wallTime: metadata.wallTime || Date.now(), log: metadata.log, beforeSnapshot: metadata.snapshots.find((s) => s.title === "before")?.snapshotName, inputSnapshot: metadata.snapshots.find((s) => s.title === "input")?.snapshotName, afterSnapshot: metadata.snapshots.find((s) => s.title === "after")?.snapshotName, error: metadata.error?.error, result: metadata.result, point: metadata.point, pageId: metadata.pageId }; } _modernize_4_to_5(events) { const result2 = []; for (const event of events) { const e = this._modernize_event_4_to_5(event); if (e) result2.push(e); } return result2; } _modernize_event_4_to_5(event) { if (event.type === "event" && event.method === "__create__" && event.class === "JSHandle") this._jsHandles.set(event.params.guid, event.params.initializer); if (event.type === "object") { if (event.class !== "ConsoleMessage") return null; const args = event.initializer.args?.map((arg) => { if (arg.guid) { const handle = this._jsHandles.get(arg.guid); return { preview: handle?.preview || "", value: "" }; } return { preview: arg.preview || "", value: arg.value || "" }; }); this._consoleObjects.set(event.guid, { type: event.initializer.type, text: event.initializer.text, location: event.initializer.location, args }); return null; } if (event.type === "event" && event.method === "console") { const consoleMessage = this._consoleObjects.get(event.params.message?.guid || ""); if (!consoleMessage) return null; return { type: "console", time: event.time, pageId: event.pageId, messageType: consoleMessage.type, text: consoleMessage.text, args: consoleMessage.args, location: consoleMessage.location }; } return event; } _modernize_5_to_6(events) { const result2 = []; for (const event of events) { result2.push(event); if (event.type !== "after" || !event.log.length) continue; for (const log2 of event.log) { result2.push({ type: "log", callId: event.callId, message: log2, time: -1 }); } } return result2; } _modernize_6_to_7(events) { const result2 = []; if (!this._processedContextCreatedEvent() && events[0].type !== "context-options") { const event = { type: "context-options", origin: "testRunner", version: 6, browserName: "", options: {}, platform: "unknown", wallTime: 0, monotonicTime: 0, sdkLanguage: "javascript", contextId: "" }; result2.push(event); } for (const event of events) { if (event.type === "context-options") { result2.push({ ...event, monotonicTime: 0, origin: "library", contextId: "" }); continue; } if (event.type === "before" || event.type === "action") { if (!this._contextEntry.wallTime) this._contextEntry.wallTime = event.wallTime; const eventAsV6 = event; const eventAsV7 = event; eventAsV7.stepId = `${eventAsV6.apiName}@${eventAsV6.wallTime}`; result2.push(eventAsV7); } else { result2.push(event); } } return result2; } _modernize_7_to_8(events) { const result2 = []; for (const event of events) { if (event.type === "before" || event.type === "action") { const eventAsV7 = event; const eventAsV8 = event; if (eventAsV7.apiName) { eventAsV8.title = eventAsV7.apiName; delete eventAsV8.apiName; } eventAsV8.stepId = eventAsV7.stepId ?? eventAsV7.callId; result2.push(eventAsV8); } else { result2.push(event); } } return result2; } }; } }); // packages/isomorphic/trace/traceLoader.ts function stripEncodingFromContentType(contentType) { const charset = contentType.match(/^(.*);\s*charset=.*$/); if (charset) return charset[1]; return contentType; } function createEmptyContext() { return { origin: "testRunner", startTime: Number.MAX_SAFE_INTEGER, wallTime: Number.MAX_SAFE_INTEGER, endTime: 0, browserName: "", options: { deviceScaleFactor: 1, isMobile: false, viewport: { width: 1280, height: 800 } }, pages: [], resources: [], actions: [], events: [], errors: [], stdio: [], hasSource: false, contextId: "" }; } var TraceLoader; var init_traceLoader = __esm({ "packages/isomorphic/trace/traceLoader.ts"() { "use strict"; init_traceUtils(); init_snapshotStorage(); init_traceModernizer(); TraceLoader = class { constructor() { this.contextEntries = []; this._resourceToContentType = /* @__PURE__ */ new Map(); } async load(backend, traceFile, unzipProgress) { this._backend = backend; const prefix = traceFile?.match(/(.+)\.trace$/)?.[1]; const prefixes = []; let hasSource = false; for (const entryName of await this._backend.entryNames()) { const match = entryName.match(/(.+)\.trace$/); if (match && (!prefix || prefix === match[1])) prefixes.push(match[1] || ""); if (entryName.includes("src@")) hasSource = true; } if (!prefixes.length) throw new Error("Cannot find .trace file"); this._snapshotStorage = new SnapshotStorage(); const total = prefixes.length * 3; let done = 0; for (const prefix2 of prefixes) { const contextEntry = createEmptyContext(); contextEntry.hasSource = hasSource; const modernizer = new TraceModernizer(contextEntry, this._snapshotStorage); const trace = await this._backend.readText(prefix2 + ".trace") || ""; modernizer.appendTrace(trace); unzipProgress?.(++done, total); const network = await this._backend.readText(prefix2 + ".network") || ""; modernizer.appendTrace(network); unzipProgress?.(++done, total); contextEntry.actions = modernizer.actions().sort((a1, a2) => a1.startTime - a2.startTime); if (!backend.isLive()) { for (const action of contextEntry.actions.slice().reverse()) { if (!action.endTime && !action.error) { for (const a of contextEntry.actions) { if (a.parentId === action.callId && action.endTime < a.endTime) action.endTime = a.endTime; } } } } const stacks = await this._backend.readText(prefix2 + ".stacks"); if (stacks) { const callMetadata = parseClientSideCallMetadata(JSON.parse(stacks)); for (const action of contextEntry.actions) action.stack = action.stack || callMetadata.get(action.callId); } unzipProgress?.(++done, total); for (const resource of contextEntry.resources) { if (resource.request.postData?._sha1) this._resourceToContentType.set(resource.request.postData._sha1, stripEncodingFromContentType(resource.request.postData.mimeType)); if (resource.response.content?._sha1) this._resourceToContentType.set(resource.response.content._sha1, stripEncodingFromContentType(resource.response.content.mimeType)); } this.contextEntries.push(contextEntry); } this._snapshotStorage.finalize(); } async hasEntry(filename) { return this._backend.hasEntry(filename); } async resourceForSha1(sha1) { const blob = await this._backend.readBlob("resources/" + sha1); const contentType = this._resourceToContentType.get(sha1); if (!blob || contentType === void 0 || contentType === "x-unknown") return blob; return new Blob([blob], { type: contentType }); } storage() { return this._snapshotStorage; } }; } }); // packages/isomorphic/trace/traceModel.ts function indexModel(context2) { for (const page of context2.pages) page[contextSymbol] = context2; for (let i = 0; i < context2.actions.length; ++i) { const action = context2.actions[i]; action[contextSymbol] = context2; } let lastNonRouteAction = void 0; for (let i = context2.actions.length - 1; i >= 0; i--) { const action = context2.actions[i]; action[nextInContextSymbol] = lastNonRouteAction; if (action.class !== "Route") lastNonRouteAction = action; } for (const event of context2.events) event[contextSymbol] = context2; for (const resource of context2.resources) resource[contextSymbol] = context2; } function mergeActionsAndUpdateTiming(contexts) { const result2 = []; const actions = mergeActionsAndUpdateTimingSameTrace(contexts); result2.push(...actions); result2.sort((a1, a2) => { if (a2.parentId === a1.callId) return 1; if (a1.parentId === a2.callId) return -1; return a1.endTime - a2.endTime; }); for (let i = 1; i < result2.length; ++i) result2[i][prevByEndTimeSymbol] = result2[i - 1]; result2.sort((a1, a2) => { if (a2.parentId === a1.callId) return -1; if (a1.parentId === a2.callId) return 1; return a1.startTime - a2.startTime; }); for (let i = 0; i + 1 < result2.length; ++i) result2[i][nextByStartTimeSymbol] = result2[i + 1]; return result2; } function mergeActionsAndUpdateTimingSameTrace(contexts) { const map = /* @__PURE__ */ new Map(); const libraryContexts = contexts.filter((context2) => context2.origin === "library"); const testRunnerContexts = contexts.filter((context2) => context2.origin === "testRunner"); if (!testRunnerContexts.length || !libraryContexts.length) { return contexts.map((context2) => { return context2.actions.map((action) => ({ ...action, context: context2 })); }).flat(); } for (const context2 of libraryContexts) { for (const action of context2.actions) { map.set(action.stepId || `tmp-step@${++lastTmpStepId}`, { ...action, context: context2 }); } } const delta = monotonicTimeDeltaBetweenLibraryAndRunner(testRunnerContexts, map); if (delta) adjustMonotonicTime(libraryContexts, delta); const nonPrimaryIdToPrimaryId = /* @__PURE__ */ new Map(); for (const context2 of testRunnerContexts) { for (const action of context2.actions) { const existing = action.stepId && map.get(action.stepId); if (existing) { nonPrimaryIdToPrimaryId.set(action.callId, existing.callId); if (action.error) existing.error = action.error; if (action.attachments) existing.attachments = action.attachments; if (action.annotations) existing.annotations = action.annotations; if (action.parentId) existing.parentId = nonPrimaryIdToPrimaryId.get(action.parentId) ?? action.parentId; if (action.group) existing.group = action.group; existing.startTime = action.startTime; existing.endTime = action.endTime; continue; } if (action.parentId) action.parentId = nonPrimaryIdToPrimaryId.get(action.parentId) ?? action.parentId; map.set(action.stepId || `tmp-step@${++lastTmpStepId}`, { ...action, context: context2 }); } } return [...map.values()]; } function adjustMonotonicTime(contexts, monotonicTimeDelta) { for (const context2 of contexts) { context2.startTime += monotonicTimeDelta; context2.endTime += monotonicTimeDelta; for (const action of context2.actions) { if (action.startTime) action.startTime += monotonicTimeDelta; if (action.endTime) action.endTime += monotonicTimeDelta; } for (const event of context2.events) event.time += monotonicTimeDelta; for (const event of context2.stdio) event.timestamp += monotonicTimeDelta; for (const page of context2.pages) { for (const frame of page.screencastFrames) frame.timestamp += monotonicTimeDelta; } for (const resource of context2.resources) { if (resource._monotonicTime) resource._monotonicTime += monotonicTimeDelta; } } } function monotonicTimeDeltaBetweenLibraryAndRunner(nonPrimaryContexts, libraryActions) { for (const context2 of nonPrimaryContexts) { for (const action of context2.actions) { if (!action.startTime) continue; const libraryAction = action.stepId ? libraryActions.get(action.stepId) : void 0; if (libraryAction) return action.startTime - libraryAction.startTime; } } return 0; } function buildActionTree(actions) { const itemMap = /* @__PURE__ */ new Map(); for (const action of actions) { itemMap.set(action.callId, { id: action.callId, parent: void 0, children: [], action }); } const rootItem = { action: { ...kFakeRootAction }, id: "", parent: void 0, children: [] }; for (const item of itemMap.values()) { rootItem.action.startTime = Math.min(rootItem.action.startTime, item.action.startTime); rootItem.action.endTime = Math.max(rootItem.action.endTime, item.action.endTime); const parent = item.action.parentId ? itemMap.get(item.action.parentId) || rootItem : rootItem; parent.children.push(item); item.parent = parent; } const inheritStack = (item) => { for (const child of item.children) { child.action.stack = child.action.stack ?? item.action.stack; inheritStack(child); } }; inheritStack(rootItem); return { rootItem, itemMap }; } function context(action) { return action[contextSymbol]; } function nextInContext(action) { return action[nextInContextSymbol]; } function previousActionByEndTime(action) { return action[prevByEndTimeSymbol]; } function nextActionByStartTime(action) { return action[nextByStartTimeSymbol]; } function stats(action) { let errors = 0; let warnings = 0; for (const event of eventsForAction(action)) { if (event.type === "console") { const type3 = event.messageType; if (type3 === "warning") ++warnings; else if (type3 === "error") ++errors; } if (event.type === "event" && event.method === "pageError") ++errors; } return { errors, warnings }; } function eventsForAction(action) { let result2 = action[eventsSymbol]; if (result2) return result2; const nextAction = nextInContext(action); result2 = context(action).events.filter((event) => { return event.time >= action.startTime && (!nextAction || event.time < nextAction.startTime); }); action[eventsSymbol] = result2; return result2; } function collectSources(actions, errorDescriptors) { const result2 = /* @__PURE__ */ new Map(); for (const action of actions) { for (const frame of action.stack || []) { let source11 = result2.get(frame.file); if (!source11) { source11 = { errors: [], content: void 0 }; result2.set(frame.file, source11); } } } for (const error of errorDescriptors) { const { action, stack, message } = error; if (!action || !stack) continue; result2.get(stack[0].file)?.errors.push({ line: stack[0].line || 0, message }); } return result2; } var contextSymbol, nextInContextSymbol, prevByEndTimeSymbol, nextByStartTimeSymbol, eventsSymbol, TraceModel, lastTmpStepId, kFakeRootAction; var init_traceModel = __esm({ "packages/isomorphic/trace/traceModel.ts"() { "use strict"; init_protocolFormatter(); contextSymbol = Symbol("context"); nextInContextSymbol = Symbol("nextInContext"); prevByEndTimeSymbol = Symbol("prevByEndTime"); nextByStartTimeSymbol = Symbol("nextByStartTime"); eventsSymbol = Symbol("events"); TraceModel = class { constructor(traceUri, contexts) { contexts.forEach((contextEntry) => indexModel(contextEntry)); const libraryContext = contexts.find((context2) => context2.origin === "library"); this.traceUri = traceUri; this.browserName = libraryContext?.browserName || ""; this.sdkLanguage = libraryContext?.sdkLanguage; this.channel = libraryContext?.channel; this.testIdAttributeName = libraryContext?.testIdAttributeName; this.platform = libraryContext?.platform || ""; this.playwrightVersion = contexts.find((c) => c.playwrightVersion)?.playwrightVersion; this.title = libraryContext?.title || ""; this.options = libraryContext?.options || {}; this.testTimeout = contexts.find((c) => c.origin === "testRunner")?.testTimeout; this.actions = mergeActionsAndUpdateTiming(contexts); this.pages = [].concat(...contexts.map((c) => c.pages)); this.wallTime = contexts.map((c) => c.wallTime).reduce((prev, cur) => Math.min(prev || Number.MAX_VALUE, cur), Number.MAX_VALUE); this.startTime = contexts.map((c) => c.startTime).reduce((prev, cur) => Math.min(prev, cur), Number.MAX_VALUE); this.endTime = contexts.map((c) => c.endTime).reduce((prev, cur) => Math.max(prev, cur), Number.MIN_VALUE); this.events = [].concat(...contexts.map((c) => c.events)); this.stdio = [].concat(...contexts.map((c) => c.stdio)); this.errors = [].concat(...contexts.map((c) => c.errors)); this.hasSource = contexts.some((c) => c.hasSource); this.hasStepData = contexts.some((context2) => context2.origin === "testRunner"); this.resources = [...contexts.map((c) => c.resources)].flat().map((entry) => ({ ...entry, id: `${entry.pageref}-${entry.startedDateTime}-${entry.request.url}` })); this.attachments = this.actions.flatMap((action) => action.attachments?.map((attachment) => ({ ...attachment, callId: action.callId, traceUri })) ?? []); this.visibleAttachments = this.attachments.filter((attachment) => !attachment.name.startsWith("_")); this.events.sort((a1, a2) => a1.time - a2.time); this.resources.sort((a1, a2) => a1._monotonicTime - a2._monotonicTime); this.errorDescriptors = this.hasStepData ? this._errorDescriptorsFromTestRunner() : this._errorDescriptorsFromActions(); this.sources = collectSources(this.actions, this.errorDescriptors); this.actionCounters = /* @__PURE__ */ new Map(); for (const action of this.actions) { action.group = action.group ?? getActionGroup({ type: action.class, method: action.method }); if (action.group) this.actionCounters.set(action.group, 1 + (this.actionCounters.get(action.group) || 0)); } } createRelativeUrl(path59) { const url2 = new URL("http://localhost/" + path59); url2.searchParams.set("trace", this.traceUri); return url2.toString().substring("http://localhost/".length); } failedAction() { return this.actions.findLast((a) => a.error); } filteredActions(actionsFilter) { const filter = new Set(actionsFilter); return this.actions.filter((action) => !action.group || filter.has(action.group)); } renderActionTree(filter) { const actions = this.filteredActions(filter ?? []); const { rootItem } = buildActionTree(actions); const actionTree = []; const visit = (actionItem, indent) => { const title = renderTitleForCall({ ...actionItem.action, type: actionItem.action.class }); actionTree.push(`${indent}${title || actionItem.id}`); for (const child of actionItem.children) visit(child, indent + " "); }; rootItem.children.forEach((a) => visit(a, "")); return actionTree; } _errorDescriptorsFromActions() { const errors = []; for (const action of this.actions || []) { if (!action.error?.message) continue; errors.push({ action, stack: action.stack, message: action.error.message }); } return errors; } _errorDescriptorsFromTestRunner() { return this.errors.filter((e) => !!e.message).map((error, i) => ({ stack: error.stack, message: error.message })); } }; lastTmpStepId = 0; kFakeRootAction = { type: "action", callId: "", startTime: 0, endTime: 0, class: "", method: "", params: {}, log: [], context: { origin: "library", startTime: 0, endTime: 0, browserName: "", wallTime: 0, options: {}, pages: [], resources: [], actions: [], events: [], stdio: [], errors: [], hasSource: false, contextId: "" } }; } }); // packages/isomorphic/yaml.ts function yamlEscapeKeyIfNeeded(str) { if (!yamlStringNeedsQuotes(str)) return str; return `'` + str.replace(/'/g, `''`) + `'`; } function yamlEscapeValueIfNeeded(str) { if (!yamlStringNeedsQuotes(str)) return str; return '"' + str.replace(/[\\"\x00-\x1f\x7f-\x9f]/g, (c) => { switch (c) { case "\\": return "\\\\"; case '"': return '\\"'; case "\b": return "\\b"; case "\f": return "\\f"; case "\n": return "\\n"; case "\r": return "\\r"; case " ": return "\\t"; default: const code = c.charCodeAt(0); return "\\x" + code.toString(16).padStart(2, "0"); } }) + '"'; } function yamlStringNeedsQuotes(str) { if (str.length === 0) return true; if (/^\s|\s$/.test(str)) return true; if (/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/.test(str)) return true; if (/^-/.test(str)) return true; if (/[\n:](\s|$)/.test(str)) return true; if (/\s#/.test(str)) return true; if (/[\n\r]/.test(str)) return true; if (/^[&*\],?!>|@"'#%]/.test(str)) return true; if (/[{}`]/.test(str)) return true; if (/^\[/.test(str)) return true; if (!isNaN(Number(str)) || ["y", "n", "yes", "no", "true", "false", "on", "off", "null"].includes(str.toLowerCase())) return true; return false; } var init_yaml = __esm({ "packages/isomorphic/yaml.ts"() { "use strict"; } }); // packages/isomorphic/index.ts var isomorphic_exports = {}; __export(isomorphic_exports, { CSharpLocatorFactory: () => CSharpLocatorFactory, DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT: () => DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT, DEFAULT_PLAYWRIGHT_TIMEOUT: () => DEFAULT_PLAYWRIGHT_TIMEOUT, InvalidSelectorError: () => InvalidSelectorError, JavaLocatorFactory: () => JavaLocatorFactory, JavaScriptLocatorFactory: () => JavaScriptLocatorFactory, JsonlLocatorFactory: () => JsonlLocatorFactory, KeyParser: () => KeyParser, LongStandingScope: () => LongStandingScope, ManualPromise: () => ManualPromise, MultiMap: () => MultiMap, ParserError: () => ParserError, PythonLocatorFactory: () => PythonLocatorFactory, Semaphore: () => Semaphore, SnapshotServer: () => SnapshotServer, SnapshotStorage: () => SnapshotStorage, TraceLoader: () => TraceLoader, TraceModel: () => TraceModel, ansiRegex: () => ansiRegex, ariaNodesEqual: () => ariaNodesEqual, asLocator: () => asLocator, asLocatorDescription: () => asLocatorDescription, asLocators: () => asLocators, assert: () => assert, base64ByteLength: () => base64ByteLength, buildActionTree: () => buildActionTree, bytesToString: () => bytesToString, cacheNormalizedWhitespaces: () => cacheNormalizedWhitespaces, captureRawStack: () => captureRawStack, constructURLBasedOnBaseURL: () => constructURLBasedOnBaseURL, context: () => context, customCSSNames: () => customCSSNames, deserializeURLMatch: () => deserializeURLMatch, escapeForAttributeSelector: () => escapeForAttributeSelector, escapeForTextSelector: () => escapeForTextSelector, escapeHTML: () => escapeHTML, escapeHTMLAttribute: () => escapeHTMLAttribute, escapeRegExp: () => escapeRegExp, escapeTemplateString: () => escapeTemplateString, escapeWithQuotes: () => escapeWithQuotes, eventsForAction: () => eventsForAction, findNewNode: () => findNewNode, formatObject: () => formatObject, formatObjectOrVoid: () => formatObjectOrVoid, formatProtocolParam: () => formatProtocolParam, getActionGroup: () => getActionGroup, getExtensionForMimeType: () => getExtensionForMimeType, getMetainfo: () => getMetainfo, getMimeTypeForPath: () => getMimeTypeForPath, globToRegexPattern: () => globToRegexPattern, hasPointerCursor: () => hasPointerCursor, headersArrayToObject: () => headersArrayToObject, headersObjectToArray: () => headersObjectToArray, isError: () => isError, isHttpUrl: () => isHttpUrl, isInvalidSelectorError: () => isInvalidSelectorError, isJsonMimeType: () => isJsonMimeType, isObject: () => isObject, isRegExp: () => isRegExp, isRegexString: () => isRegexString, isString: () => isString, isTextualMimeType: () => isTextualMimeType, isURLPattern: () => isURLPattern, isXmlMimeType: () => isXmlMimeType, locatorCustomDescription: () => locatorCustomDescription, locatorOrSelectorAsSelector: () => locatorOrSelectorAsSelector, longestCommonSubstring: () => longestCommonSubstring, methodMetainfo: () => methodMetainfo, monotonicTime: () => monotonicTime, msToString: () => msToString, nextActionByStartTime: () => nextActionByStartTime, noColors: () => noColors, normalizeEscapedRegexQuotes: () => normalizeEscapedRegexQuotes, normalizeWhiteSpace: () => normalizeWhiteSpace, padImageToSize: () => padImageToSize, parseAriaSnapshot: () => parseAriaSnapshot, parseAriaSnapshotUnsafe: () => parseAriaSnapshotUnsafe, parseAttributeSelector: () => parseAttributeSelector, parseCSS: () => parseCSS, parseClientSideCallMetadata: () => parseClientSideCallMetadata, parseErrorStack: () => parseErrorStack, parseRegex: () => parseRegex, parseSelector: () => parseSelector, parseStackFrame: () => parseStackFrame, pollAgainstDeadline: () => pollAgainstDeadline, previousActionByEndTime: () => previousActionByEndTime, quoteCSSAttributeValue: () => quoteCSSAttributeValue, raceAgainstDeadline: () => raceAgainstDeadline, renderTitleForCall: () => renderTitleForCall, resolveGlobToRegexPattern: () => resolveGlobToRegexPattern, rewriteErrorMessage: () => rewriteErrorMessage, scaleImageToSize: () => scaleImageToSize, serializeClientSideCallMetadata: () => serializeClientSideCallMetadata, serializeExpectedTextValues: () => serializeExpectedTextValues, serializeSelector: () => serializeSelector, serializeURLMatch: () => serializeURLMatch, serializeURLPattern: () => serializeURLPattern, setTimeOrigin: () => setTimeOrigin, signalToPromise: () => signalToPromise, splitErrorMessage: () => splitErrorMessage, splitSelectorByFrame: () => splitSelectorByFrame, stats: () => stats, stringifySelector: () => stringifySelector, stringifyStackFrames: () => stringifyStackFrames, stripAnsiEscapes: () => stripAnsiEscapes, textValue: () => textValue, timeOrigin: () => timeOrigin, toSnakeCase: () => toSnakeCase, toTitleCase: () => toTitleCase, tomlArray: () => tomlArray, tomlBasicString: () => tomlBasicString, tomlMultilineBasicString: () => tomlMultilineBasicString, trimString: () => trimString, trimStringWithEllipsis: () => trimStringWithEllipsis, unsafeLocatorOrSelectorAsSelector: () => unsafeLocatorOrSelectorAsSelector, urlMatches: () => urlMatches, urlMatchesEqual: () => urlMatchesEqual, validate: () => validate, visitAllSelectorParts: () => visitAllSelectorParts, webColors: () => webColors, yamlEscapeKeyIfNeeded: () => yamlEscapeKeyIfNeeded, yamlEscapeValueIfNeeded: () => yamlEscapeValueIfNeeded }); var init_isomorphic = __esm({ "packages/isomorphic/index.ts"() { "use strict"; init_ariaSnapshot(); init_expectUtils(); init_assert(); init_base64(); init_colors(); init_headers(); init_imageUtils(); init_jsonSchema(); init_locatorGenerators(); init_manualPromise(); init_mimeType(); init_multimap(); init_protocolFormatter(); init_protocolMetainfo(); init_rtti(); init_semaphore(); init_stackTrace(); init_stringUtils(); init_formatUtils(); init_time(); init_timeoutRunner(); init_snapshotServer(); init_urlMatch(); init_cssParser(); init_locatorParser(); init_selectorParser(); init_snapshotStorage(); init_traceLoader(); init_traceModel(); init_traceUtils(); init_yaml(); } }); // packages/utils/ascii.ts function wrapInASCIIBox(text2, padding = 0) { const lines = text2.split("\n"); const maxLength = Math.max(...lines.map((line) => line.length)); return [ "\u2554" + "\u2550".repeat(maxLength + padding * 2) + "\u2557", ...lines.map((line) => "\u2551" + " ".repeat(padding) + line + " ".repeat(maxLength - line.length + padding) + "\u2551"), "\u255A" + "\u2550".repeat(maxLength + padding * 2) + "\u255D" ].join("\n"); } function jsonStringifyForceASCII(object) { return JSON.stringify(object).replace( /[\u007f-\uffff]/g, (c) => "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4) ); } var init_ascii = __esm({ "packages/utils/ascii.ts"() { "use strict"; } }); // packages/utils/chromiumChannels.ts function defaultUserDataDirForChannel(channel) { return channelToDefaultUserDataDir.get(channel)?.[process.platform]; } function isChromiumChannelName(channel) { return channelToDefaultUserDataDir.has(channel); } var import_os, import_path, channelToDefaultUserDataDir; var init_chromiumChannels = __esm({ "packages/utils/chromiumChannels.ts"() { "use strict"; import_os = __toESM(require("os")); import_path = __toESM(require("path")); channelToDefaultUserDataDir = /* @__PURE__ */ new Map([ ["chrome", { "linux": import_path.default.join(import_os.default.homedir(), ".config", "google-chrome"), "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Google", "Chrome"), "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Google", "Chrome", "User Data") }], ["chrome-beta", { "linux": import_path.default.join(import_os.default.homedir(), ".config", "google-chrome-beta"), "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Google", "Chrome Beta"), "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Google", "Chrome Beta", "User Data") }], ["chrome-dev", { "linux": import_path.default.join(import_os.default.homedir(), ".config", "google-chrome-unstable"), "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Google", "Chrome Dev"), "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Google", "Chrome Dev", "User Data") }], ["chrome-canary", { "linux": import_path.default.join(import_os.default.homedir(), ".config", "google-chrome-canary"), "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Google", "Chrome Canary"), "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Google", "Chrome SxS", "User Data") }], ["msedge", { "linux": import_path.default.join(import_os.default.homedir(), ".config", "microsoft-edge"), "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Microsoft Edge"), "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Microsoft", "Edge", "User Data") }], ["msedge-beta", { "linux": import_path.default.join(import_os.default.homedir(), ".config", "microsoft-edge-beta"), "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Microsoft Edge Beta"), "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Microsoft", "Edge Beta", "User Data") }], ["msedge-dev", { "linux": import_path.default.join(import_os.default.homedir(), ".config", "microsoft-edge-dev"), "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Microsoft Edge Dev"), "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Microsoft", "Edge Dev", "User Data") }], ["msedge-canary", { "linux": import_path.default.join(import_os.default.homedir(), ".config", "microsoft-edge-canary"), "darwin": import_path.default.join(import_os.default.homedir(), "Library", "Application Support", "Microsoft Edge Canary"), "win32": import_path.default.join(process.env.LOCALAPPDATA || import_path.default.join(import_os.default.homedir(), "AppData", "Local"), "Microsoft", "Edge SxS", "User Data") }] ]); } }); // packages/utils/third_party/pixelmatch.js var require_pixelmatch = __commonJS({ "packages/utils/third_party/pixelmatch.js"(exports2, module2) { "use strict"; module2.exports = pixelmatch2; var defaultOptions = { threshold: 0.1, // matching threshold (0 to 1); smaller is more sensitive includeAA: false, // whether to skip anti-aliasing detection alpha: 0.1, // opacity of original image in diff output aaColor: [255, 255, 0], // color of anti-aliased pixels in diff output diffColor: [255, 0, 0], // color of different pixels in diff output diffColorAlt: null, // whether to detect dark on light differences between img1 and img2 and set an alternative color to differentiate between the two diffMask: false // draw the diff over a transparent background (a mask) }; function pixelmatch2(img1, img2, output, width, height, options) { if (!isPixelData(img1) || !isPixelData(img2) || output && !isPixelData(output)) throw new Error("Image data: Uint8Array, Uint8ClampedArray or Buffer expected."); if (img1.length !== img2.length || output && output.length !== img1.length) throw new Error("Image sizes do not match."); if (img1.length !== width * height * 4) throw new Error("Image data size does not match width/height."); options = Object.assign({}, defaultOptions, options); const len = width * height; const a32 = new Uint32Array(img1.buffer, img1.byteOffset, len); const b32 = new Uint32Array(img2.buffer, img2.byteOffset, len); let identical = true; for (let i = 0; i < len; i++) { if (a32[i] !== b32[i]) { identical = false; break; } } if (identical) { if (output && !options.diffMask) { for (let i = 0; i < len; i++) drawGrayPixel(img1, 4 * i, options.alpha, output); } return 0; } const maxDelta = 35215 * options.threshold * options.threshold; let diff2 = 0; for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { const pos = (y * width + x) * 4; const delta = colorDelta(img1, img2, pos, pos); if (Math.abs(delta) > maxDelta) { if (!options.includeAA && (antialiased(img1, x, y, width, height, img2) || antialiased(img2, x, y, width, height, img1))) { if (output && !options.diffMask) drawPixel2(output, pos, ...options.aaColor); } else { if (output) { drawPixel2(output, pos, ...delta < 0 && options.diffColorAlt || options.diffColor); } diff2++; } } else if (output) { if (!options.diffMask) drawGrayPixel(img1, pos, options.alpha, output); } } } return diff2; } function isPixelData(arr) { return ArrayBuffer.isView(arr) && arr.constructor.BYTES_PER_ELEMENT === 1; } function antialiased(img, x1, y1, width, height, img2) { const x0 = Math.max(x1 - 1, 0); const y0 = Math.max(y1 - 1, 0); const x2 = Math.min(x1 + 1, width - 1); const y2 = Math.min(y1 + 1, height - 1); const pos = (y1 * width + x1) * 4; let zeroes = x1 === x0 || x1 === x2 || y1 === y0 || y1 === y2 ? 1 : 0; let min = 0; let max = 0; let minX, minY, maxX, maxY; for (let x = x0; x <= x2; x++) { for (let y = y0; y <= y2; y++) { if (x === x1 && y === y1) continue; const delta = colorDelta(img, img, pos, (y * width + x) * 4, true); if (delta === 0) { zeroes++; if (zeroes > 2) return false; } else if (delta < min) { min = delta; minX = x; minY = y; } else if (delta > max) { max = delta; maxX = x; maxY = y; } } } if (min === 0 || max === 0) return false; return hasManySiblings(img, minX, minY, width, height) && hasManySiblings(img2, minX, minY, width, height) || hasManySiblings(img, maxX, maxY, width, height) && hasManySiblings(img2, maxX, maxY, width, height); } function hasManySiblings(img, x1, y1, width, height) { const x0 = Math.max(x1 - 1, 0); const y0 = Math.max(y1 - 1, 0); const x2 = Math.min(x1 + 1, width - 1); const y2 = Math.min(y1 + 1, height - 1); const pos = (y1 * width + x1) * 4; let zeroes = x1 === x0 || x1 === x2 || y1 === y0 || y1 === y2 ? 1 : 0; for (let x = x0; x <= x2; x++) { for (let y = y0; y <= y2; y++) { if (x === x1 && y === y1) continue; const pos2 = (y * width + x) * 4; if (img[pos] === img[pos2] && img[pos + 1] === img[pos2 + 1] && img[pos + 2] === img[pos2 + 2] && img[pos + 3] === img[pos2 + 3]) zeroes++; if (zeroes > 2) return true; } } return false; } function colorDelta(img1, img2, k, m, yOnly) { let r1 = img1[k + 0]; let g1 = img1[k + 1]; let b1 = img1[k + 2]; let a1 = img1[k + 3]; let r2 = img2[m + 0]; let g2 = img2[m + 1]; let b2 = img2[m + 2]; let a2 = img2[m + 3]; if (a1 === a2 && r1 === r2 && g1 === g2 && b1 === b2) return 0; if (a1 < 255) { a1 /= 255; r1 = blend(r1, a1); g1 = blend(g1, a1); b1 = blend(b1, a1); } if (a2 < 255) { a2 /= 255; r2 = blend(r2, a2); g2 = blend(g2, a2); b2 = blend(b2, a2); } const y1 = rgb2y(r1, g1, b1); const y2 = rgb2y(r2, g2, b2); const y = y1 - y2; if (yOnly) return y; const i = rgb2i(r1, g1, b1) - rgb2i(r2, g2, b2); const q = rgb2q(r1, g1, b1) - rgb2q(r2, g2, b2); const delta = 0.5053 * y * y + 0.299 * i * i + 0.1957 * q * q; return y1 > y2 ? -delta : delta; } function rgb2y(r, g, b) { return r * 0.29889531 + g * 0.58662247 + b * 0.11448223; } function rgb2i(r, g, b) { return r * 0.59597799 - g * 0.2741761 - b * 0.32180189; } function rgb2q(r, g, b) { return r * 0.21147017 - g * 0.52261711 + b * 0.31114694; } function blend(c, a) { return 255 + (c - 255) * a; } function drawPixel2(output, pos, r, g, b) { output[pos + 0] = r; output[pos + 1] = g; output[pos + 2] = b; output[pos + 3] = 255; } function drawGrayPixel(img, i, alpha, output) { const r = img[i + 0]; const g = img[i + 1]; const b = img[i + 2]; const val = blend(rgb2y(r, g, b), alpha * img[i + 3] / 255); drawPixel2(output, i, val, val, val); } } }); // packages/utils/image_tools/colorUtils.ts function blendWithWhite(c, a) { return 255 + (c - 255) * a; } function rgb2gray(r, g, b) { return 77 * r + 150 * g + 29 * b + 128 >> 8; } function colorDeltaE94(rgb1, rgb2) { const [l1, a1, b1] = xyz2lab(srgb2xyz(rgb1)); const [l2, a2, b2] = xyz2lab(srgb2xyz(rgb2)); const deltaL = l1 - l2; const deltaA = a1 - a2; const deltaB = b1 - b2; const c1 = Math.sqrt(a1 ** 2 + b1 ** 2); const c2 = Math.sqrt(a2 ** 2 + b2 ** 2); const deltaC = c1 - c2; let deltaH = deltaA ** 2 + deltaB ** 2 - deltaC ** 2; deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH); const k1 = 0.045; const k2 = 0.015; const kL = 1; const kC = 1; const kH = 1; const sC = 1 + k1 * c1; const sH = 1 + k2 * c1; const sL = 1; return Math.sqrt((deltaL / sL / kL) ** 2 + (deltaC / sC / kC) ** 2 + (deltaH / sH / kH) ** 2); } function srgb2xyz(rgb) { let r = rgb[0] / 255; let g = rgb[1] / 255; let b = rgb[2] / 255; r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92; g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92; b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92; return [ r * 0.4124 + g * 0.3576 + b * 0.1805, r * 0.2126 + g * 0.7152 + b * 0.0722, r * 0.0193 + g * 0.1192 + b * 0.9505 ]; } function xyz2lab(xyz) { const x = xyz[0] / 0.950489; const y = xyz[1]; const z31 = xyz[2] / 1.08884; const fx = x > sigma_pow3 ? x ** (1 / 3) : x / 3 / sigma_pow2 + 4 / 29; const fy = y > sigma_pow3 ? y ** (1 / 3) : y / 3 / sigma_pow2 + 4 / 29; const fz = z31 > sigma_pow3 ? z31 ** (1 / 3) : z31 / 3 / sigma_pow2 + 4 / 29; const l = 116 * fy - 16; const a = 500 * (fx - fy); const b = 200 * (fy - fz); return [l, a, b]; } var sigma_pow2, sigma_pow3; var init_colorUtils = __esm({ "packages/utils/image_tools/colorUtils.ts"() { "use strict"; sigma_pow2 = 6 * 6 / 29 / 29; sigma_pow3 = 6 * 6 * 6 / 29 / 29 / 29; } }); // packages/utils/image_tools/imageChannel.ts var ImageChannel; var init_imageChannel = __esm({ "packages/utils/image_tools/imageChannel.ts"() { "use strict"; init_colorUtils(); ImageChannel = class _ImageChannel { static intoRGB(width, height, data, options = {}) { const { paddingSize = 0, paddingColorOdd = [255, 0, 255], paddingColorEven = [0, 255, 0] } = options; const newWidth = width + 2 * paddingSize; const newHeight = height + 2 * paddingSize; const r = new Uint8Array(newWidth * newHeight); const g = new Uint8Array(newWidth * newHeight); const b = new Uint8Array(newWidth * newHeight); for (let y = 0; y < newHeight; ++y) { for (let x = 0; x < newWidth; ++x) { const index = y * newWidth + x; if (y >= paddingSize && y < newHeight - paddingSize && x >= paddingSize && x < newWidth - paddingSize) { const offset = ((y - paddingSize) * width + (x - paddingSize)) * 4; const alpha = data[offset + 3] === 255 ? 1 : data[offset + 3] / 255; r[index] = blendWithWhite(data[offset], alpha); g[index] = blendWithWhite(data[offset + 1], alpha); b[index] = blendWithWhite(data[offset + 2], alpha); } else { const color = (y + x) % 2 === 0 ? paddingColorEven : paddingColorOdd; r[index] = color[0]; g[index] = color[1]; b[index] = color[2]; } } } return [ new _ImageChannel(newWidth, newHeight, r), new _ImageChannel(newWidth, newHeight, g), new _ImageChannel(newWidth, newHeight, b) ]; } constructor(width, height, data) { this.data = data; this.width = width; this.height = height; } get(x, y) { return this.data[y * this.width + x]; } boundXY(x, y) { return [ Math.min(Math.max(x, 0), this.width - 1), Math.min(Math.max(y, 0), this.height - 1) ]; } }; } }); // packages/utils/image_tools/stats.ts function ssim(stats2, x1, y1, x2, y2) { const mean1 = stats2.meanC1(x1, y1, x2, y2); const mean2 = stats2.meanC2(x1, y1, x2, y2); const var1 = stats2.varianceC1(x1, y1, x2, y2); const var2 = stats2.varianceC2(x1, y1, x2, y2); const cov = stats2.covariance(x1, y1, x2, y2); const c1 = (0.01 * DYNAMIC_RANGE) ** 2; const c2 = (0.03 * DYNAMIC_RANGE) ** 2; return (2 * mean1 * mean2 + c1) * (2 * cov + c2) / (mean1 ** 2 + mean2 ** 2 + c1) / (var1 + var2 + c2); } var DYNAMIC_RANGE, FastStats; var init_stats = __esm({ "packages/utils/image_tools/stats.ts"() { "use strict"; DYNAMIC_RANGE = 2 ** 8 - 1; FastStats = class { constructor(c1, c2) { this.c1 = c1; this.c2 = c2; const { width, height } = c1; this._partialSumC1 = new Array(width * height); this._partialSumC2 = new Array(width * height); this._partialSumSq1 = new Array(width * height); this._partialSumSq2 = new Array(width * height); this._partialSumMult = new Array(width * height); const recalc = (mx, idx, initial, x, y) => { mx[idx] = initial; if (y > 0) mx[idx] += mx[(y - 1) * width + x]; if (x > 0) mx[idx] += mx[y * width + x - 1]; if (x > 0 && y > 0) mx[idx] -= mx[(y - 1) * width + x - 1]; }; for (let y = 0; y < height; ++y) { for (let x = 0; x < width; ++x) { const idx = y * width + x; recalc(this._partialSumC1, idx, this.c1.data[idx], x, y); recalc(this._partialSumC2, idx, this.c2.data[idx], x, y); recalc(this._partialSumSq1, idx, this.c1.data[idx] * this.c1.data[idx], x, y); recalc(this._partialSumSq2, idx, this.c2.data[idx] * this.c2.data[idx], x, y); recalc(this._partialSumMult, idx, this.c1.data[idx] * this.c2.data[idx], x, y); } } } _sum(partialSum, x1, y1, x2, y2) { const width = this.c1.width; let result2 = partialSum[y2 * width + x2]; if (y1 > 0) result2 -= partialSum[(y1 - 1) * width + x2]; if (x1 > 0) result2 -= partialSum[y2 * width + x1 - 1]; if (x1 > 0 && y1 > 0) result2 += partialSum[(y1 - 1) * width + x1 - 1]; return result2; } meanC1(x1, y1, x2, y2) { const N = (y2 - y1 + 1) * (x2 - x1 + 1); return this._sum(this._partialSumC1, x1, y1, x2, y2) / N; } meanC2(x1, y1, x2, y2) { const N = (y2 - y1 + 1) * (x2 - x1 + 1); return this._sum(this._partialSumC2, x1, y1, x2, y2) / N; } varianceC1(x1, y1, x2, y2) { const N = (y2 - y1 + 1) * (x2 - x1 + 1); return (this._sum(this._partialSumSq1, x1, y1, x2, y2) - this._sum(this._partialSumC1, x1, y1, x2, y2) ** 2 / N) / N; } varianceC2(x1, y1, x2, y2) { const N = (y2 - y1 + 1) * (x2 - x1 + 1); return (this._sum(this._partialSumSq2, x1, y1, x2, y2) - this._sum(this._partialSumC2, x1, y1, x2, y2) ** 2 / N) / N; } covariance(x1, y1, x2, y2) { const N = (y2 - y1 + 1) * (x2 - x1 + 1); return (this._sum(this._partialSumMult, x1, y1, x2, y2) - this._sum(this._partialSumC1, x1, y1, x2, y2) * this._sum(this._partialSumC2, x1, y1, x2, y2) / N) / N; } }; } }); // packages/utils/image_tools/compare.ts function drawPixel(width, data, x, y, r, g, b) { const idx = (y * width + x) * 4; data[idx + 0] = r; data[idx + 1] = g; data[idx + 2] = b; data[idx + 3] = 255; } function compare(actual, expected, diff2, width, height, options = {}) { const { maxColorDeltaE94 = 1 } = options; const paddingSize = Math.max(VARIANCE_WINDOW_RADIUS, SSIM_WINDOW_RADIUS); const paddingColorEven = [255, 0, 255]; const paddingColorOdd = [0, 255, 0]; const [r1, g1, b1] = ImageChannel.intoRGB(width, height, expected, { paddingSize, paddingColorEven, paddingColorOdd }); const [r2, g2, b2] = ImageChannel.intoRGB(width, height, actual, { paddingSize, paddingColorEven, paddingColorOdd }); const noop = (x, y) => { }; const drawRedPixel = diff2 ? (x, y) => drawPixel(width, diff2, x - paddingSize, y - paddingSize, 255, 0, 0) : noop; const drawYellowPixel = diff2 ? (x, y) => drawPixel(width, diff2, x - paddingSize, y - paddingSize, 255, 255, 0) : noop; const drawGrayPixel = diff2 ? (x, y) => { const gray = rgb2gray(r1.get(x, y), g1.get(x, y), b1.get(x, y)); const value2 = blendWithWhite(gray, 0.1); drawPixel(width, diff2, x - paddingSize, y - paddingSize, value2, value2, value2); } : noop; let fastR; let fastG; let fastB; let diffCount = 0; for (let y = paddingSize; y < r1.height - paddingSize; ++y) { for (let x = paddingSize; x < r1.width - paddingSize; ++x) { if (r1.get(x, y) === r2.get(x, y) && g1.get(x, y) === g2.get(x, y) && b1.get(x, y) === b2.get(x, y)) { drawGrayPixel(x, y); continue; } const delta = colorDeltaE94( [r1.get(x, y), g1.get(x, y), b1.get(x, y)], [r2.get(x, y), g2.get(x, y), b2.get(x, y)] ); if (delta <= maxColorDeltaE94) { drawGrayPixel(x, y); continue; } if (!fastR || !fastG || !fastB) { fastR = new FastStats(r1, r2); fastG = new FastStats(g1, g2); fastB = new FastStats(b1, b2); } const [varX1, varY1] = r1.boundXY(x - VARIANCE_WINDOW_RADIUS, y - VARIANCE_WINDOW_RADIUS); const [varX2, varY2] = r1.boundXY(x + VARIANCE_WINDOW_RADIUS, y + VARIANCE_WINDOW_RADIUS); const var1 = fastR.varianceC1(varX1, varY1, varX2, varY2) + fastG.varianceC1(varX1, varY1, varX2, varY2) + fastB.varianceC1(varX1, varY1, varX2, varY2); const var2 = fastR.varianceC2(varX1, varY1, varX2, varY2) + fastG.varianceC2(varX1, varY1, varX2, varY2) + fastB.varianceC2(varX1, varY1, varX2, varY2); if (var1 === 0 || var2 === 0) { drawRedPixel(x, y); ++diffCount; continue; } const [ssimX1, ssimY1] = r1.boundXY(x - SSIM_WINDOW_RADIUS, y - SSIM_WINDOW_RADIUS); const [ssimX2, ssimY2] = r1.boundXY(x + SSIM_WINDOW_RADIUS, y + SSIM_WINDOW_RADIUS); const ssimRGB = (ssim(fastR, ssimX1, ssimY1, ssimX2, ssimY2) + ssim(fastG, ssimX1, ssimY1, ssimX2, ssimY2) + ssim(fastB, ssimX1, ssimY1, ssimX2, ssimY2)) / 3; const isAntialiased = ssimRGB >= 0.99; if (isAntialiased) { drawYellowPixel(x, y); } else { drawRedPixel(x, y); ++diffCount; } } } return diffCount; } var SSIM_WINDOW_RADIUS, VARIANCE_WINDOW_RADIUS; var init_compare = __esm({ "packages/utils/image_tools/compare.ts"() { "use strict"; init_colorUtils(); init_imageChannel(); init_stats(); SSIM_WINDOW_RADIUS = 15; VARIANCE_WINDOW_RADIUS = 1; } }); // packages/utils/comparators.ts function getComparator(mimeType) { if (mimeType === "image/png") return compareImages.bind(null, "image/png"); if (mimeType === "image/jpeg") return compareImages.bind(null, "image/jpeg"); if (mimeType === "text/plain") return compareText; return compareBuffersOrStrings; } function compareBuffersOrStrings(actualBuffer, expectedBuffer) { if (typeof actualBuffer === "string") return compareText(actualBuffer, expectedBuffer); if (!actualBuffer || !(actualBuffer instanceof Buffer)) return { errorMessage: "Actual result should be a Buffer or a string." }; if (Buffer.compare(actualBuffer, expectedBuffer)) return { errorMessage: "Buffers differ" }; return null; } function compareImages(mimeType, actualBuffer, expectedBuffer, options = {}) { if (!actualBuffer || !(actualBuffer instanceof Buffer)) return { errorMessage: "Actual result should be a Buffer." }; validateBuffer(expectedBuffer, mimeType); let actual = mimeType === "image/png" ? PNG.sync.read(actualBuffer) : jpegjs.decode(actualBuffer, { maxMemoryUsageInMB: JPEG_JS_MAX_BUFFER_SIZE_IN_MB }); let expected = mimeType === "image/png" ? PNG.sync.read(expectedBuffer) : jpegjs.decode(expectedBuffer, { maxMemoryUsageInMB: JPEG_JS_MAX_BUFFER_SIZE_IN_MB }); const size = { width: Math.max(expected.width, actual.width), height: Math.max(expected.height, actual.height) }; let sizesMismatchError = ""; if (expected.width !== actual.width || expected.height !== actual.height) { sizesMismatchError = `Expected an image ${expected.width}px by ${expected.height}px, received ${actual.width}px by ${actual.height}px. `; actual = padImageToSize(actual, size); expected = padImageToSize(expected, size); } const diff2 = new PNG({ width: size.width, height: size.height }); let count; if (options.comparator === "ssim-cie94") { count = compare(expected.data, actual.data, diff2.data, size.width, size.height, { // All ΔE* formulae are originally designed to have the difference of 1.0 stand for a "just noticeable difference" (JND). // See https://en.wikipedia.org/wiki/Color_difference#CIELAB_%CE%94E* maxColorDeltaE94: 1 }); } else if ((options.comparator ?? "pixelmatch") === "pixelmatch") { count = (0, import_pixelmatch.default)(expected.data, actual.data, diff2.data, size.width, size.height, { threshold: options.threshold ?? 0.2 }); } else { throw new Error(`Configuration specifies unknown comparator "${options.comparator}"`); } const maxDiffPixels1 = options.maxDiffPixels; const maxDiffPixels2 = options.maxDiffPixelRatio !== void 0 ? expected.width * expected.height * options.maxDiffPixelRatio : void 0; let maxDiffPixels; if (maxDiffPixels1 !== void 0 && maxDiffPixels2 !== void 0) maxDiffPixels = Math.min(maxDiffPixels1, maxDiffPixels2); else maxDiffPixels = maxDiffPixels1 ?? maxDiffPixels2 ?? 0; const ratio = Math.ceil(count / (expected.width * expected.height) * 100) / 100; const pixelsMismatchError = count > maxDiffPixels ? `${count} pixels (ratio ${ratio.toFixed(2)} of all image pixels) are different.` : ""; if (pixelsMismatchError || sizesMismatchError) return { errorMessage: sizesMismatchError + pixelsMismatchError, diff: PNG.sync.write(diff2) }; return null; } function validateBuffer(buffer, mimeType) { if (mimeType === "image/png") { const pngMagicNumber = [137, 80, 78, 71, 13, 10, 26, 10]; if (buffer.length < pngMagicNumber.length || !pngMagicNumber.every((byte, index) => buffer[index] === byte)) throw new Error("Could not decode expected image as PNG."); } else if (mimeType === "image/jpeg") { const jpegMagicNumber = [255, 216]; if (buffer.length < jpegMagicNumber.length || !jpegMagicNumber.every((byte, index) => buffer[index] === byte)) throw new Error("Could not decode expected image as JPEG."); } } function compareText(actual, expectedBuffer) { if (typeof actual !== "string") return { errorMessage: "Actual result should be a string" }; let expected = expectedBuffer.toString("utf-8"); if (expected === actual) return null; if (!actual.endsWith("\n")) actual += "\n"; if (!expected.endsWith("\n")) expected += "\n"; const lines = diff.createPatch("file", expected, actual, void 0, void 0, { context: 5 }).split("\n"); const coloredLines = lines.slice(4).map((line) => { if (line.startsWith("-")) return colors.green(line); if (line.startsWith("+")) return colors.red(line); if (line.startsWith("@@")) return colors.dim(line); return line; }); const errorMessage = coloredLines.join("\n"); return { errorMessage }; } var import_pixelmatch, jpegjs, colors, diff, PNG, JPEG_JS_MAX_BUFFER_SIZE_IN_MB; var init_comparators = __esm({ "packages/utils/comparators.ts"() { "use strict"; init_imageUtils(); import_pixelmatch = __toESM(require_pixelmatch()); init_compare(); jpegjs = require("./utilsBundle").jpegjs; colors = require("./utilsBundle").colors; diff = require("./utilsBundle").diff; ({ PNG } = require("./utilsBundle")); JPEG_JS_MAX_BUFFER_SIZE_IN_MB = 5 * 1024; } }); // packages/utils/crypto.ts function createGuid() { return import_crypto.default.randomBytes(16).toString("hex"); } function calculateSha1(buffer) { const hash = import_crypto.default.createHash("sha1"); hash.update(buffer); return hash.digest("hex"); } function encodeBase128(value2) { const bytes = []; do { let byte = value2 & 127; value2 >>>= 7; if (bytes.length > 0) byte |= 128; bytes.push(byte); } while (value2 > 0); return Buffer.from(bytes.reverse()); } function generateSelfSignedCertificate() { const { privateKey, publicKey } = import_crypto.default.generateKeyPairSync("rsa", { modulusLength: 2048 }); const publicKeyDer = publicKey.export({ type: "pkcs1", format: "der" }); const oneYearInMilliseconds = 365 * 24 * 60 * 60 * 1e3; const notBefore = new Date((/* @__PURE__ */ new Date()).getTime() - oneYearInMilliseconds); const notAfter = new Date((/* @__PURE__ */ new Date()).getTime() + oneYearInMilliseconds); const tbsCertificate = DER.encodeSequence([ DER.encodeExplicitContextDependent(0, DER.encodeInteger(1)), // version DER.encodeInteger(1), // serialNumber DER.encodeSequence([ DER.encodeObjectIdentifier("1.2.840.113549.1.1.11"), // sha256WithRSAEncryption PKCS #1 DER.encodeNull() ]), // signature DER.encodeSequence([ DER.encodeSet([ DER.encodeSequence([ DER.encodeObjectIdentifier("2.5.4.3"), // commonName X.520 DN component DER.encodePrintableString("localhost") ]) ]), DER.encodeSet([ DER.encodeSequence([ DER.encodeObjectIdentifier("2.5.4.10"), // organizationName X.520 DN component DER.encodePrintableString("Playwright Client Certificate Support") ]) ]) ]), // issuer DER.encodeSequence([ DER.encodeDate(notBefore), // notBefore DER.encodeDate(notAfter) // notAfter ]), // validity DER.encodeSequence([ DER.encodeSet([ DER.encodeSequence([ DER.encodeObjectIdentifier("2.5.4.3"), // commonName X.520 DN component DER.encodePrintableString("localhost") ]) ]), DER.encodeSet([ DER.encodeSequence([ DER.encodeObjectIdentifier("2.5.4.10"), // organizationName X.520 DN component DER.encodePrintableString("Playwright Client Certificate Support") ]) ]) ]), // subject DER.encodeSequence([ DER.encodeSequence([ DER.encodeObjectIdentifier("1.2.840.113549.1.1.1"), // rsaEncryption PKCS #1 DER.encodeNull() ]), DER.encodeBitString(publicKeyDer) ]) // SubjectPublicKeyInfo ]); const signature = import_crypto.default.sign("sha256", tbsCertificate, privateKey); const certificate = DER.encodeSequence([ tbsCertificate, DER.encodeSequence([ DER.encodeObjectIdentifier("1.2.840.113549.1.1.11"), // sha256WithRSAEncryption PKCS #1 DER.encodeNull() ]), DER.encodeBitString(signature) ]); const certPem = [ "-----BEGIN CERTIFICATE-----", // Split the base64 string into lines of 64 characters certificate.toString("base64").match(/.{1,64}/g).join("\n"), "-----END CERTIFICATE-----" ].join("\n"); return { cert: certPem, key: privateKey.export({ type: "pkcs1", format: "pem" }) }; } var import_crypto, DER; var init_crypto = __esm({ "packages/utils/crypto.ts"() { "use strict"; import_crypto = __toESM(require("crypto")); init_assert(); DER = class { static encodeSequence(data) { return this._encode(48, Buffer.concat(data)); } static encodeInteger(data) { assert(data >= -128 && data <= 127); return this._encode(2, Buffer.from([data])); } static encodeObjectIdentifier(oid) { const parts = oid.split(".").map((v) => Number(v)); const output = [encodeBase128(40 * parts[0] + parts[1])]; for (let i = 2; i < parts.length; i++) output.push(encodeBase128(parts[i])); return this._encode(6, Buffer.concat(output)); } static encodeNull() { return Buffer.from([5, 0]); } static encodeSet(data) { assert(data.length === 1, "Only one item in the set is supported. We'd need to sort the data to support more."); return this._encode(49, Buffer.concat(data)); } static encodeExplicitContextDependent(tag, data) { return this._encode(160 + tag, data); } static encodePrintableString(data) { return this._encode(19, Buffer.from(data)); } static encodeBitString(data) { const unusedBits = 0; const content = Buffer.concat([Buffer.from([unusedBits]), data]); return this._encode(3, content); } static encodeDate(date) { const year = date.getUTCFullYear(); const isGeneralizedTime = year >= 2050; const parts = [ isGeneralizedTime ? year.toString() : year.toString().slice(-2), (date.getUTCMonth() + 1).toString().padStart(2, "0"), date.getUTCDate().toString().padStart(2, "0"), date.getUTCHours().toString().padStart(2, "0"), date.getUTCMinutes().toString().padStart(2, "0"), date.getUTCSeconds().toString().padStart(2, "0") ]; const encodedDate = parts.join("") + "Z"; const tag = isGeneralizedTime ? 24 : 23; return this._encode(tag, Buffer.from(encodedDate)); } static _encode(tag, data) { const lengthBytes = this._encodeLength(data.length); return Buffer.concat([Buffer.from([tag]), lengthBytes, data]); } static _encodeLength(length) { if (length < 128) { return Buffer.from([length]); } else { const lengthBytes = []; while (length > 0) { lengthBytes.unshift(length & 255); length >>= 8; } return Buffer.from([128 | lengthBytes.length, ...lengthBytes]); } } }; } }); // packages/utils/env.ts function getFromENV(name) { let value2 = process.env[name]; value2 = value2 === void 0 ? process.env[`npm_config_${name.toLowerCase()}`] : value2; value2 = value2 === void 0 ? process.env[`npm_package_config_${name.toLowerCase()}`] : value2; return value2; } function getAsBooleanFromENV(name, defaultValue) { const value2 = getFromENV(name); if (value2 === "false" || value2 === "0") return false; if (value2) return true; return !!defaultValue; } function getPackageManager() { const env = process.env.npm_config_user_agent || ""; if (env.includes("yarn")) return "yarn"; if (env.includes("pnpm")) return "pnpm"; return "npm"; } function getPackageManagerExecCommand() { const packageManager = getPackageManager(); if (packageManager === "yarn") return "yarn"; if (packageManager === "pnpm") return "pnpm exec"; return "npx"; } function isLikelyNpxGlobal() { return process.argv.length >= 2 && process.argv[1].includes("_npx"); } function setPlaywrightTestProcessEnv() { return process.env["PLAYWRIGHT_TEST"] = "1"; } function guessClientName() { if (process.env.CLAUDECODE) return "Claude Code"; if (process.env.COPILOT_CLI) return "GitHub Copilot"; return "playwright-cli"; } function isCodingAgent() { return !!process.env.CLAUDECODE || !!process.env.COPILOT_CLI; } var init_env = __esm({ "packages/utils/env.ts"() { "use strict"; } }); // packages/utils/debug.ts function debugMode() { if (_debugMode === "console") return "console"; if (_debugMode === "0" || _debugMode === "false") return ""; return _debugMode ? "inspector" : ""; } function isUnderTest() { return _isUnderTest; } var _debugMode, _isUnderTest; var init_debug = __esm({ "packages/utils/debug.ts"() { "use strict"; init_env(); _debugMode = getFromENV("PWDEBUG") || ""; _isUnderTest = getAsBooleanFromENV("PWTEST_UNDER_TEST"); } }); // packages/utils/debugLogger.ts var import_fs, debug, debugLoggerColorMap, DebugLogger, debugLogger, kLogCount, RecentLogsCollector; var init_debugLogger = __esm({ "packages/utils/debugLogger.ts"() { "use strict"; import_fs = __toESM(require("fs")); debug = require("./utilsBundle").debug; debugLoggerColorMap = { "api": 45, // cyan "protocol": 34, // green "install": 34, // green "download": 34, // green "browser": 0, // reset "socks": 92, // purple "client-certificates": 92, // purple "error": 160, // red, "channel": 33, // blue "server": 45, // cyan "server:channel": 34, // green "server:metadata": 33, // blue, "recorder": 45 // cyan }; DebugLogger = class { constructor() { this._debuggers = /* @__PURE__ */ new Map(); if (process.env.DEBUG_FILE) { const ansiRegex2 = new RegExp([ "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))" ].join("|"), "g"); const stream3 = import_fs.default.createWriteStream(process.env.DEBUG_FILE); debug.log = (data) => { stream3.write(data.replace(ansiRegex2, "")); stream3.write("\n"); }; } } log(name, message) { let cachedDebugger = this._debuggers.get(name); if (!cachedDebugger) { cachedDebugger = debug(`pw:${name}`); this._debuggers.set(name, cachedDebugger); cachedDebugger.color = debugLoggerColorMap[name] || 0; } cachedDebugger(message); } isEnabled(name) { return debug.enabled(`pw:${name}`); } }; debugLogger = new DebugLogger(); kLogCount = 150; RecentLogsCollector = class { constructor() { this._logs = []; this._listeners = []; } log(message) { this._logs.push(message); if (this._logs.length === kLogCount * 2) this._logs.splice(0, kLogCount); for (const listener of this._listeners) listener(message); } recentLogs() { if (this._logs.length > kLogCount) return this._logs.slice(-kLogCount); return this._logs; } onMessage(listener) { for (const message of this._logs) listener(message); this._listeners.push(listener); } }; } }); // packages/utils/eventsHelper.ts var EventsHelper, eventsHelper; var init_eventsHelper = __esm({ "packages/utils/eventsHelper.ts"() { "use strict"; EventsHelper = class { static addEventListener(emitter, eventName, handler) { emitter.on(eventName, handler); return { emitter, eventName, handler, dispose: async () => { emitter.removeListener(eventName, handler); } }; } static removeEventListeners(listeners) { for (const listener of listeners) listener.emitter.removeListener(listener.eventName, listener.handler); listeners.splice(0, listeners.length); } }; eventsHelper = EventsHelper; } }); // packages/utils/fileUtils.ts async function mkdirIfNeeded(filePath) { await import_fs2.default.promises.mkdir(import_path2.default.dirname(filePath), { recursive: true }).catch(() => { }); } async function removeFolders(dirs) { return await Promise.all(dirs.map( (dir) => import_fs2.default.promises.rm(dir, { recursive: true, force: true, maxRetries: 10 }).catch((e) => e) )); } function canAccessFile(file) { if (!file) return false; try { import_fs2.default.accessSync(file); return true; } catch (e) { return false; } } function isWritable(file) { try { import_fs2.default.accessSync(file, import_fs2.default.constants.W_OK); return true; } catch { return false; } } function isSystemDirectory(dir) { const resolved = import_path2.default.resolve(dir); if (process.platform === "win32") { const systemRoot = import_path2.default.resolve(process.env.SystemRoot || "C:\\Windows"); return isPathInside(systemRoot.toLowerCase(), resolved.toLowerCase()); } return resolved === "/"; } async function copyFileAndMakeWritable(from, to) { await import_fs2.default.promises.copyFile(from, to); await import_fs2.default.promises.chmod(to, 436); } function addSuffixToFilePath(filePath, suffix) { const ext = import_path2.default.extname(filePath); const base = filePath.substring(0, filePath.length - ext.length); return base + suffix + ext; } function sanitizeForFilePath(s) { return s.replace(/[\x00-\x2C\x2E-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]+/g, "-"); } function trimLongString(s, length = 100) { if (s.length <= length) return s; const hash = calculateSha1(s); const middle = `-${hash.substring(0, 5)}-`; const start3 = Math.floor((length - middle.length) / 2); const end = length - middle.length - start3; return s.substring(0, start3) + middle + s.slice(-end); } function isPathInside(root, candidate) { const resolvedRoot = import_path2.default.resolve(root); const resolvedCandidate = import_path2.default.resolve(candidate); if (resolvedCandidate === resolvedRoot) return true; return resolvedCandidate.startsWith(resolvedRoot + import_path2.default.sep); } function resolveWithinRoot(root, fileName) { if (import_path2.default.isAbsolute(fileName)) return null; const resolvedFile = import_path2.default.resolve(root, fileName); return isPathInside(root, resolvedFile) ? resolvedFile : null; } function throwingResolveWithinRoot(root, fileName) { const resolved = resolveWithinRoot(root, fileName); if (!resolved) throw new Error(`Path '${fileName}' escapes root directory`); return resolved; } function toPosixPath(aPath) { return aPath.split(import_path2.default.sep).join(import_path2.default.posix.sep); } function makeSocketPath(domain, name) { const userNameHash = calculateSha1(process.env.USERNAME || process.env.USER || "default").slice(0, 8); if (process.platform === "win32") { const socketsDir = process.env.PWTEST_SOCKETS_DIR; const suffix2 = socketsDir ? `-${calculateSha1(socketsDir).slice(0, 8)}` : ""; return `\\\\.\\pipe\\pw-${userNameHash}-${domain}-${name}${suffix2}`; } const baseDir = process.env.PWTEST_SOCKETS_DIR || import_path2.default.join(import_os2.default.tmpdir(), `pw-${userNameHash}`); const dir = import_path2.default.join(baseDir, domain); const suffix = ".sock"; const maxNameLength = UNIX_SOCKET_PATH_MAX - dir.length - import_path2.default.sep.length - suffix.length; if (maxNameLength < 1) throw new Error(`Socket directory path is too long (${dir.length} chars); set PWTEST_SOCKETS_DIR to a shorter location.`); const fsFriendlyName = trimLongString(sanitizeForFilePath(name), maxNameLength); const result2 = import_path2.default.join(dir, `${fsFriendlyName}${suffix}`); import_fs2.default.mkdirSync(dir, { recursive: true }); return result2; } var import_fs2, import_os2, import_path2, existsAsync, UNIX_SOCKET_PATH_MAX; var init_fileUtils = __esm({ "packages/utils/fileUtils.ts"() { "use strict"; import_fs2 = __toESM(require("fs")); import_os2 = __toESM(require("os")); import_path2 = __toESM(require("path")); init_crypto(); existsAsync = (path59) => new Promise((resolve) => import_fs2.default.stat(path59, (err) => resolve(!err))); UNIX_SOCKET_PATH_MAX = 103; } }); // packages/utils/linuxUtils.ts function getLinuxDistributionInfoSync() { if (process.platform !== "linux") return void 0; if (!osRelease && !didFailToReadOSRelease) { try { const osReleaseText = import_fs3.default.readFileSync("/etc/os-release", "utf8"); const fields = parseOSReleaseText(osReleaseText); osRelease = { id: fields.get("id") ?? "", version: fields.get("version_id") ?? "" }; } catch (e) { didFailToReadOSRelease = true; } } return osRelease; } function parseOSReleaseText(osReleaseText) { const fields = /* @__PURE__ */ new Map(); for (const line of osReleaseText.split("\n")) { const tokens = line.split("="); const name = tokens.shift(); let value2 = tokens.join("=").trim(); if (value2.startsWith('"') && value2.endsWith('"')) value2 = value2.substring(1, value2.length - 1); if (!name) continue; fields.set(name.toLowerCase(), value2); } return fields; } var import_fs3, didFailToReadOSRelease, osRelease; var init_linuxUtils = __esm({ "packages/utils/linuxUtils.ts"() { "use strict"; import_fs3 = __toESM(require("fs")); didFailToReadOSRelease = false; } }); // packages/utils/hostPlatform.ts function calculatePlatform() { if (process.env.PLAYWRIGHT_HOST_PLATFORM_OVERRIDE) { return { hostPlatform: process.env.PLAYWRIGHT_HOST_PLATFORM_OVERRIDE, isOfficiallySupportedPlatform: false }; } const platform = import_os3.default.platform(); if (platform === "darwin") { const ver = import_os3.default.release().split(".").map((a) => parseInt(a, 10)); let macVersion = ""; if (ver[0] < 18) { macVersion = "mac10.13"; } else if (ver[0] === 18) { macVersion = "mac10.14"; } else if (ver[0] === 19) { macVersion = "mac10.15"; } else if (ver[0] < 25) { macVersion = "mac" + (ver[0] - 9); if (import_os3.default.cpus().some((cpu) => cpu.model.includes("Apple"))) macVersion += "-arm64"; } else { const LAST_STABLE_MACOS_MAJOR_VERSION = 26; macVersion = "mac" + Math.min(ver[0] + 1, LAST_STABLE_MACOS_MAJOR_VERSION); if (import_os3.default.cpus().some((cpu) => cpu.model.includes("Apple"))) macVersion += "-arm64"; } return { hostPlatform: macVersion, isOfficiallySupportedPlatform: true }; } if (platform === "linux") { if (!["x64", "arm64"].includes(import_os3.default.arch())) return { hostPlatform: "", isOfficiallySupportedPlatform: false }; const archSuffix = "-" + import_os3.default.arch(); const distroInfo = getLinuxDistributionInfoSync(); if (distroInfo?.id === "ubuntu" || distroInfo?.id === "pop" || distroInfo?.id === "neon" || distroInfo?.id === "tuxedo") { const isUbuntu = distroInfo?.id === "ubuntu"; const version3 = distroInfo?.version; const major2 = parseInt(distroInfo.version, 10); if (major2 < 20) return { hostPlatform: "ubuntu18.04" + archSuffix, isOfficiallySupportedPlatform: false }; if (major2 < 22) return { hostPlatform: "ubuntu20.04" + archSuffix, isOfficiallySupportedPlatform: isUbuntu && version3 === "20.04" }; if (major2 < 24) return { hostPlatform: "ubuntu22.04" + archSuffix, isOfficiallySupportedPlatform: isUbuntu && version3 === "22.04" }; if (major2 < 26) return { hostPlatform: "ubuntu24.04" + archSuffix, isOfficiallySupportedPlatform: isUbuntu && version3 === "24.04" }; if (major2 < 28) return { hostPlatform: "ubuntu26.04" + archSuffix, isOfficiallySupportedPlatform: isUbuntu && version3 === "26.04" }; return { hostPlatform: "ubuntu" + distroInfo.version + archSuffix, isOfficiallySupportedPlatform: false }; } if (distroInfo?.id === "linuxmint") { const mintMajor = parseInt(distroInfo.version, 10); if (mintMajor <= 20) return { hostPlatform: "ubuntu20.04" + archSuffix, isOfficiallySupportedPlatform: false }; if (mintMajor === 21) return { hostPlatform: "ubuntu22.04" + archSuffix, isOfficiallySupportedPlatform: false }; return { hostPlatform: "ubuntu24.04" + archSuffix, isOfficiallySupportedPlatform: false }; } if (distroInfo?.id === "debian" || distroInfo?.id === "raspbian") { const isOfficiallySupportedPlatform2 = distroInfo?.id === "debian"; if (distroInfo?.version === "11") return { hostPlatform: "debian11" + archSuffix, isOfficiallySupportedPlatform: isOfficiallySupportedPlatform2 }; if (distroInfo?.version === "12") return { hostPlatform: "debian12" + archSuffix, isOfficiallySupportedPlatform: isOfficiallySupportedPlatform2 }; if (distroInfo?.version === "13") return { hostPlatform: "debian13" + archSuffix, isOfficiallySupportedPlatform: isOfficiallySupportedPlatform2 }; if (distroInfo?.version === "") return { hostPlatform: "debian13" + archSuffix, isOfficiallySupportedPlatform: isOfficiallySupportedPlatform2 }; } return { hostPlatform: "ubuntu24.04" + archSuffix, isOfficiallySupportedPlatform: false }; } if (platform === "win32") return { hostPlatform: "win64", isOfficiallySupportedPlatform: true }; return { hostPlatform: "", isOfficiallySupportedPlatform: false }; } function toShortPlatform(hostPlatform2) { if (hostPlatform2 === "") return ""; if (hostPlatform2 === "win64") return "win-x64"; if (hostPlatform2.startsWith("mac")) return hostPlatform2.endsWith("arm64") ? "mac-arm64" : "mac-x64"; return hostPlatform2.endsWith("arm64") ? "linux-arm64" : "linux-x64"; } var import_os3, hostPlatform, isOfficiallySupportedPlatform, shortPlatform; var init_hostPlatform = __esm({ "packages/utils/hostPlatform.ts"() { "use strict"; import_os3 = __toESM(require("os")); init_linuxUtils(); ({ hostPlatform, isOfficiallySupportedPlatform } = calculatePlatform()); shortPlatform = toShortPlatform(hostPlatform); } }); // packages/utils/happyEyeballs.ts async function createSocket(host, port) { return new Promise((resolve, reject) => { if (import_net.default.isIP(host)) { const socket = import_net.default.createConnection({ host, port }); socket.on("connect", () => resolve(socket)); socket.on("error", (error) => reject(error)); } else { createConnectionAsync( { host, port }, (err, socket) => { if (err) reject(err); if (socket) resolve(socket); }, /* useTLS */ false ).catch((err) => reject(err)); } }); } async function createConnectionAsync(options, oncreate, useTLS) { const lookup = options.__testHookLookup || lookupAddresses; const hostname = clientRequestArgsToHostName(options); const addresses = await lookup(hostname); const dnsLookupAt = monotonicTime(); const sockets = /* @__PURE__ */ new Set(); let firstError; let errorCount = 0; const handleError = (socket, err) => { if (!sockets.delete(socket)) return; ++errorCount; firstError ??= err; if (errorCount === addresses.length) oncreate?.(firstError); }; const connected = new ManualPromise(); for (const { address } of addresses) { const socket = useTLS ? import_tls.default.connect({ ...options, port: options.port, host: address, servername: hostname }) : import_net.default.createConnection({ ...options, port: options.port, host: address }); socket[kDNSLookupAt] = dnsLookupAt; socket.on("connect", () => { socket[kTCPConnectionAt] = monotonicTime(); connected.resolve(); oncreate?.(null, socket); sockets.delete(socket); for (const s of sockets) s.destroy(); sockets.clear(); }); socket.on("timeout", () => { socket.destroy(); handleError(socket, new Error("Connection timeout")); }); socket.on("error", (e) => handleError(socket, e)); sockets.add(socket); await Promise.race([ connected, new Promise((f) => setTimeout(f, connectionAttemptDelayMs)) ]); if (connected.isDone()) break; } } async function lookupAddresses(hostname) { const [v4Result, v6Result] = await Promise.allSettled([ import_dns.default.promises.lookup(hostname, { all: true, family: 4 }), import_dns.default.promises.lookup(hostname, { all: true, family: 6 }) ]); const v4Addresses = v4Result.status === "fulfilled" ? v4Result.value : []; const v6Addresses = v6Result.status === "fulfilled" ? v6Result.value : []; if (!v4Addresses.length && !v6Addresses.length) { if (v4Result.status === "rejected") throw v4Result.reason; throw v6Result.reason; } const result2 = []; for (let i = 0; i < Math.max(v4Addresses.length, v6Addresses.length); i++) { if (v6Addresses[i]) result2.push(v6Addresses[i]); if (v4Addresses[i]) result2.push(v4Addresses[i]); } return result2; } function clientRequestArgsToHostName(options) { if (options.hostname) return options.hostname; if (options.host) return options.host; throw new Error("Either options.hostname or options.host must be provided"); } function timingForSocket(socket) { return { dnsLookupAt: socket[kDNSLookupAt], tcpConnectionAt: socket[kTCPConnectionAt] }; } var import_dns, import_http, import_https, import_net, import_tls, connectionAttemptDelayMs, kDNSLookupAt, kTCPConnectionAt, HttpHappyEyeballsAgent, HttpsHappyEyeballsAgent, httpsHappyEyeballsAgent, httpHappyEyeballsAgent; var init_happyEyeballs = __esm({ "packages/utils/happyEyeballs.ts"() { "use strict"; import_dns = __toESM(require("dns")); import_http = __toESM(require("http")); import_https = __toESM(require("https")); import_net = __toESM(require("net")); import_tls = __toESM(require("tls")); init_assert(); init_manualPromise(); init_time(); connectionAttemptDelayMs = 300; kDNSLookupAt = Symbol("kDNSLookupAt"); kTCPConnectionAt = Symbol("kTCPConnectionAt"); HttpHappyEyeballsAgent = class extends import_http.default.Agent { createConnection(options, oncreate) { if (import_net.default.isIP(clientRequestArgsToHostName(options))) return import_net.default.createConnection(options); createConnectionAsync( options, oncreate, /* useTLS */ false ).catch((err) => oncreate?.(err)); } }; HttpsHappyEyeballsAgent = class extends import_https.default.Agent { createConnection(options, oncreate) { if (import_net.default.isIP(clientRequestArgsToHostName(options))) return import_tls.default.connect(options); createConnectionAsync( options, oncreate, /* useTLS */ true ).catch((err) => oncreate?.(err)); } }; httpsHappyEyeballsAgent = new HttpsHappyEyeballsAgent({ keepAlive: true }); httpHappyEyeballsAgent = new HttpHappyEyeballsAgent({ keepAlive: true }); } }); // packages/utils/network.ts function httpRequest(params2, onResponse, onError) { let url2 = new URL(params2.url); const options = { method: params2.method || "GET", headers: params2.headers }; if (params2.rejectUnauthorized !== void 0) options.rejectUnauthorized = params2.rejectUnauthorized; const proxyURL = getProxyForUrl(params2.url); if (proxyURL) { const parsedProxyURL = normalizeProxyURL(proxyURL); if (params2.url.startsWith("http:")) { options.path = url2.toString(); const headers = options.headers || {}; if (!Object.keys(headers).some((header) => header.toLowerCase() === "host")) headers.host = url2.host; options.headers = headers; url2 = parsedProxyURL; } else { options.agent = new HttpsProxyAgent(parsedProxyURL); } } options.agent ??= url2.protocol === "https:" ? httpsHappyEyeballsAgent : httpHappyEyeballsAgent; let cancelRequest; const requestCallback = (res) => { const statusCode = res.statusCode || 0; if (statusCode >= 300 && statusCode < 400 && res.headers.location) { request2.destroy(); cancelRequest = httpRequest({ ...params2, url: new URL(res.headers.location, params2.url).toString() }, onResponse, onError).cancel; } else { onResponse(res); } }; const request2 = url2.protocol === "https:" ? import_https2.default.request(url2, options, requestCallback) : import_http2.default.request(url2, options, requestCallback); request2.on("error", onError); if (params2.socketTimeout !== void 0) { request2.setTimeout(params2.socketTimeout, () => { onError(new Error(`Request to ${params2.url} timed out after ${params2.socketTimeout}ms`)); request2.abort(); }); } cancelRequest = (e) => { try { request2.destroy(e); } catch { } }; request2.end(params2.data); return { cancel: (e) => cancelRequest(e) }; } function shouldBypassProxy(url2, bypass) { if (!bypass) return false; const domains = bypass.split(",").map((s) => { s = s.trim(); if (!s.startsWith(".")) s = "." + s; return s; }); const domain = "." + url2.hostname; return domains.some((d) => domain.endsWith(d)); } function normalizeProxyURL(proxy) { proxy = proxy.trim(); if (!/^\w+:\/\//.test(proxy)) proxy = "http://" + proxy; return new URL(proxy); } function createProxyAgent(proxy, forUrl) { if (!proxy) return; if (forUrl && proxy.bypass && shouldBypassProxy(forUrl, proxy.bypass)) return; const proxyURL = normalizeProxyURL(proxy.server); if (proxyURL.protocol?.startsWith("socks")) { if (proxyURL.protocol === "socks5:") proxyURL.protocol = "socks5h:"; else if (proxyURL.protocol === "socks4:") proxyURL.protocol = "socks4a:"; return new SocksProxyAgent(proxyURL); } if (proxy.username) { proxyURL.username = proxy.username; proxyURL.password = proxy.password || ""; } if (forUrl && ["ws:", "wss:"].includes(forUrl.protocol)) { return new HttpsProxyAgent(proxyURL); } return new HttpsProxyAgent(proxyURL); } function createHttpServer(...args) { const server = import_http2.default.createServer(...args); decorateServer(server); return server; } function createHttpsServer(...args) { const server = import_https2.default.createServer(...args); decorateServer(server); return server; } function createHttp2Server(...args) { const server = import_http22.default.createSecureServer(...args); decorateServer(server); return server; } async function startHttpServer(server, options) { const { host = "localhost", port = 0 } = options; const errorPromise = new ManualPromise(); const errorListener = (error) => errorPromise.reject(error); server.on("error", errorListener); try { server.listen(port, host); await Promise.race([ new Promise((cb) => server.once("listening", cb)), errorPromise ]); } finally { server.removeListener("error", errorListener); } } async function isURLAvailable(url2, ignoreHTTPSErrors, onLog, onStdErr) { let statusCode = await httpStatusCode(url2, ignoreHTTPSErrors, onLog, onStdErr); if (statusCode === 404 && url2.pathname === "/") { const indexUrl = new URL(url2); indexUrl.pathname = "/index.html"; statusCode = await httpStatusCode(indexUrl, ignoreHTTPSErrors, onLog, onStdErr); } return statusCode >= 200 && statusCode < 404; } async function httpStatusCode(url2, ignoreHTTPSErrors, onLog, onStdErr) { return new Promise((resolve) => { onLog?.(`HTTP GET: ${url2}`); httpRequest({ url: url2.toString(), headers: { Accept: "*/*" }, rejectUnauthorized: !ignoreHTTPSErrors }, (res) => { res.resume(); const statusCode = res.statusCode ?? 0; onLog?.(`HTTP Status: ${statusCode}`); resolve(statusCode); }, (error) => { if (error.code === "DEPTH_ZERO_SELF_SIGNED_CERT") onStdErr?.(`[WebServer] Self-signed certificate detected. Try adding ignoreHTTPSErrors: true to config.webServer.`); onLog?.(`Error while checking if ${url2} is available: ${error.message}`); resolve(0); }); }); } function decorateServer(server) { const sockets = /* @__PURE__ */ new Set(); server.on("connection", (socket) => { sockets.add(socket); socket.once("close", () => sockets.delete(socket)); }); const close3 = server.close; server.close = (callback) => { for (const socket of sockets) socket.destroy(); sockets.clear(); return close3.call(server, callback); }; } var import_http2, import_http22, import_https2, HttpsProxyAgent, SocksProxyAgent, getProxyForUrl, NET_DEFAULT_TIMEOUT; var init_network = __esm({ "packages/utils/network.ts"() { "use strict"; import_http2 = __toESM(require("http")); import_http22 = __toESM(require("http2")); import_https2 = __toESM(require("https")); init_manualPromise(); init_happyEyeballs(); ({ HttpsProxyAgent } = require("./utilsBundle")); ({ SocksProxyAgent } = require("./utilsBundle")); ({ getProxyForUrl } = require("./utilsBundle")); NET_DEFAULT_TIMEOUT = 3e4; } }); // packages/utils/httpServer.ts function computeAllowedHosts(requested, bound) { const loopback = /* @__PURE__ */ new Set(["127.0.0.1", "::1", "localhost"]); const isLoopback = (h) => h !== void 0 && loopback.has(h.toLowerCase()); if (!isLoopback(requested) && requested !== void 0) return null; if (!isLoopback(bound) && requested === void 0) return null; return /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); } function urlHostFromAddress(address) { return address.family === "IPv6" ? `[${address.address}]` : address.address; } function hostnameFromHostHeader(host) { if (host.startsWith("[")) { const end = host.indexOf("]"); return end < 0 ? host : host.substring(0, end + 1); } const colon = host.indexOf(":"); return colon < 0 ? host : host.substring(0, colon); } function serveFolder(folder) { const server = new HttpServer(folder); server.routePrefix("/", (request2, response2) => { let relativePath = new URL("http://localhost" + request2.url).pathname; if (relativePath.startsWith("/trace/file")) { const url2 = new URL("http://localhost" + request2.url); const requested = url2.searchParams.get("path"); if (!requested) return false; const resolved = import_path3.default.resolve(requested); try { return server.serveFile(request2, response2, resolved); } catch (e) { return false; } } if (relativePath === "/") relativePath = "/index.html"; const absolutePath = import_path3.default.join(folder, ...relativePath.split("/")); return server.serveFile(request2, response2, absolutePath); }); return server; } var import_fs4, import_path3, mime, wsServer, HttpServer; var init_httpServer = __esm({ "packages/utils/httpServer.ts"() { "use strict"; import_fs4 = __toESM(require("fs")); import_path3 = __toESM(require("path")); init_assert(); init_crypto(); init_fileUtils(); init_network(); mime = require("./utilsBundle").mime; ({ wsServer } = require("./utilsBundle")); HttpServer = class { constructor(staticRoot) { this._urlPrefixPrecise = ""; this._urlPrefixHumanReadable = ""; this._port = 0; this._started = false; this._routes = []; // Allowed Host headers; null disables the check (host bound to a public address). this._allowedHosts = null; this._server = createHttpServer(this._onRequest.bind(this)); this._staticRoot = staticRoot ? import_path3.default.resolve(staticRoot) : void 0; } server() { return this._server; } routePrefix(prefix, handler) { this._routes.push({ prefix, handler }); } routePath(path59, handler) { this._routes.push({ exact: path59, handler }); } port() { return this._port; } createWebSocket(transportFactory, guid) { assert(!this._wsGuid, "can only create one main websocket transport per server"); this._wsGuid = guid || createGuid(); const wsPath = "/" + this._wsGuid; const wss = new wsServer({ noServer: true }); this._server.on("upgrade", (request2, socket, head) => { const pathname = new URL(request2.url ?? "/", "http://localhost").pathname; if (pathname !== wsPath) return; wss.handleUpgrade(request2, socket, head, (ws4) => wss.emit("connection", ws4, request2)); }); wss.on("connection", (ws4, request2) => { const url2 = new URL(request2.url ?? "/", "http://localhost"); const transport = transportFactory(url2); transport.sendEvent = (method, params2) => ws4.send(JSON.stringify({ method, params: params2 })); transport.close = () => ws4.close(); transport.onconnect(); ws4.on("message", async (message) => { const { id, method, params: params2 } = JSON.parse(String(message)); try { const result2 = await transport.dispatch(method, params2); ws4.send(JSON.stringify({ id, result: result2 })); } catch (e) { ws4.send(JSON.stringify({ id, error: String(e) })); } }); ws4.on("close", () => transport.onclose()); ws4.on("error", () => transport.onclose()); }); } wsGuid() { return this._wsGuid; } async createViteDevServer(options) { const loadVite = new Function('return import("vite")'); const vite = await loadVite(); return await vite.createServer({ root: options.root, base: options.base, server: { middlewareMode: true, // Dedicated path so Vite's HMR websocket does not collide with any // websocket HttpServer owns via createWebSocket(). hmr: { path: "/__vite_hmr", server: this._server } }, appType: "spa", clearScreen: false }); } // HMR end // Vite's middleware `next` callback for the "no middleware matched" case; // emits a 404 only if nothing downstream already responded. static notFoundFallback(response2) { return () => { if (!response2.headersSent) { response2.statusCode = 404; response2.end(); } }; } async start(options = {}) { assert(!this._started, "server already started"); this._started = true; const host = options.host; if (options.preferredPort) { try { await startHttpServer(this._server, { port: options.preferredPort, host }); } catch (e) { if (!e || !e.message || !e.message.includes("EADDRINUSE")) throw e; await startHttpServer(this._server, { host }); } } else { await startHttpServer(this._server, { port: options.port, host }); } const address = this._server.address(); assert(address, "Could not bind server socket"); if (typeof address === "string") { this._urlPrefixPrecise = address; this._urlPrefixHumanReadable = address; } else { this._port = address.port; this._urlPrefixPrecise = `http://${urlHostFromAddress(address)}:${address.port}`; this._urlPrefixHumanReadable = `http://${host ?? "localhost"}:${address.port}`; this._allowedHosts = computeAllowedHosts(host, address.address); } } async stop() { await new Promise((cb) => this._server.close(cb)); } urlPrefix(purpose) { return purpose === "human-readable" ? this._urlPrefixHumanReadable : this._urlPrefixPrecise; } serveFile(request2, response2, absoluteFilePath, headers, options) { if (this._staticRoot && !options?.skipRootCheck && !isPathInside(this._staticRoot, absoluteFilePath)) { response2.statusCode = 403; response2.end(); return true; } try { for (const [name, value2] of Object.entries(headers || {})) response2.setHeader(name, value2); if (request2.headers.range) this._serveRangeFile(request2, response2, absoluteFilePath); else this._serveFile(response2, absoluteFilePath); return true; } catch (e) { return false; } } _serveFile(response2, absoluteFilePath) { const content = import_fs4.default.readFileSync(absoluteFilePath); response2.statusCode = 200; const contentType = mime.getType(import_path3.default.extname(absoluteFilePath)) || "application/octet-stream"; response2.setHeader("Content-Type", contentType); response2.setHeader("Content-Length", content.byteLength); response2.end(content); } _serveRangeFile(request2, response2, absoluteFilePath) { const range = request2.headers.range; if (!range || !range.startsWith("bytes=") || range.includes(", ") || [...range].filter((char) => char === "-").length !== 1) { response2.statusCode = 400; return response2.end("Bad request"); } const [startStr, endStr] = range.replace(/bytes=/, "").split("-"); let start3; let end; const size = import_fs4.default.statSync(absoluteFilePath).size; if (startStr !== "" && endStr === "") { start3 = +startStr; end = size - 1; } else if (startStr === "" && endStr !== "") { start3 = size - +endStr; end = size - 1; } else { start3 = +startStr; end = +endStr; } if (Number.isNaN(start3) || Number.isNaN(end) || start3 >= size || end >= size || start3 > end) { response2.writeHead(416, { "Content-Range": `bytes */${size}` }); return response2.end(); } response2.writeHead(206, { "Content-Range": `bytes ${start3}-${end}/${size}`, "Accept-Ranges": "bytes", "Content-Length": end - start3 + 1, "Content-Type": mime.getType(import_path3.default.extname(absoluteFilePath)) }); const readable = import_fs4.default.createReadStream(absoluteFilePath, { start: start3, end }); readable.pipe(response2); } _onRequest(request2, response2) { if (request2.method === "OPTIONS") { response2.writeHead(200); response2.end(); return; } if (this._allowedHosts) { const host = request2.headers.host?.toLowerCase(); const hostname = host ? hostnameFromHostHeader(host) : void 0; if (!hostname || !this._allowedHosts.has(hostname)) { response2.statusCode = 403; response2.end(); return; } } request2.on("error", () => response2.end()); try { if (!request2.url) { response2.end(); return; } const url2 = new URL("http://localhost" + request2.url); for (const route2 of this._routes) { if (route2.exact && url2.pathname === route2.exact && route2.handler(request2, response2)) return; if (route2.prefix && url2.pathname.startsWith(route2.prefix) && route2.handler(request2, response2)) return; } response2.statusCode = 404; response2.end(); } catch (e) { response2.end(); } } }; } }); // packages/utils/zones.ts function currentZone() { return asyncLocalStorage.getStore() ?? emptyZone; } var import_async_hooks, asyncLocalStorage, Zone, emptyZone; var init_zones = __esm({ "packages/utils/zones.ts"() { "use strict"; import_async_hooks = require("async_hooks"); asyncLocalStorage = new import_async_hooks.AsyncLocalStorage(); Zone = class _Zone { constructor(asyncLocalStorage2, store) { this._asyncLocalStorage = asyncLocalStorage2; this._data = store; } with(type3, data) { return new _Zone(this._asyncLocalStorage, new Map(this._data).set(type3, data)); } without(type3) { const data = type3 ? new Map(this._data) : /* @__PURE__ */ new Map(); data.delete(type3); return new _Zone(this._asyncLocalStorage, data); } run(func) { return this._asyncLocalStorage.run(this, func); } data(type3) { return this._data.get(type3); } }; emptyZone = new Zone(asyncLocalStorage, /* @__PURE__ */ new Map()); } }); // packages/utils/nodePlatform.ts function setBoxedStackPrefixes(prefixes) { boxedStackPrefixes = prefixes; } var import_crypto4, import_fs5, import_path4, util, import_stream, import_events, colors2, pipelineAsync, NodeZone, boxedStackPrefixes, nodePlatform, ReadableStreamImpl, WritableStreamImpl; var init_nodePlatform = __esm({ "packages/utils/nodePlatform.ts"() { "use strict"; import_crypto4 = __toESM(require("crypto")); import_fs5 = __toESM(require("fs")); import_path4 = __toESM(require("path")); util = __toESM(require("util")); import_stream = require("stream"); import_events = require("events"); init_debugLogger(); init_zones(); init_debug(); colors2 = require("./utilsBundle").colors; pipelineAsync = util.promisify(import_stream.pipeline); NodeZone = class _NodeZone { constructor(zone) { this._zone = zone; } push(data) { return new _NodeZone(this._zone.with("apiZone", data)); } pop() { return new _NodeZone(this._zone.without("apiZone")); } run(func) { return this._zone.run(func); } data() { return this._zone.data("apiZone"); } }; boxedStackPrefixes = []; nodePlatform = (coreDir) => ({ name: "node", boxedStackPrefixes: () => { if (process.env.PWDEBUGIMPL) return []; return [coreDir, ...boxedStackPrefixes]; }, calculateSha1: (text2) => { const sha1 = import_crypto4.default.createHash("sha1"); sha1.update(text2); return Promise.resolve(sha1.digest("hex")); }, colors: colors2, coreDir, createGuid: () => import_crypto4.default.randomBytes(16).toString("hex"), defaultMaxListeners: () => import_events.EventEmitter.defaultMaxListeners, fs: () => import_fs5.default, env: process.env, inspectCustom: util.inspect.custom, isDebugMode: () => debugMode() === "inspector", isJSDebuggerAttached: () => !!require("inspector").url(), isLogEnabled(name) { return debugLogger.isEnabled(name); }, isUnderTest: () => isUnderTest(), log(name, message) { debugLogger.log(name, message); }, path: () => import_path4.default, pathSeparator: import_path4.default.sep, showInternalStackFrames: () => !!process.env.PWDEBUGIMPL, async streamFile(path59, stream3) { await pipelineAsync(import_fs5.default.createReadStream(path59), stream3); }, streamReadable: (channel) => { return new ReadableStreamImpl(channel); }, streamWritable: (channel) => { return new WritableStreamImpl(channel); }, zones: { current: () => new NodeZone(currentZone()), empty: new NodeZone(emptyZone) } }); ReadableStreamImpl = class extends import_stream.Readable { constructor(channel) { super(); this._channel = channel; } async _read() { const result2 = await this._channel.read({ size: 1024 * 1024 }); if (result2.binary.byteLength) this.push(result2.binary); else this.push(null); } _destroy(error, callback) { this._channel.close().catch((e) => null); super._destroy(error, callback); } }; WritableStreamImpl = class extends import_stream.Writable { constructor(channel) { super(); this._channel = channel; } async _write(chunk, encoding, callback) { const error = await this._channel.write({ binary: typeof chunk === "string" ? Buffer.from(chunk) : chunk }).catch((e) => e); callback(error || null); } async _final(callback) { const error = await this._channel.close().catch((e) => e); callback(error || null); } }; } }); // packages/utils/processLauncher.ts async function gracefullyCloseAll() { await Promise.all(Array.from(gracefullyCloseSet).map((gracefullyClose) => gracefullyClose().catch((e) => { }))); } function gracefullyProcessExitDoNotHang(code, onExit2) { const beforeExit = onExit2 ? () => onExit2().catch(() => { }) : () => Promise.resolve(); const callback = () => beforeExit().then(() => process.exit(code)); setTimeout(callback, 3e4); gracefullyCloseAll().then(callback); } function exitHandler() { for (const kill of killSet) kill(); } function sigintHandler() { const exitWithCode130 = () => { if (isUnderTest()) { setTimeout(() => process.exit(130), 1e3); } else { process.exit(130); } }; if (sigintHandlerCalled) { process.off("SIGINT", sigintHandler); for (const kill of killSet) kill(); exitWithCode130(); } else { sigintHandlerCalled = true; gracefullyCloseAll().then(() => exitWithCode130()); } } function sigtermHandler() { gracefullyCloseAll(); } function sighupHandler() { gracefullyCloseAll(); } function addProcessHandlerIfNeeded(name) { if (!installedHandlers.has(name)) { installedHandlers.add(name); process.on(name, processHandlers[name]); } } function removeProcessHandlersIfNeeded() { if (killSet.size) return; for (const handler of installedHandlers) process.off(handler, processHandlers[handler]); installedHandlers.clear(); } async function launchProcess(options) { const stdio = options.stdio === "pipe" ? ["ignore", "pipe", "pipe", "pipe", "pipe"] : ["pipe", "pipe", "pipe"]; options.log(` ${options.command} ${options.args ? options.args.join(" ") : ""}`); const spawnOptions = { // On non-windows platforms, `detached: true` makes child process a leader of a new // process group, making it possible to kill child process tree with `.kill(-pid)` command. // @see https://nodejs.org/api/child_process.html#child_process_options_detached detached: process.platform !== "win32", env: options.env, cwd: options.cwd, shell: options.shell, stdio }; const spawnedProcess = childProcess.spawn(options.command, options.args || [], spawnOptions); const cleanup = async () => { options.log(`[pid=${spawnedProcess.pid || "N/A"}] starting temporary directories cleanup`); const errors = await removeFolders(options.tempDirectories); for (let i = 0; i < options.tempDirectories.length; ++i) { if (errors[i]) options.log(`[pid=${spawnedProcess.pid || "N/A"}] exception while removing ${options.tempDirectories[i]}: ${errors[i]}`); } options.log(`[pid=${spawnedProcess.pid || "N/A"}] finished temporary directories cleanup`); }; spawnedProcess.on("error", () => { }); if (!spawnedProcess.pid) { let failed; const failedPromise = new Promise((f, r) => failed = f); spawnedProcess.once("error", (error) => { failed(new Error("Failed to launch: " + error)); }); return failedPromise.then(async (error) => { await cleanup(); throw error; }); } options.log(` pid=${spawnedProcess.pid}`); const stdout = readline.createInterface({ input: spawnedProcess.stdout }); stdout.on("line", (data) => { options.log(`[pid=${spawnedProcess.pid}][out] ` + data); }); const stderr = readline.createInterface({ input: spawnedProcess.stderr }); stderr.on("line", (data) => { options.log(`[pid=${spawnedProcess.pid}][err] ` + data); }); let processClosed = false; let fulfillCleanup = () => { }; const waitForCleanup = new Promise((f) => fulfillCleanup = f); spawnedProcess.once("close", (exitCode, signal) => { options.log(`[pid=${spawnedProcess.pid}] `); processClosed = true; gracefullyCloseSet.delete(gracefullyClose); killSet.delete(killProcessAndCleanup); removeProcessHandlersIfNeeded(); options.onExit(exitCode, signal); cleanup().then(fulfillCleanup); }); addProcessHandlerIfNeeded("exit"); if (options.handleSIGINT) addProcessHandlerIfNeeded("SIGINT"); if (options.handleSIGTERM) addProcessHandlerIfNeeded("SIGTERM"); if (options.handleSIGHUP) addProcessHandlerIfNeeded("SIGHUP"); gracefullyCloseSet.add(gracefullyClose); killSet.add(killProcessAndCleanup); let gracefullyClosing = false; async function gracefullyClose() { if (gracefullyClosing) { options.log(`[pid=${spawnedProcess.pid}] `); killProcess(); await waitForCleanup; return; } gracefullyClosing = true; options.log(`[pid=${spawnedProcess.pid}] `); await options.attemptToGracefullyClose().catch(() => killProcess()); await waitForCleanup; options.log(`[pid=${spawnedProcess.pid}] `); } function killProcess() { gracefullyCloseSet.delete(gracefullyClose); killSet.delete(killProcessAndCleanup); removeProcessHandlersIfNeeded(); options.log(`[pid=${spawnedProcess.pid}] `); if (spawnedProcess.pid && !spawnedProcess.killed && !processClosed) { options.log(`[pid=${spawnedProcess.pid}] `); try { if (process.platform === "win32") { const taskkillProcess = childProcess.spawnSync(`taskkill /pid ${spawnedProcess.pid} /T /F`, { shell: true }); const [stdout2, stderr2] = [taskkillProcess.stdout.toString(), taskkillProcess.stderr.toString()]; if (stdout2) options.log(`[pid=${spawnedProcess.pid}] taskkill stdout: ${stdout2}`); if (stderr2) options.log(`[pid=${spawnedProcess.pid}] taskkill stderr: ${stderr2}`); } else { process.kill(-spawnedProcess.pid, "SIGKILL"); } } catch (e) { options.log(`[pid=${spawnedProcess.pid}] exception while trying to kill process: ${e}`); } } else { options.log(`[pid=${spawnedProcess.pid}] `); } } function killProcessAndCleanup() { killProcess(); options.log(`[pid=${spawnedProcess.pid || "N/A"}] starting temporary directories cleanup`); for (const dir of options.tempDirectories) { try { import_fs6.default.rmSync(dir, { force: true, recursive: true, maxRetries: 5 }); } catch (e) { options.log(`[pid=${spawnedProcess.pid || "N/A"}] exception while removing ${dir}: ${e}`); } } options.log(`[pid=${spawnedProcess.pid || "N/A"}] finished temporary directories cleanup`); } function killAndWait() { killProcess(); return waitForCleanup; } return { launchedProcess: spawnedProcess, gracefullyClose, kill: killAndWait }; } function envArrayToObject(env) { const result2 = {}; for (const { name, value: value2 } of env) result2[name] = value2; return result2; } var childProcess, import_fs6, readline, gracefullyCloseSet, killSet, sigintHandlerCalled, installedHandlers, processHandlers; var init_processLauncher = __esm({ "packages/utils/processLauncher.ts"() { "use strict"; childProcess = __toESM(require("child_process")); import_fs6 = __toESM(require("fs")); readline = __toESM(require("readline")); init_fileUtils(); init_debug(); gracefullyCloseSet = /* @__PURE__ */ new Set(); killSet = /* @__PURE__ */ new Set(); sigintHandlerCalled = false; installedHandlers = /* @__PURE__ */ new Set(); processHandlers = { exit: exitHandler, SIGINT: sigintHandler, SIGTERM: sigtermHandler, SIGHUP: sighupHandler }; } }); // packages/utils/profiler.ts async function startProfiling() { if (!profileDir) return; session = new (require("inspector")).Session(); session.connect(); await new Promise((f) => { session.post("Profiler.enable", () => { session.post("Profiler.start", f); }); }); } async function stopProfiling(profileName) { if (!profileDir) return; await new Promise((f) => session.post("Profiler.stop", (err, { profile }) => { if (!err) { import_fs7.default.mkdirSync(profileDir, { recursive: true }); import_fs7.default.writeFileSync(import_path5.default.join(profileDir, profileName + ".json"), JSON.stringify(profile)); } f(); })); } var import_fs7, import_path5, profileDir, session; var init_profiler = __esm({ "packages/utils/profiler.ts"() { "use strict"; import_fs7 = __toESM(require("fs")); import_path5 = __toESM(require("path")); profileDir = process.env.PWTEST_PROFILE_DIR || ""; } }); // packages/utils/serializedFS.ts var import_fs8, yazl, APPEND_CHUNK_SIZE, SerializedFS; var init_serializedFS = __esm({ "packages/utils/serializedFS.ts"() { "use strict"; import_fs8 = __toESM(require("fs")); init_manualPromise(); yazl = require("./utilsBundle").yazl; APPEND_CHUNK_SIZE = 64 * 1024; SerializedFS = class { constructor() { this._buffers = /* @__PURE__ */ new Map(); this._operations = []; this._operationsDone = new ManualPromise(); this._operationsDone.resolve(); } mkdir(dir) { this._appendOperation({ op: "mkdir", dir }); } writeFile(file, content, skipIfExists) { this._buffers.delete(file); this._appendOperation({ op: "writeFile", file, content, skipIfExists }); } appendFile(file, text2, flush) { if (!this._buffers.has(file)) this._buffers.set(file, []); const buffer = this._buffers.get(file); buffer.push(text2); let size = 0; for (const chunk of buffer) size += chunk.length; if (flush || size >= APPEND_CHUNK_SIZE) this._flushFile(file); } _flushFile(file) { const buffer = this._buffers.get(file); if (buffer === void 0) return; const content = buffer.join(""); this._buffers.delete(file); this._appendOperation({ op: "appendFile", file, content }); } copyFile(from, to) { this._flushFile(from); this._buffers.delete(to); this._appendOperation({ op: "copyFile", from, to }); } async syncAndGetError() { for (const file of this._buffers.keys()) this._flushFile(file); await this._operationsDone; return this._error; } zip(entries, zipFileName) { for (const file of this._buffers.keys()) this._flushFile(file); this._appendOperation({ op: "zip", entries, zipFileName }); } // This method serializes all writes to the trace. _appendOperation(op) { const last = this._operations[this._operations.length - 1]; if (last?.op === "appendFile" && op.op === "appendFile" && last.file === op.file && last.content.length < APPEND_CHUNK_SIZE) { last.content += op.content; return; } this._operations.push(op); if (this._operationsDone.isDone()) this._performOperations(); } async _performOperations() { this._operationsDone = new ManualPromise(); while (this._operations.length) { const op = this._operations.shift(); if (this._error) continue; try { await this._performOperation(op); } catch (e) { this._error = e; } } this._operationsDone.resolve(); } async _performOperation(op) { switch (op.op) { case "mkdir": { await import_fs8.default.promises.mkdir(op.dir, { recursive: true }); return; } case "writeFile": { if (op.skipIfExists) await import_fs8.default.promises.writeFile(op.file, op.content, { flag: "wx" }).catch(() => { }); else await import_fs8.default.promises.writeFile(op.file, op.content); return; } case "copyFile": { await import_fs8.default.promises.copyFile(op.from, op.to); return; } case "appendFile": { await import_fs8.default.promises.appendFile(op.file, op.content); return; } case "zip": { const zipFile = new yazl.ZipFile(); const result2 = new ManualPromise(); zipFile.on("error", (error) => result2.reject(error)); for (const entry of op.entries) zipFile.addFile(entry.value, entry.name); zipFile.end(); zipFile.outputStream.pipe(import_fs8.default.createWriteStream(op.zipFileName)).on("close", () => result2.resolve()).on("error", (error) => result2.reject(error)); await result2; return; } } } }; } }); // packages/utils/socksProxy.ts function hexToNumber(hex) { return [...hex].reduce((value2, digit2) => { const code = digit2.charCodeAt(0); if (code >= 48 && code <= 57) return value2 + code; if (code >= 97 && code <= 102) return value2 + (code - 97) + 10; if (code >= 65 && code <= 70) return value2 + (code - 65) + 10; throw new Error("Invalid IPv6 token " + hex); }, 0); } function ipToSocksAddress(address) { const ipv4Mapped = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i.exec(address); if (ipv4Mapped) address = ipv4Mapped[1]; if (import_net2.default.isIPv4(address)) { return [ 1, // IPv4 ...address.split(".", 4).map((t) => +t & 255) // Address ]; } if (import_net2.default.isIPv6(address)) { const result2 = [4]; const tokens = address.split(":", 8); while (tokens.length < 8) tokens.unshift(""); for (const token of tokens) { const value2 = hexToNumber(token); result2.push(value2 >> 8 & 255, value2 & 255); } return result2; } throw new Error("Only IPv4 and IPv6 addresses are supported"); } function starMatchToRegex(pattern) { const source11 = pattern.split("*").map((s) => { return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }).join(".*"); return new RegExp("^" + source11 + "$"); } function parsePattern(pattern) { if (!pattern) return () => false; const matchers = pattern.split(",").map((token) => { const match = token.match(/^(.*?)(?::(\d+))?$/); if (!match) throw new Error(`Unsupported token "${token}" in pattern "${pattern}"`); const tokenPort = match[2] ? +match[2] : void 0; const portMatches = (port) => tokenPort === void 0 || tokenPort === port; let tokenHost = match[1]; if (tokenHost === "") { return (host, port) => { if (!portMatches(port)) return false; return host === "localhost" || host.endsWith(".localhost") || host === "127.0.0.1" || host === "[::1]"; }; } if (tokenHost === "*") return (host, port) => portMatches(port); if (import_net2.default.isIPv4(tokenHost) || import_net2.default.isIPv6(tokenHost)) return (host, port) => host === tokenHost && portMatches(port); if (tokenHost[0] === ".") tokenHost = "*" + tokenHost; const tokenRegex = starMatchToRegex(tokenHost); return (host, port) => { if (!portMatches(port)) return false; if (import_net2.default.isIPv4(host) || import_net2.default.isIPv6(host)) return false; return !!host.match(tokenRegex); }; }); return (host, port) => matchers.some((matcher) => matcher(host, port)); } var import_events2, import_net2, SocksConnection, SocksProxy, SocksProxyHandler; var init_socksProxy = __esm({ "packages/utils/socksProxy.ts"() { "use strict"; import_events2 = __toESM(require("events")); import_net2 = __toESM(require("net")); init_assert(); init_crypto(); init_debugLogger(); init_happyEyeballs(); SocksConnection = class { constructor(uid, socket, client) { this._buffer = Buffer.from([]); this._offset = 0; this._fence = 0; this._uid = uid; this._socket = socket; this._client = client; this._boundOnData = this._onData.bind(this); socket.on("data", this._boundOnData); socket.on("close", () => this._onClose()); socket.on("end", () => this._onClose()); socket.on("error", () => this._onClose()); this._run().catch(() => this._socket.end()); } async _run() { assert(await this._authenticate()); const { command, host, port } = await this._parseRequest(); if (command !== 1 /* CONNECT */) { this._writeBytes(Buffer.from([ 5, 7 /* CommandNotSupported */, 0, // RSV 1, // IPv4 0, 0, 0, 0, // Address 0, 0 // Port ])); return; } this._socket.off("data", this._boundOnData); this._client.onSocketRequested({ uid: this._uid, host, port }); } async _authenticate() { const version3 = await this._readByte(); assert(version3 === 5, "The VER field must be set to x05 for this version of the protocol, was " + version3); const nMethods = await this._readByte(); assert(nMethods, "No authentication methods specified"); const methods = await this._readBytes(nMethods); for (const method of methods) { if (method === 0) { this._writeBytes(Buffer.from([version3, method])); return true; } } this._writeBytes(Buffer.from([version3, 255 /* NO_ACCEPTABLE_METHODS */])); return false; } async _parseRequest() { const version3 = await this._readByte(); assert(version3 === 5, "The VER field must be set to x05 for this version of the protocol, was " + version3); const command = await this._readByte(); await this._readByte(); const addressType = await this._readByte(); let host = ""; switch (addressType) { case 1 /* IPv4 */: host = (await this._readBytes(4)).join("."); break; case 3 /* FqName */: const length = await this._readByte(); host = (await this._readBytes(length)).toString(); break; case 4 /* IPv6 */: const bytes = await this._readBytes(16); const tokens = []; for (let i = 0; i < 8; ++i) tokens.push(bytes.readUInt16BE(i * 2).toString(16)); host = tokens.join(":"); break; } const port = (await this._readBytes(2)).readUInt16BE(0); this._buffer = Buffer.from([]); this._offset = 0; this._fence = 0; return { command, host, port }; } async _readByte() { const buffer = await this._readBytes(1); return buffer[0]; } async _readBytes(length) { this._fence = this._offset + length; if (!this._buffer || this._buffer.length < this._fence) await new Promise((f) => this._fenceCallback = f); this._offset += length; return this._buffer.slice(this._offset - length, this._offset); } _writeBytes(buffer) { if (this._socket.writable) this._socket.write(buffer); } _onClose() { this._client.onSocketClosed({ uid: this._uid }); } _onData(buffer) { this._buffer = Buffer.concat([this._buffer, buffer]); if (this._fenceCallback && this._buffer.length >= this._fence) { const callback = this._fenceCallback; this._fenceCallback = void 0; callback(); } } socketConnected(host, port) { this._writeBytes(Buffer.from([ 5, 0 /* Succeeded */, 0, // RSV ...ipToSocksAddress(host), // ATYP, Address port >> 8, port & 255 // Port ])); this._socket.on("data", (data) => this._client.onSocketData({ uid: this._uid, data })); } socketFailed(errorCode) { const buffer = Buffer.from([ 5, 0, 0, // RSV ...ipToSocksAddress("0.0.0.0"), // ATYP, Address 0, 0 // Port ]); switch (errorCode) { case "ENOENT": case "ENOTFOUND": case "ETIMEDOUT": case "EHOSTUNREACH": buffer[1] = 4 /* HostUnreachable */; break; case "ENETUNREACH": buffer[1] = 3 /* NetworkUnreachable */; break; case "ECONNREFUSED": buffer[1] = 5 /* ConnectionRefused */; break; case "ERULESET": buffer[1] = 2 /* NotAllowedByRuleSet */; break; } this._writeBytes(buffer); this._socket.end(); } sendData(data) { this._socket.write(data); } end() { this._socket.end(); } error(error) { this._socket.destroy(new Error(error)); } }; SocksProxy = class _SocksProxy extends import_events2.default { constructor() { super(); this._connections = /* @__PURE__ */ new Map(); this._sockets = /* @__PURE__ */ new Set(); this._closed = false; this._patternMatcher = () => false; this._directSockets = /* @__PURE__ */ new Map(); this._server = new import_net2.default.Server((socket) => { const uid = createGuid(); const connection = new SocksConnection(uid, socket, this); this._connections.set(uid, connection); }); this._server.on("connection", (socket) => { if (this._closed) { socket.destroy(); return; } this._sockets.add(socket); socket.once("close", () => this._sockets.delete(socket)); }); } static { this.Events = { SocksRequested: "socksRequested", SocksData: "socksData", SocksClosed: "socksClosed" }; } setPattern(pattern) { try { this._patternMatcher = parsePattern(pattern); } catch (e) { this._patternMatcher = () => false; } } async _handleDirect(request2) { try { const socket = await createSocket(request2.host, request2.port); socket.on("data", (data) => this._connections.get(request2.uid)?.sendData(data)); socket.on("error", (error) => { this._connections.get(request2.uid)?.error(error.message); this._directSockets.delete(request2.uid); }); socket.on("end", () => { this._connections.get(request2.uid)?.end(); this._directSockets.delete(request2.uid); }); const localAddress = socket.localAddress; const localPort = socket.localPort; this._directSockets.set(request2.uid, socket); this._connections.get(request2.uid)?.socketConnected(localAddress, localPort); } catch (error) { this._connections.get(request2.uid)?.socketFailed(error.code); } } port() { return this._port; } async listen(port, hostname) { return new Promise((f) => { this._server.listen(port, hostname, () => { const port2 = this._server.address().port; this._port = port2; f(port2); }); }); } async close() { if (this._closed) return; this._closed = true; for (const socket of this._sockets) socket.destroy(); this._sockets.clear(); await new Promise((f) => this._server.close(f)); } onSocketRequested(payload) { if (!this._patternMatcher(payload.host, payload.port)) { this._handleDirect(payload); return; } this.emit(_SocksProxy.Events.SocksRequested, payload); } onSocketData(payload) { const direct = this._directSockets.get(payload.uid); if (direct) { direct.write(payload.data); return; } this.emit(_SocksProxy.Events.SocksData, payload); } onSocketClosed(payload) { const direct = this._directSockets.get(payload.uid); if (direct) { direct.destroy(); this._directSockets.delete(payload.uid); return; } this.emit(_SocksProxy.Events.SocksClosed, payload); } socketConnected({ uid, host, port }) { this._connections.get(uid)?.socketConnected(host, port); } socketFailed({ uid, errorCode }) { this._connections.get(uid)?.socketFailed(errorCode); } sendSocketData({ uid, data }) { this._connections.get(uid)?.sendData(data); } sendSocketEnd({ uid }) { this._connections.get(uid)?.end(); } sendSocketError({ uid, error }) { this._connections.get(uid)?.error(error); } }; SocksProxyHandler = class _SocksProxyHandler extends import_events2.default { constructor(pattern, redirectPortForTest) { super(); this._sockets = /* @__PURE__ */ new Map(); this._patternMatcher = () => false; this._patternMatcher = parsePattern(pattern); this._redirectPortForTest = redirectPortForTest; } static { this.Events = { SocksConnected: "socksConnected", SocksData: "socksData", SocksError: "socksError", SocksFailed: "socksFailed", SocksEnd: "socksEnd" }; } cleanup() { for (const uid of this._sockets.keys()) this.socketClosed({ uid }); } async socketRequested({ uid, host, port }) { debugLogger.log("socks", `[${uid}] => request ${host}:${port}`); if (!this._patternMatcher(host, port)) { const payload = { uid, errorCode: "ERULESET" }; debugLogger.log("socks", `[${uid}] <= pattern error ${payload.errorCode}`); this.emit(_SocksProxyHandler.Events.SocksFailed, payload); return; } if (host === "local.playwright") host = "localhost"; try { if (this._redirectPortForTest) port = this._redirectPortForTest; const socket = await createSocket(host, port); socket.on("data", (data) => { const payload2 = { uid, data }; this.emit(_SocksProxyHandler.Events.SocksData, payload2); }); socket.on("error", (error) => { const payload2 = { uid, error: error.message }; debugLogger.log("socks", `[${uid}] <= network socket error ${payload2.error}`); this.emit(_SocksProxyHandler.Events.SocksError, payload2); this._sockets.delete(uid); }); socket.on("end", () => { const payload2 = { uid }; debugLogger.log("socks", `[${uid}] <= network socket closed`); this.emit(_SocksProxyHandler.Events.SocksEnd, payload2); this._sockets.delete(uid); }); const localAddress = socket.localAddress; const localPort = socket.localPort; this._sockets.set(uid, socket); const payload = { uid, host: localAddress, port: localPort }; debugLogger.log("socks", `[${uid}] <= connected to network ${payload.host}:${payload.port}`); this.emit(_SocksProxyHandler.Events.SocksConnected, payload); } catch (error) { const payload = { uid, errorCode: error.code }; debugLogger.log("socks", `[${uid}] <= connect error ${payload.errorCode}`); this.emit(_SocksProxyHandler.Events.SocksFailed, payload); } } sendSocketData({ uid, data }) { this._sockets.get(uid)?.write(data); } socketClosed({ uid }) { debugLogger.log("socks", `[${uid}] <= browser socket closed`); this._sockets.get(uid)?.destroy(); this._sockets.delete(uid); } }; } }); // packages/utils/spawnAsync.ts function spawnAsync(cmd, args, options = {}) { const process2 = (0, import_child_process.spawn)(cmd, args, Object.assign({ windowsHide: true }, options)); return new Promise((resolve) => { let stdout = ""; let stderr = ""; if (process2.stdout) process2.stdout.on("data", (data) => stdout += data.toString()); if (process2.stderr) process2.stderr.on("data", (data) => stderr += data.toString()); process2.on("close", (code) => resolve({ stdout, stderr, code })); process2.on("error", (error) => resolve({ stdout, stderr, code: 0, error })); }); } var import_child_process; var init_spawnAsync = __esm({ "packages/utils/spawnAsync.ts"() { "use strict"; import_child_process = require("child_process"); } }); // packages/utils/stringWidth.ts function characterWidth(c) { return getEastAsianWidth.eastAsianWidth(c.codePointAt(0)); } function stringWidth(v) { let width = 0; for (const { segment } of new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(v)) width += characterWidth(segment); return width; } function suffixOfWidth(v, width) { const segments = [...new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(v)]; let suffixBegin = v.length; for (const { segment, index } of segments.reverse()) { const segmentWidth = stringWidth(segment); if (segmentWidth > width) break; width -= segmentWidth; suffixBegin = index; } return v.substring(suffixBegin); } function fitToWidth(line, width, prefix) { const prefixLength = prefix ? stripAnsiEscapes(prefix).length : 0; width -= prefixLength; if (stringWidth(line) <= width) return line; const parts = line.split(ansiRegex); const taken = []; for (let i = parts.length - 1; i >= 0; i--) { if (i % 2) { taken.push(parts[i]); } else { let part = suffixOfWidth(parts[i], width); const wasTruncated = part.length < parts[i].length; if (wasTruncated && parts[i].length > 0) { part = "\u2026" + suffixOfWidth(parts[i], width - 1); } taken.push(part); width -= stringWidth(part); } } return taken.reverse().join(""); } var getEastAsianWidth; var init_stringWidth = __esm({ "packages/utils/stringWidth.ts"() { "use strict"; init_stringUtils(); getEastAsianWidth = require("./utilsBundle").getEastAsianWidth; } }); // packages/utils/task.ts function makeWaitForNextTask() { if (process.versions.electron) return (callback) => setTimeout(callback, 0); if (parseInt(process.versions.node, 10) >= 11) return setImmediate; let spinning = false; const callbacks = []; const loop = () => { const callback = callbacks.shift(); if (!callback) { spinning = false; return; } setImmediate(loop); callback(); }; return (callback) => { callbacks.push(callback); if (!spinning) { spinning = true; setImmediate(loop); } }; } var init_task = __esm({ "packages/utils/task.ts"() { "use strict"; } }); // packages/utils/wsServer.ts var wsServer2, lastConnectionId, kConnectionSymbol, perMessageDeflate, WSServer; var init_wsServer = __esm({ "packages/utils/wsServer.ts"() { "use strict"; init_httpServer(); init_network(); init_debugLogger(); ({ wsServer: wsServer2 } = require("./utilsBundle")); lastConnectionId = 0; kConnectionSymbol = Symbol("kConnection"); perMessageDeflate = { serverNoContextTakeover: true, zlibDeflateOptions: { level: 3 }, zlibInflateOptions: { chunkSize: 10 * 1024 }, threshold: 10 * 1024 }; WSServer = class { constructor(delegate) { // Allowed Host headers for HTTP requests. null disables the check (server bound to a public address). this._allowedHosts = null; this._delegate = delegate; } async listen(port = 0, hostname, path59) { debugLogger.log("server", `Server started at ${/* @__PURE__ */ new Date()}`); hostname ??= "localhost"; const server = createHttpServer((request2, response2) => this._onRequest(request2, response2)); server.on("error", (error) => debugLogger.log("server", String(error))); this.server = server; const wsEndpoint = await new Promise((resolve, reject) => { server.listen(port, hostname, () => { const address = server.address(); if (!address) { reject(new Error("Could not bind server socket")); return; } if (typeof address === "string") { resolve(`${address}${path59}`); return; } this._allowedHosts = computeAllowedHosts(hostname, address.address); resolve(`ws://${urlHostFromAddress(address)}:${address.port}${path59}`); }).on("error", reject); }); debugLogger.log("server", "Listening at " + wsEndpoint); this._wsServer = new wsServer2({ noServer: true, perMessageDeflate }); this._wsServer.on("headers", (headers) => this._delegate.onHeaders(headers)); server.on("upgrade", (request2, socket, head) => { const pathname = new URL("http://localhost" + request2.url).pathname; if (pathname !== path59) { socket.write(`HTTP/${request2.httpVersion} 400 Bad Request\r \r `); socket.destroy(); return; } if (this._allowedHosts && !this._isAllowedOrigin(request2.headers.origin)) { socket.write(`HTTP/${request2.httpVersion} 403 Forbidden\r \r `); socket.destroy(); return; } const upgradeResult = this._delegate.onUpgrade(request2, socket); if (upgradeResult) { socket.write(upgradeResult.error); socket.destroy(); return; } this._wsServer.handleUpgrade(request2, socket, head, (ws4) => this._wsServer.emit("connection", ws4, request2)); }); this._wsServer.on("connection", (ws4, request2) => { debugLogger.log("server", "Connected client ws.extension=" + ws4.extensions); const url2 = new URL("http://localhost" + (request2.url || "")); const id = String(++lastConnectionId); debugLogger.log("server", `[${id}] serving connection: ${request2.url}`); const connection = this._delegate.onConnection(request2, url2, ws4, id); ws4[kConnectionSymbol] = connection; }); return wsEndpoint; } _onRequest(request2, response2) { if (this._allowedHosts) { const host = request2.headers.host?.toLowerCase(); const hostname = host ? hostnameFromHostHeader(host) : void 0; if (!hostname || !this._allowedHosts.has(hostname)) { response2.statusCode = 403; response2.end(); return; } } this._delegate.onRequest(request2, response2); } _isAllowedOrigin(origin) { if (!origin) return true; try { const hostname = new URL(origin).hostname.toLowerCase(); const bracketed = hostname.includes(":") ? `[${hostname}]` : hostname; return this._allowedHosts.has(hostname) || this._allowedHosts.has(bracketed); } catch { return false; } } async close() { const server = this._wsServer; if (!server) return; debugLogger.log("server", "closing websocket server"); const waitForClose = new Promise((f) => server.close(f)); await Promise.all(Array.from(server.clients).map(async (ws4) => { const connection = ws4[kConnectionSymbol]; if (connection) await connection.close(); try { ws4.terminate(); } catch (e) { } })); await waitForClose; debugLogger.log("server", "closing http server"); if (this.server) await new Promise((f) => this.server.close(f)); this._wsServer = void 0; this.server = void 0; debugLogger.log("server", "closed server"); } }; } }); // packages/utils/zipFile.ts var yauzl, ZipFile; var init_zipFile = __esm({ "packages/utils/zipFile.ts"() { "use strict"; yauzl = require("./utilsBundle").yauzl; ZipFile = class { constructor(fileName) { this._entries = /* @__PURE__ */ new Map(); this._fileName = fileName; this._openedPromise = this._open(); } async _open() { await new Promise((fulfill, reject) => { yauzl.open(this._fileName, { autoClose: false }, (e, z31) => { if (e) { reject(e); return; } this._zipFile = z31; this._zipFile.on("entry", (entry) => { this._entries.set(entry.fileName, entry); }); this._zipFile.on("end", fulfill); }); }); } async entries() { await this._openedPromise; return [...this._entries.keys()]; } async read(entryPath) { await this._openedPromise; const entry = this._entries.get(entryPath); if (!entry) throw new Error(`${entryPath} not found in file ${this._fileName}`); return new Promise((resolve, reject) => { this._zipFile.openReadStream(entry, (error, readStream) => { if (error || !readStream) { reject(error || "Entry not found"); return; } const buffers = []; readStream.on("data", (data) => buffers.push(data)); readStream.on("end", () => resolve(Buffer.concat(buffers))); }); }); } close() { this._zipFile?.close(); } }; } }); // packages/utils/third_party/extractZip.ts async function extractZip(zipPath, opts) { debug2("creating target directory", opts.dir); if (!import_path6.default.isAbsolute(opts.dir)) throw new Error("Target directory is expected to be absolute"); await import_fs9.promises.mkdir(opts.dir, { recursive: true }); opts.dir = await import_fs9.promises.realpath(opts.dir); return new Extractor(zipPath, opts).extract(); } var import_fs9, import_path6, import_stream2, import_util, debugPkg, getStream, yauzl2, debug2, openZip, pipeline2, Extractor; var init_extractZip = __esm({ "packages/utils/third_party/extractZip.ts"() { "use strict"; import_fs9 = require("fs"); import_path6 = __toESM(require("path")); import_stream2 = __toESM(require("stream")); import_util = require("util"); debugPkg = require("./utilsBundle").debug; getStream = require("./utilsBundle").getStream; yauzl2 = require("./utilsBundle").yauzl; debug2 = debugPkg("extract-zip"); openZip = (0, import_util.promisify)(yauzl2.open); pipeline2 = (0, import_util.promisify)(import_stream2.default.pipeline); Extractor = class { constructor(zipPath, opts) { this.canceled = false; this.zipPath = zipPath; this.opts = opts; } async extract() { debug2("opening", this.zipPath, "with opts", this.opts); this.zipfile = await openZip(this.zipPath, { lazyEntries: true }); this.canceled = false; return new Promise((resolve, reject) => { this.zipfile.on("error", (err) => { this.canceled = true; reject(err); }); this.zipfile.readEntry(); this.zipfile.on("close", () => { if (!this.canceled) { debug2("zip extraction complete"); resolve(); } }); this.zipfile.on("entry", async (entry) => { if (this.canceled) { debug2("skipping entry", entry.fileName, { cancelled: this.canceled }); return; } debug2("zipfile entry", entry.fileName); if (entry.fileName.startsWith("__MACOSX/")) { this.zipfile.readEntry(); return; } const destDir = import_path6.default.dirname(import_path6.default.join(this.opts.dir, entry.fileName)); try { await import_fs9.promises.mkdir(destDir, { recursive: true }); const canonicalDestDir = await import_fs9.promises.realpath(destDir); const relativeDestDir = import_path6.default.relative(this.opts.dir, canonicalDestDir); if (relativeDestDir.split(import_path6.default.sep).includes("..")) throw new Error(`Out of bound path "${canonicalDestDir}" found while processing file ${entry.fileName}`); await this.extractEntry(entry); debug2("finished processing", entry.fileName); this.zipfile.readEntry(); } catch (err) { this.canceled = true; this.zipfile.close(); reject(err); } }); }); } async extractEntry(entry) { if (this.canceled) { debug2("skipping entry extraction", entry.fileName, { cancelled: this.canceled }); return; } if (this.opts.onEntry) this.opts.onEntry(entry, this.zipfile); const dest = import_path6.default.join(this.opts.dir, entry.fileName); const mode = entry.externalFileAttributes >> 16 & 65535; const IFMT = 61440; const IFDIR = 16384; const IFLNK = 40960; const symlink = (mode & IFMT) === IFLNK; let isDir = (mode & IFMT) === IFDIR; if (!isDir && entry.fileName.endsWith("/")) isDir = true; const madeBy = entry.versionMadeBy >> 8; if (!isDir) isDir = madeBy === 0 && entry.externalFileAttributes === 16; debug2("extracting entry", { filename: entry.fileName, isDir, isSymlink: symlink }); const procMode = this.getExtractedMode(mode, isDir) & 511; const destDir = isDir ? dest : import_path6.default.dirname(dest); const mkdirOptions = { recursive: true }; if (isDir) mkdirOptions.mode = procMode; debug2("mkdir", { dir: destDir, ...mkdirOptions }); await import_fs9.promises.mkdir(destDir, mkdirOptions); if (isDir) return; debug2("opening read stream", dest); const readStream = await (0, import_util.promisify)(this.zipfile.openReadStream.bind(this.zipfile))(entry); if (symlink) { const link = await getStream(readStream); debug2("creating symlink", link, dest); await import_fs9.promises.symlink(link, dest); } else { await pipeline2(readStream, (0, import_fs9.createWriteStream)(dest, { mode: procMode })); } } getExtractedMode(entryMode, isDir) { let mode = entryMode; if (mode === 0) { if (isDir) { if (this.opts.defaultDirMode) mode = Number(this.opts.defaultDirMode); if (!mode) mode = 493; } else { if (this.opts.defaultFileMode) mode = Number(this.opts.defaultFileMode); if (!mode) mode = 420; } } return mode; } }; } }); // packages/utils/third_party/lockfile.ts function probe(file, fs61, callback) { const cachedPrecision = fs61[cacheSymbol]; if (cachedPrecision) { return fs61.stat(file, (err, stat) => { if (err) return callback(err); callback(null, stat.mtime, cachedPrecision); }); } const mtime = new Date(Math.ceil(Date.now() / 1e3) * 1e3 + 5); fs61.utimes(file, mtime, mtime, (err) => { if (err) return callback(err); fs61.stat(file, (err2, stat) => { if (err2) return callback(err2); const precision = stat.mtime.getTime() % 1e3 === 0 ? "s" : "ms"; Object.defineProperty(fs61, cacheSymbol, { value: precision }); callback(null, stat.mtime, precision); }); }); } function getMtime(precision) { let now = Date.now(); if (precision === "s") now = Math.ceil(now / 1e3) * 1e3; return new Date(now); } function getLockFile(file, options) { return options.lockfilePath || `${file}.lock`; } function resolveCanonicalPath(file, options, callback) { if (!options.realpath) return callback(null, import_path7.default.resolve(file)); options.fs.realpath(file, callback); } function acquireLock(file, options, callback) { const lockfilePath = getLockFile(file, options); options.fs.mkdir(lockfilePath, (err) => { if (!err) { return probe(lockfilePath, options.fs, (err2, mtime, mtimePrecision) => { if (err2) { options.fs.rmdir(lockfilePath, () => { }); return callback(err2); } callback(null, mtime, mtimePrecision); }); } if (err.code !== "EEXIST") return callback(err); if (options.stale <= 0) return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file })); options.fs.stat(lockfilePath, (err2, stat) => { if (err2) { if (err2.code === "ENOENT") return acquireLock(file, { ...options, stale: 0 }, callback); return callback(err2); } if (!isLockStale(stat, options)) return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file })); removeLock(file, options, (err3) => { if (err3) return callback(err3); acquireLock(file, { ...options, stale: 0 }, callback); }); }); }); } function isLockStale(stat, options) { return stat.mtime.getTime() < Date.now() - options.stale; } function removeLock(file, options, callback) { options.fs.rmdir(getLockFile(file, options), (err) => { if (err && err.code !== "ENOENT") return callback(err); callback(null); }); } function updateLock(file, options) { const lock2 = locks[file]; if (lock2.updateTimeout) return; lock2.updateDelay = lock2.updateDelay || options.update; lock2.updateTimeout = setTimeout(() => { lock2.updateTimeout = null; options.fs.stat(lock2.lockfilePath, (err, stat) => { const isOverThreshold = lock2.lastUpdate + options.stale < Date.now(); if (err) { if (err.code === "ENOENT" || isOverThreshold) return setLockAsCompromised(file, lock2, Object.assign(err, { code: "ECOMPROMISED" })); lock2.updateDelay = 1e3; return updateLock(file, options); } const isMtimeOurs = lock2.mtime.getTime() === stat.mtime.getTime(); if (!isMtimeOurs) { return setLockAsCompromised( file, lock2, Object.assign( new Error("Unable to update lock within the stale threshold"), { code: "ECOMPROMISED" } ) ); } const mtime = getMtime(lock2.mtimePrecision); options.fs.utimes(lock2.lockfilePath, mtime, mtime, (err2) => { const isOverThreshold2 = lock2.lastUpdate + options.stale < Date.now(); if (lock2.released) return; if (err2) { if (err2.code === "ENOENT" || isOverThreshold2) return setLockAsCompromised(file, lock2, Object.assign(err2, { code: "ECOMPROMISED" })); lock2.updateDelay = 1e3; return updateLock(file, options); } lock2.mtime = mtime; lock2.lastUpdate = Date.now(); lock2.updateDelay = null; updateLock(file, options); }); }); }, lock2.updateDelay); if (lock2.updateTimeout && lock2.updateTimeout.unref) lock2.updateTimeout.unref(); } function setLockAsCompromised(file, lock2, err) { lock2.released = true; if (lock2.updateTimeout) clearTimeout(lock2.updateTimeout); if (locks[file] === lock2) delete locks[file]; lock2.options.onCompromised(err); } function lockImpl(file, options, callback) { const resolvedOptions = { stale: 1e4, update: null, realpath: true, retries: 0, fs: gracefulFs, onCompromised: (err) => { throw err; }, ...options }; resolvedOptions.retries = resolvedOptions.retries || 0; resolvedOptions.retries = typeof resolvedOptions.retries === "number" ? { retries: resolvedOptions.retries } : resolvedOptions.retries; resolvedOptions.stale = Math.max(resolvedOptions.stale || 0, 2e3); resolvedOptions.update = resolvedOptions.update === null || resolvedOptions.update === void 0 ? resolvedOptions.stale / 2 : resolvedOptions.update || 0; resolvedOptions.update = Math.max(Math.min(resolvedOptions.update, resolvedOptions.stale / 2), 1e3); resolveCanonicalPath(file, resolvedOptions, (err, resolvedFile) => { if (err) return callback(err); const canonicalFile = resolvedFile; const operation = retry.operation(resolvedOptions.retries); operation.attempt(() => { acquireLock(canonicalFile, resolvedOptions, (err2, mtime, mtimePrecision) => { if (operation.retry(err2 || void 0)) return; if (err2) return callback(operation.mainError()); const lock2 = locks[canonicalFile] = { lockfilePath: getLockFile(canonicalFile, resolvedOptions), mtime, mtimePrecision, options: resolvedOptions, lastUpdate: Date.now() }; updateLock(canonicalFile, resolvedOptions); callback(null, (releasedCallback) => { if (lock2.released) { return releasedCallback && releasedCallback(Object.assign(new Error("Lock is already released"), { code: "ERELEASED" })); } unlock(canonicalFile, { ...resolvedOptions, realpath: false }, releasedCallback || (() => { })); }); }); }); }); } function unlock(file, options, callback) { const resolvedOptions = { stale: 1e4, update: null, realpath: true, retries: 0, fs: gracefulFs, onCompromised: (err) => { throw err; }, ...options }; resolveCanonicalPath(file, resolvedOptions, (err, resolvedFile) => { if (err) return callback(err); const canonicalFile = resolvedFile; const lock2 = locks[canonicalFile]; if (!lock2) return callback(Object.assign(new Error("Lock is not acquired/owned by you"), { code: "ENOTACQUIRED" })); if (lock2.updateTimeout) clearTimeout(lock2.updateTimeout); lock2.released = true; delete locks[canonicalFile]; removeLock(canonicalFile, resolvedOptions, callback); }); } function toPromise(method) { return (...args) => new Promise((resolve, reject) => { args.push((err, result2) => { if (err) reject(err); else resolve(result2); }); method(...args); }); } function ensureCleanup() { if (cleanupInitialized) return; cleanupInitialized = true; onExit(() => { for (const file in locks) { const options = locks[file].options; try { options.fs.rmdirSync(getLockFile(file, options)); } catch (e) { } } }); } async function lock(file, options) { ensureCleanup(); const release = await toPromise(lockImpl)(file, options || {}); return toPromise(release); } var import_path7, gracefulFs, retry, onExit, locks, cacheSymbol, cleanupInitialized; var init_lockfile = __esm({ "packages/utils/third_party/lockfile.ts"() { "use strict"; import_path7 = __toESM(require("path")); gracefulFs = require("./utilsBundle").gracefulFs; retry = require("./utilsBundle").retry; onExit = require("./utilsBundle").onExit; locks = {}; cacheSymbol = Symbol(); cleanupInitialized = false; } }); // packages/utils/index.ts var utils_exports = {}; __export(utils_exports, { FastStats: () => FastStats, HttpServer: () => HttpServer, ImageChannel: () => ImageChannel, NET_DEFAULT_TIMEOUT: () => NET_DEFAULT_TIMEOUT, RecentLogsCollector: () => RecentLogsCollector, SerializedFS: () => SerializedFS, SocksProxy: () => SocksProxy, SocksProxyHandler: () => SocksProxyHandler, WSServer: () => WSServer, ZipFile: () => ZipFile, Zone: () => Zone, addSuffixToFilePath: () => addSuffixToFilePath, blendWithWhite: () => blendWithWhite, calculateSha1: () => calculateSha1, canAccessFile: () => canAccessFile, colorDeltaE94: () => colorDeltaE94, compare: () => compare, compareBuffersOrStrings: () => compareBuffersOrStrings, computeAllowedHosts: () => computeAllowedHosts, copyFileAndMakeWritable: () => copyFileAndMakeWritable, createGuid: () => createGuid, createHttp2Server: () => createHttp2Server, createHttpServer: () => createHttpServer, createHttpsServer: () => createHttpsServer, createProxyAgent: () => createProxyAgent, currentZone: () => currentZone, debugLogger: () => debugLogger, debugMode: () => debugMode, decorateServer: () => decorateServer, defaultUserDataDirForChannel: () => defaultUserDataDirForChannel, emptyZone: () => emptyZone, envArrayToObject: () => envArrayToObject, eventsHelper: () => eventsHelper, existsAsync: () => existsAsync, extractZip: () => extractZip, fitToWidth: () => fitToWidth, generateSelfSignedCertificate: () => generateSelfSignedCertificate, getAsBooleanFromENV: () => getAsBooleanFromENV, getComparator: () => getComparator, getFromENV: () => getFromENV, getPackageManager: () => getPackageManager, getPackageManagerExecCommand: () => getPackageManagerExecCommand, gracefullyCloseAll: () => gracefullyCloseAll, gracefullyCloseSet: () => gracefullyCloseSet, gracefullyProcessExitDoNotHang: () => gracefullyProcessExitDoNotHang, guessClientName: () => guessClientName, hostPlatform: () => hostPlatform, hostnameFromHostHeader: () => hostnameFromHostHeader, httpRequest: () => httpRequest, isChromiumChannelName: () => isChromiumChannelName, isCodingAgent: () => isCodingAgent, isLikelyNpxGlobal: () => isLikelyNpxGlobal, isOfficiallySupportedPlatform: () => isOfficiallySupportedPlatform, isPathInside: () => isPathInside, isSystemDirectory: () => isSystemDirectory, isURLAvailable: () => isURLAvailable, isUnderTest: () => isUnderTest, isWritable: () => isWritable, jsonStringifyForceASCII: () => jsonStringifyForceASCII, launchProcess: () => launchProcess, lock: () => lock, makeSocketPath: () => makeSocketPath, makeWaitForNextTask: () => makeWaitForNextTask, mkdirIfNeeded: () => mkdirIfNeeded, nodePlatform: () => nodePlatform, parsePattern: () => parsePattern, perMessageDeflate: () => perMessageDeflate, removeFolders: () => removeFolders, resolveWithinRoot: () => resolveWithinRoot, rgb2gray: () => rgb2gray, sanitizeForFilePath: () => sanitizeForFilePath, serveFolder: () => serveFolder, setBoxedStackPrefixes: () => setBoxedStackPrefixes, setPlaywrightTestProcessEnv: () => setPlaywrightTestProcessEnv, shortPlatform: () => shortPlatform, spawnAsync: () => spawnAsync, srgb2xyz: () => srgb2xyz, ssim: () => ssim, startHttpServer: () => startHttpServer, startProfiling: () => startProfiling, stopProfiling: () => stopProfiling, stringWidth: () => stringWidth, throwingResolveWithinRoot: () => throwingResolveWithinRoot, toPosixPath: () => toPosixPath, trimLongString: () => trimLongString, urlHostFromAddress: () => urlHostFromAddress, wrapInASCIIBox: () => wrapInASCIIBox, xyz2lab: () => xyz2lab }); var init_utils = __esm({ "packages/utils/index.ts"() { "use strict"; init_ascii(); init_chromiumChannels(); init_comparators(); init_crypto(); init_debug(); init_debugLogger(); init_env(); init_eventsHelper(); init_fileUtils(); init_hostPlatform(); init_httpServer(); init_network(); init_nodePlatform(); init_processLauncher(); init_profiler(); init_serializedFS(); init_socksProxy(); init_spawnAsync(); init_stringWidth(); init_task(); init_wsServer(); init_zipFile(); init_zones(); init_extractZip(); init_lockfile(); init_colorUtils(); init_compare(); init_imageChannel(); init_stats(); } }); // packages/playwright-core/src/client/eventEmitter.ts function checkListener(listener) { if (typeof listener !== "function") throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); } function unwrapListener(l) { return wrappedListener(l) ?? l; } function unwrapListeners(arr) { return arr.map((l) => wrappedListener(l) ?? l); } function wrappedListener(l) { return l.listener; } var EventEmitter3, OnceWrapper; var init_eventEmitter = __esm({ "packages/playwright-core/src/client/eventEmitter.ts"() { "use strict"; EventEmitter3 = class { constructor(platform) { this._events = void 0; this._eventsCount = 0; this._maxListeners = void 0; this._pendingHandlers = /* @__PURE__ */ new Map(); this._platform = platform; if (this._events === void 0 || this._events === Object.getPrototypeOf(this)._events) { this._events = /* @__PURE__ */ Object.create(null); this._eventsCount = 0; } this._maxListeners = this._maxListeners || void 0; this.on = this.addListener; this.off = this.removeListener; } setMaxListeners(n) { if (typeof n !== "number" || n < 0 || Number.isNaN(n)) throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + "."); this._maxListeners = n; return this; } getMaxListeners() { return this._maxListeners === void 0 ? this._platform.defaultMaxListeners() : this._maxListeners; } emit(type3, ...args) { const events = this._events; if (events === void 0) return false; const handler = events?.[type3]; if (handler === void 0) return false; if (typeof handler === "function") { this._callHandler(type3, handler, args); } else { const len = handler.length; const listeners = handler.slice(); for (let i = 0; i < len; ++i) this._callHandler(type3, listeners[i], args); } return true; } _callHandler(type3, handler, args) { const promise = Reflect.apply(handler, this, args); if (!(promise instanceof Promise)) return; let set = this._pendingHandlers.get(type3); if (!set) { set = /* @__PURE__ */ new Set(); this._pendingHandlers.set(type3, set); } set.add(promise); promise.catch((e) => { if (this._rejectionHandler) this._rejectionHandler(e); else throw e; }).finally(() => set.delete(promise)); } addListener(type3, listener) { return this._addListener(type3, listener, false); } on(type3, listener) { return this._addListener(type3, listener, false); } _addListener(type3, listener, prepend) { checkListener(listener); let events = this._events; let existing; if (events === void 0) { events = this._events = /* @__PURE__ */ Object.create(null); this._eventsCount = 0; } else { if (events.newListener !== void 0) { this.emit("newListener", type3, unwrapListener(listener)); events = this._events; } existing = events[type3]; } if (existing === void 0) { existing = events[type3] = listener; ++this._eventsCount; } else { if (typeof existing === "function") { existing = events[type3] = prepend ? [listener, existing] : [existing, listener]; } else if (prepend) { existing.unshift(listener); } else { existing.push(listener); } const m = this.getMaxListeners(); if (m > 0 && existing.length > m && !existing.warned) { existing.warned = true; const w = new Error("Possible EventEmitter memory leak detected. " + existing.length + " " + String(type3) + " listeners added. Use emitter.setMaxListeners() to increase limit"); w.name = "MaxListenersExceededWarning"; w.emitter = this; w.type = type3; w.count = existing.length; if (!this._platform.isUnderTest()) { console.warn(w); } } } return this; } prependListener(type3, listener) { return this._addListener(type3, listener, true); } once(type3, listener) { checkListener(listener); this.on(type3, new OnceWrapper(this, type3, listener).wrapperFunction); return this; } prependOnceListener(type3, listener) { checkListener(listener); this.prependListener(type3, new OnceWrapper(this, type3, listener).wrapperFunction); return this; } removeListener(type3, listener) { checkListener(listener); const events = this._events; if (events === void 0) return this; const list = events[type3]; if (list === void 0) return this; if (list === listener || list.listener === listener) { if (--this._eventsCount === 0) { this._events = /* @__PURE__ */ Object.create(null); } else { delete events[type3]; if (events.removeListener) this.emit("removeListener", type3, list.listener ?? listener); } } else if (typeof list !== "function") { let position = -1; let originalListener; for (let i = list.length - 1; i >= 0; i--) { if (list[i] === listener || wrappedListener(list[i]) === listener) { originalListener = wrappedListener(list[i]); position = i; break; } } if (position < 0) return this; if (position === 0) list.shift(); else list.splice(position, 1); if (list.length === 1) events[type3] = list[0]; if (events.removeListener !== void 0) this.emit("removeListener", type3, originalListener || listener); } return this; } off(type3, listener) { return this.removeListener(type3, listener); } removeAllListeners(type3, options) { this._removeAllListeners(type3); if (!options) return this; if (options.behavior === "wait") { const errors = []; this._rejectionHandler = (error) => errors.push(error); return this._waitFor(type3).then(() => { if (errors.length) throw errors[0]; }); } if (options.behavior === "ignoreErrors") this._rejectionHandler = () => { }; return Promise.resolve(); } _removeAllListeners(type3) { const events = this._events; if (!events) return; if (!events.removeListener) { if (type3 === void 0) { this._events = /* @__PURE__ */ Object.create(null); this._eventsCount = 0; } else if (events[type3] !== void 0) { if (--this._eventsCount === 0) this._events = /* @__PURE__ */ Object.create(null); else delete events[type3]; } return; } if (type3 === void 0) { const keys = Object.keys(events); let key; for (let i = 0; i < keys.length; ++i) { key = keys[i]; if (key === "removeListener") continue; this._removeAllListeners(key); } this._removeAllListeners("removeListener"); this._events = /* @__PURE__ */ Object.create(null); this._eventsCount = 0; return; } const listeners = events[type3]; if (typeof listeners === "function") { this.removeListener(type3, listeners); } else if (listeners !== void 0) { for (let i = listeners.length - 1; i >= 0; i--) this.removeListener(type3, listeners[i]); } } listeners(type3) { return this._listeners(this, type3, true); } rawListeners(type3) { return this._listeners(this, type3, false); } listenerCount(type3) { const events = this._events; if (events !== void 0) { const listener = events[type3]; if (typeof listener === "function") return 1; if (listener !== void 0) return listener.length; } return 0; } eventNames() { return this._eventsCount > 0 && this._events ? Reflect.ownKeys(this._events) : []; } async _waitFor(type3) { let promises = []; if (type3) { promises = [...this._pendingHandlers.get(type3) || []]; } else { promises = []; for (const [, pending] of this._pendingHandlers) promises.push(...pending); } await Promise.all(promises); } _listeners(target, type3, unwrap) { const events = target._events; if (events === void 0) return []; const listener = events[type3]; if (listener === void 0) return []; if (typeof listener === "function") return unwrap ? [unwrapListener(listener)] : [listener]; return unwrap ? unwrapListeners(listener) : listener.slice(); } }; OnceWrapper = class { constructor(eventEmitter, eventType, listener) { this._fired = false; this._eventEmitter = eventEmitter; this._eventType = eventType; this._listener = listener; this.wrapperFunction = this._handle.bind(this); this.wrapperFunction.listener = listener; } _handle(...args) { if (this._fired) return; this._fired = true; this._eventEmitter.removeListener(this._eventType, this.wrapperFunction); return this._listener.apply(this._eventEmitter, args); } }; } }); // packages/playwright-core/src/bootstrap.ts var minimumMajorNodeVersion, currentNodeVersion, major; var init_bootstrap = __esm({ "packages/playwright-core/src/bootstrap.ts"() { "use strict"; minimumMajorNodeVersion = 18; currentNodeVersion = process.versions.node; major = +currentNodeVersion.split(".")[0]; if (major < minimumMajorNodeVersion) { console.error( "You are running Node.js " + currentNodeVersion + `. Playwright requires Node.js ${minimumMajorNodeVersion} or higher. Please update your version of Node.js.` ); process.exit(1); } if (process.env.PW_INSTRUMENT_MODULES) { const Module = require("module"); const originalLoad = Module._load; const root = { name: "", selfMs: 0, totalMs: 0, childrenMs: 0, children: [] }; let current = root; const stack = []; Module._load = function(request2, _parent, _isMain) { const node = { name: request2, selfMs: 0, totalMs: 0, childrenMs: 0, children: [] }; current.children.push(node); stack.push(current); current = node; const start3 = performance.now(); let result2; try { result2 = originalLoad.apply(this, arguments); } catch (e) { current = stack.pop(); current.children.pop(); throw e; } const duration = performance.now() - start3; node.totalMs = duration; node.selfMs = Math.max(0, duration - node.childrenMs); current = stack.pop(); current.childrenMs += duration; return result2; }; process.on("exit", () => { function printTree(node, prefix, isLast, lines2, depth) { if (node.totalMs < 1 && depth > 0) return; const connector = depth === 0 ? "" : isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 "; const time = `${node.totalMs.toFixed(1).padStart(8)}ms`; const self2 = node.children.length ? ` (self: ${node.selfMs.toFixed(1)}ms)` : ""; lines2.push(`${time} ${prefix}${connector}${node.name}${self2}`); const childPrefix = prefix + (depth === 0 ? "" : isLast ? " " : "\u2502 "); const sorted2 = node.children.slice().sort((a, b) => b.totalMs - a.totalMs); for (let i = 0; i < sorted2.length; i++) printTree(sorted2[i], childPrefix, i === sorted2.length - 1, lines2, depth + 1); } let totalModules = 0; function count(n) { totalModules++; n.children.forEach(count); } root.children.forEach(count); const lines = []; const sorted = root.children.slice().sort((a, b) => b.totalMs - a.totalMs); for (let i = 0; i < sorted.length; i++) printTree(sorted[i], "", i === sorted.length - 1, lines, 0); const totalMs = root.children.reduce((s, c) => s + c.totalMs, 0); process.stderr.write(` --- Module load tree: ${totalModules} modules, ${totalMs.toFixed(0)}ms total --- ` + lines.join("\n") + "\n"); const flat = /* @__PURE__ */ new Map(); function gather(n) { const existing = flat.get(n.name); if (existing) { existing.selfMs += n.selfMs; existing.totalMs += n.totalMs; existing.count++; } else { flat.set(n.name, { selfMs: n.selfMs, totalMs: n.totalMs, count: 1 }); } n.children.forEach(gather); } root.children.forEach(gather); const top50 = [...flat.entries()].sort((a, b) => b[1].selfMs - a[1].selfMs).slice(0, 50); const flatLines = top50.map( ([mod, { selfMs, totalMs: totalMs2, count: count2 }]) => `${selfMs.toFixed(1).padStart(8)}ms self ${totalMs2.toFixed(1).padStart(8)}ms total (x${String(count2).padStart(3)}) ${mod}` ); process.stderr.write(` --- Top 50 modules by self time --- ` + flatLines.join("\n") + "\n"); }); } } }); // packages/playwright-core/src/package.ts function libPath(...parts) { return import_path8.default.join(packageRoot, "lib", ...parts); } var import_path8, packageRoot, packageJSON, binPath; var init_package = __esm({ "packages/playwright-core/src/package.ts"() { "use strict"; import_path8 = __toESM(require("path")); packageRoot = import_path8.default.join(__dirname, ".."); packageJSON = require(import_path8.default.join(packageRoot, "package.json")); binPath = import_path8.default.join(packageRoot, "bin"); } }); // packages/playwright-core/src/tools/trace/traceParser.ts async function extractTrace(traceFile, outDir) { const zipFile = new ZipFile(traceFile); try { const entries = await zipFile.entries(); for (const entry of entries) { const outPath = resolveWithinRoot(outDir, entry); if (!outPath) throw new Error(`Trace entry '${entry}' escapes output directory`); await import_fs10.default.promises.mkdir(import_path9.default.dirname(outPath), { recursive: true }); const buffer = await zipFile.read(entry); await import_fs10.default.promises.writeFile(outPath, buffer); } } finally { zipFile.close(); } } var import_fs10, import_path9, DirTraceLoaderBackend; var init_traceParser = __esm({ "packages/playwright-core/src/tools/trace/traceParser.ts"() { "use strict"; import_fs10 = __toESM(require("fs")); import_path9 = __toESM(require("path")); init_fileUtils(); init_zipFile(); DirTraceLoaderBackend = class { constructor(dir) { this._dir = dir; } isLive() { return false; } async entryNames() { const entries = []; const walk = async (dir, prefix) => { const items = await import_fs10.default.promises.readdir(dir, { withFileTypes: true }); for (const item of items) { if (item.isDirectory()) await walk(import_path9.default.join(dir, item.name), prefix ? `${prefix}/${item.name}` : item.name); else entries.push(prefix ? `${prefix}/${item.name}` : item.name); } }; await walk(this._dir, ""); return entries; } async hasEntry(entryName) { const resolved = resolveWithinRoot(this._dir, entryName); if (!resolved) return false; try { await import_fs10.default.promises.access(resolved); return true; } catch { return false; } } async readText(entryName) { const resolved = resolveWithinRoot(this._dir, entryName); if (!resolved) return; try { return await import_fs10.default.promises.readFile(resolved, "utf-8"); } catch { } } async readBlob(entryName) { const resolved = resolveWithinRoot(this._dir, entryName); if (!resolved) return; try { const buffer = await import_fs10.default.promises.readFile(resolved); return new Blob([new Uint8Array(buffer)]); } catch { } } }; } }); // packages/playwright-core/src/tools/trace/traceUtils.ts function ensureTraceOpen() { if (!import_fs11.default.existsSync(traceDir)) throw new Error(`No trace opened. Run 'npx playwright trace open ' first.`); return traceDir; } async function closeTrace() { if (import_fs11.default.existsSync(traceDir)) await import_fs11.default.promises.rm(traceDir, { recursive: true }); } async function openTrace(traceFile) { const filePath = import_path10.default.resolve(traceFile); if (!import_fs11.default.existsSync(filePath)) throw new Error(`Trace file not found: ${filePath}`); await closeTrace(); await import_fs11.default.promises.mkdir(traceDir, { recursive: true }); if (filePath.endsWith(".zip")) await extractTrace(filePath, traceDir); else await import_fs11.default.promises.writeFile(import_path10.default.join(traceDir, ".link"), filePath, "utf-8"); } async function loadTrace() { const dir = ensureTraceOpen(); const linkFile = import_path10.default.join(dir, ".link"); let traceDir2; let traceFile; if (import_fs11.default.existsSync(linkFile)) { const tracePath = await import_fs11.default.promises.readFile(linkFile, "utf-8"); traceDir2 = import_path10.default.dirname(tracePath); traceFile = import_path10.default.basename(tracePath); } else { traceDir2 = dir; } const backend = new DirTraceLoaderBackend(traceDir2); const loader = new TraceLoader(); await loader.load(backend, traceFile); const model = new TraceModel(traceDir2, loader.contextEntries); return new LoadedTrace(model, loader, buildOrdinalMap(model)); } function formatTimestamp(ms, base) { const relative = ms - base; if (relative < 0) return "0:00.000"; const totalMs = Math.floor(relative); const minutes = Math.floor(totalMs / 6e4); const seconds = Math.floor(totalMs % 6e4 / 1e3); const millis = totalMs % 1e3; return `${minutes}:${seconds.toString().padStart(2, "0")}.${millis.toString().padStart(3, "0")}`; } function actionTitle(action) { return renderTitleForCall({ ...action, type: action.class }) || `${action.class}.${action.method}`; } async function saveOutputFile(fileName, content, explicitOutput) { let outFile; if (explicitOutput) { outFile = explicitOutput; } else { const resolved = resolveWithinRoot(cliOutputDir, fileName); if (!resolved) throw new Error(`Attachment name '${fileName}' escapes output directory`); await import_fs11.default.promises.mkdir(import_path10.default.dirname(resolved), { recursive: true }); outFile = resolved; } await import_fs11.default.promises.writeFile(outFile, content); return outFile; } function buildOrdinalMap(model) { const actions = model.actions.filter((a) => a.group !== "configuration"); const { rootItem } = buildActionTree(actions); const ordinalToCallId = /* @__PURE__ */ new Map(); const callIdToOrdinal = /* @__PURE__ */ new Map(); let ordinal = 1; const visit = (item) => { ordinalToCallId.set(ordinal, item.action.callId); callIdToOrdinal.set(item.action.callId, ordinal); ordinal++; for (const child of item.children) visit(child); }; for (const child of rootItem.children) visit(child); return { ordinalToCallId, callIdToOrdinal }; } var import_fs11, import_path10, traceDir, cliOutputDir, LoadedTrace; var init_traceUtils2 = __esm({ "packages/playwright-core/src/tools/trace/traceUtils.ts"() { "use strict"; import_fs11 = __toESM(require("fs")); import_path10 = __toESM(require("path")); init_traceModel(); init_traceLoader(); init_protocolFormatter(); init_fileUtils(); init_traceParser(); traceDir = import_path10.default.join(".playwright-cli", "trace"); cliOutputDir = ".playwright-cli"; LoadedTrace = class { constructor(model, loader, ordinals) { this.model = model; this.loader = loader; this.ordinalToCallId = ordinals.ordinalToCallId; this.callIdToOrdinal = ordinals.callIdToOrdinal; } resolveActionId(actionId) { const ordinal = parseInt(actionId, 10); if (!isNaN(ordinal)) { const callId = this.ordinalToCallId.get(ordinal); if (callId) return this.model.actions.find((a) => a.callId === callId); } return this.model.actions.find((a) => a.callId === actionId); } }; } }); // packages/playwright-core/src/tools/trace/traceOpen.ts async function traceOpen(traceFile) { await openTrace(traceFile); await traceInfo(); } async function traceInfo() { const trace = await loadTrace(); const model = trace.model; const info = { browser: model.browserName || "unknown", platform: model.platform || "unknown", playwrightVersion: model.playwrightVersion || "unknown", title: model.title || "", duration: msToString(model.endTime - model.startTime), durationMs: model.endTime - model.startTime, startTime: model.wallTime ? new Date(model.wallTime).toISOString() : "unknown", viewport: model.options.viewport ? `${model.options.viewport.width}x${model.options.viewport.height}` : "default", actions: model.actions.length, pages: model.pages.length, network: model.resources.length, errors: model.errorDescriptors.length, attachments: model.attachments.length, consoleMessages: model.events.filter((e) => e.type === "console").length }; console.log(""); console.log(` Browser: ${info.browser}`); console.log(` Platform: ${info.platform}`); console.log(` Playwright: ${info.playwrightVersion}`); if (info.title) console.log(` Title: ${info.title}`); console.log(` Duration: ${info.duration}`); console.log(` Start time: ${info.startTime}`); console.log(` Viewport: ${info.viewport}`); console.log(` Actions: ${info.actions}`); console.log(` Pages: ${info.pages}`); console.log(` Network: ${info.network} requests`); console.log(` Errors: ${info.errors}`); console.log(` Attachments: ${info.attachments}`); console.log(` Console: ${info.consoleMessages} messages`); console.log(""); } var init_traceOpen = __esm({ "packages/playwright-core/src/tools/trace/traceOpen.ts"() { "use strict"; init_formatUtils(); init_traceUtils2(); } }); // packages/playwright-core/src/tools/trace/traceActions.ts async function traceActions(options) { const trace = await loadTrace(); const actions = filterActions(trace.model.actions, options); const { rootItem } = buildActionTree(actions); console.log(` ${"#".padStart(4)} ${"Time".padEnd(9)} ${"Action".padEnd(55)} ${"Duration".padStart(8)}`); console.log(` ${"\u2500".repeat(4)} ${"\u2500".repeat(9)} ${"\u2500".repeat(55)} ${"\u2500".repeat(8)}`); const visit = (item, indent) => { const action = item.action; const ordinal = trace.callIdToOrdinal.get(action.callId) ?? "?"; const ts = formatTimestamp(action.startTime, trace.model.startTime); const duration = action.endTime ? msToString(action.endTime - action.startTime) : "running"; const title = actionTitle(action); const locator2 = actionLocator(action); const error = action.error ? " \u2717" : ""; const prefix = ` ${(ordinal + ".").padStart(4)} ${ts} ${indent}`; console.log(`${prefix}${title.padEnd(Math.max(1, 55 - indent.length))} ${duration.padStart(8)}${error}`); if (locator2) console.log(`${" ".repeat(prefix.length)}${locator2}`); for (const child of item.children) visit(child, indent + " "); }; for (const child of rootItem.children) visit(child, ""); } function filterActions(actions, options) { let result2 = actions.filter((a) => a.group !== "configuration"); if (options.grep) { const pattern = new RegExp(options.grep, "i"); result2 = result2.filter((a) => pattern.test(actionTitle(a)) || pattern.test(actionLocator(a) || "")); } if (options.errorsOnly) result2 = result2.filter((a) => !!a.error); return result2; } function actionLocator(action, sdkLanguage) { return action.params.selector ? asLocatorDescription(sdkLanguage || "javascript", action.params.selector) : void 0; } async function traceAction(actionId) { const trace = await loadTrace(); const action = trace.resolveActionId(actionId); if (!action) { console.error(`Action '${actionId}' not found. Use 'trace actions' to see available action IDs.`); process.exitCode = 1; return; } const title = actionTitle(action); console.log(` ${title} `); console.log(" Time"); console.log(` start: ${formatTimestamp(action.startTime, trace.model.startTime)}`); const duration = action.endTime ? msToString(action.endTime - action.startTime) : action.error ? "Timed Out" : "Running"; console.log(` duration: ${duration}`); const paramKeys = Object.keys(action.params).filter((name) => name !== "info"); if (paramKeys.length) { console.log("\n Parameters"); for (const key of paramKeys) { const value2 = formatParamValue(action.params[key]); console.log(` ${key}: ${value2}`); } } if (action.result) { console.log("\n Return value"); for (const [key, value2] of Object.entries(action.result)) console.log(` ${key}: ${formatParamValue(value2)}`); } if (action.error) { console.log("\n Error"); console.log(` ${action.error.message}`); } if (action.log.length) { console.log("\n Log"); for (const entry of action.log) { const time = entry.time !== -1 ? formatTimestamp(entry.time, trace.model.startTime) : ""; console.log(` ${time.padEnd(12)} ${entry.message}`); } } if (action.stack?.length) { console.log("\n Source"); for (const frame of action.stack.slice(0, 5)) { const file = frame.file.replace(/.*[/\\](.*)/, "$1"); console.log(` ${file}:${frame.line}:${frame.column}`); } } const snapshots = []; if (action.beforeSnapshot) snapshots.push("before"); if (action.inputSnapshot) snapshots.push("input"); if (action.afterSnapshot) snapshots.push("after"); if (snapshots.length) { console.log("\n Snapshots"); console.log(` available: ${snapshots.join(", ")}`); console.log(` usage: npx playwright trace snapshot ${actionId} --name <${snapshots.join("|")}>`); } console.log(""); } function formatParamValue(value2) { if (value2 === void 0 || value2 === null) return String(value2); if (typeof value2 === "string") return `"${value2}"`; if (typeof value2 !== "object") return String(value2); if (value2.guid) return ""; return JSON.stringify(value2).slice(0, 1e3); } var init_traceActions = __esm({ "packages/playwright-core/src/tools/trace/traceActions.ts"() { "use strict"; init_traceModel(); init_locatorGenerators(); init_formatUtils(); init_traceUtils2(); } }); // packages/playwright-core/src/tools/trace/traceRequests.ts async function traceRequests(options) { const trace = await loadTrace(); const model = trace.model; let indexed = model.resources.map((r, i) => ({ resource: r, ordinal: i + 1 })); if (options.grep) { const pattern = new RegExp(options.grep, "i"); indexed = indexed.filter(({ resource: r }) => pattern.test(r.request.url)); } if (options.method) indexed = indexed.filter(({ resource: r }) => r.request.method.toLowerCase() === options.method.toLowerCase()); if (options.status) { const code = parseInt(options.status, 10); indexed = indexed.filter(({ resource: r }) => r.response.status === code); } if (options.failed) indexed = indexed.filter(({ resource: r }) => r.response.status >= 400 || r.response.status === -1); if (!indexed.length) { console.log(" No network requests"); return; } console.log(` ${"#".padStart(4)} ${"Method".padEnd(8)} ${"Status".padEnd(8)} ${"Name".padEnd(45)} ${"Duration".padStart(10)} ${"Size".padStart(8)} ${"Route".padEnd(10)}`); console.log(` ${"\u2500".repeat(4)} ${"\u2500".repeat(8)} ${"\u2500".repeat(8)} ${"\u2500".repeat(45)} ${"\u2500".repeat(10)} ${"\u2500".repeat(8)} ${"\u2500".repeat(10)}`); for (const { resource: r, ordinal } of indexed) { let name; try { const url2 = new URL(r.request.url); name = url2.pathname.substring(url2.pathname.lastIndexOf("/") + 1); if (!name) name = url2.host; if (url2.search) name += url2.search; } catch { name = r.request.url; } if (name.length > 45) name = name.substring(0, 42) + "..."; const status = r.response.status > 0 ? String(r.response.status) : "ERR"; const size = r.response._transferSize > 0 ? r.response._transferSize : r.response.bodySize; const route2 = formatRouteStatus(r); console.log(` ${(ordinal + ".").padStart(4)} ${r.request.method.padEnd(8)} ${status.padEnd(8)} ${name.padEnd(45)} ${msToString(r.time).padStart(10)} ${bytesToString2(size).padStart(8)} ${route2.padEnd(10)}`); } } async function traceRequest(requestId) { const trace = await loadTrace(); const model = trace.model; const ordinal = parseInt(requestId, 10); const resource = !isNaN(ordinal) && ordinal >= 1 && ordinal <= model.resources.length ? model.resources[ordinal - 1] : void 0; if (!resource) { console.error(`Request '${requestId}' not found. Use 'trace requests' to see available request IDs.`); process.exitCode = 1; return; } const r = resource; const status = r.response.status > 0 ? `${r.response.status} ${r.response.statusText}` : "ERR"; const size = r.response._transferSize > 0 ? r.response._transferSize : r.response.bodySize; console.log(` ${r.request.method} ${r.request.url} `); console.log(" General"); console.log(` status: ${status}`); console.log(` duration: ${msToString(r.time)}`); console.log(` size: ${bytesToString2(size)}`); if (r.response.content.mimeType) console.log(` type: ${r.response.content.mimeType}`); const route2 = formatRouteStatus(r); if (route2) console.log(` route: ${route2}`); if (r.serverIPAddress) console.log(` server: ${r.serverIPAddress}${r._serverPort ? ":" + r._serverPort : ""}`); if (r.response._failureText) console.log(` error: ${r.response._failureText}`); if (r.request.headers.length) { console.log("\n Request headers"); for (const h of r.request.headers) console.log(` ${h.name}: ${h.value}`); } if (r.request.postData) { console.log("\n Request body"); const resource2 = r.request.postData._sha1 ?? r.request.postData._file; if (resource2) { console.log(` ${import_path11.default.relative(process.cwd(), import_path11.default.join(trace.model.traceUri, "resources", resource2))}`); } else { const text2 = r.request.postData.text.length > 2e3 ? r.request.postData.text.substring(0, 2e3) + "..." : r.request.postData.text; console.log(` ${text2}`); } } if (r.response.headers.length) { console.log("\n Response headers"); for (const h of r.response.headers) console.log(` ${h.name}: ${h.value}`); } if (r.response.bodySize > 0) { const resource2 = r.response.content._sha1 ?? r.response.content._file; if (resource2) { console.log("\n Response body"); console.log(` ${import_path11.default.relative(process.cwd(), import_path11.default.join(trace.model.traceUri, "resources", resource2))}`); } else if (r.response.content.text) { const text2 = r.response.content.text.length > 2e3 ? r.response.content.text.substring(0, 2e3) + "..." : r.response.content.text; console.log("\n Response body"); console.log(` ${text2}`); } } if (r._securityDetails) { console.log("\n Security"); if (r._securityDetails.protocol) console.log(` protocol: ${r._securityDetails.protocol}`); if (r._securityDetails.subjectName) console.log(` subject: ${r._securityDetails.subjectName}`); if (r._securityDetails.issuer) console.log(` issuer: ${r._securityDetails.issuer}`); } console.log(""); } function bytesToString2(bytes) { if (bytes < 0 || !isFinite(bytes)) return "-"; if (bytes === 0) return "0"; if (bytes < 1e3) return bytes.toFixed(0); const kb = bytes / 1024; if (kb < 1e3) return kb.toFixed(1) + "K"; const mb = kb / 1024; if (mb < 1e3) return mb.toFixed(1) + "M"; const gb = mb / 1024; return gb.toFixed(1) + "G"; } function formatRouteStatus(r) { if (r._wasAborted) return "aborted"; if (r._wasContinued) return "continued"; if (r._wasFulfilled) return "fulfilled"; if (r._apiRequest) return "api"; return ""; } var import_path11; var init_traceRequests = __esm({ "packages/playwright-core/src/tools/trace/traceRequests.ts"() { "use strict"; import_path11 = __toESM(require("path")); init_formatUtils(); init_traceUtils2(); } }); // packages/playwright-core/src/tools/trace/traceConsole.ts async function traceConsole(options) { const trace = await loadTrace(); const model = trace.model; const items = []; for (const event of model.events) { if (event.type === "console") { if (options.stdio) continue; const level = event.messageType; if (options.errorsOnly && level !== "error") continue; if (options.warnings && level !== "error" && level !== "warning") continue; const url2 = event.location.url; const filename = url2 ? url2.substring(url2.lastIndexOf("/") + 1) : ""; items.push({ type: "browser", level, text: event.text, location: `${filename}:${event.location.lineNumber}`, timestamp: event.time }); } if (event.type === "event" && event.method === "pageError") { if (options.stdio) continue; const error = event.params.error; items.push({ type: "browser", level: "error", text: error?.error?.message || String(error?.value || ""), timestamp: event.time }); } } for (const event of model.stdio) { if (options.browser) continue; if (options.errorsOnly && event.type !== "stderr") continue; if (options.warnings && event.type !== "stderr") continue; let text2 = ""; if (event.text) text2 = event.text.trim(); if (event.base64) text2 = Buffer.from(event.base64, "base64").toString("utf-8").trim(); if (!text2) continue; items.push({ type: event.type, level: event.type === "stderr" ? "error" : "info", text: text2, timestamp: event.timestamp }); } items.sort((a, b) => a.timestamp - b.timestamp); if (!items.length) { console.log(" No console entries"); return; } for (const item of items) { const ts = formatTimestamp(item.timestamp, model.startTime); const source11 = item.type === "browser" ? "[browser]" : `[${item.type}]`; const level = item.level.padEnd(8); const location2 = item.location ? ` ${item.location}` : ""; console.log(` ${ts} ${source11.padEnd(10)} ${level} ${item.text}${location2}`); } } var init_traceConsole = __esm({ "packages/playwright-core/src/tools/trace/traceConsole.ts"() { "use strict"; init_traceUtils2(); } }); // packages/playwright-core/src/tools/trace/traceErrors.ts async function traceErrors() { const trace = await loadTrace(); const model = trace.model; if (!model.errorDescriptors.length) { console.log(" No errors"); return; } for (const error of model.errorDescriptors) { if (error.action) { const title = actionTitle(error.action); console.log(` \u2717 ${title}`); } else { console.log(` \u2717 Error`); } if (error.stack?.length) { const frame = error.stack[0]; const file = frame.file.replace(/.*[/\\](.*)/, "$1"); console.log(` at ${file}:${frame.line}:${frame.column}`); } console.log(""); const indented = error.message.split("\n").map((l) => ` ${l}`).join("\n"); console.log(indented); } console.log(""); } var init_traceErrors = __esm({ "packages/playwright-core/src/tools/trace/traceErrors.ts"() { "use strict"; init_traceUtils2(); } }); // packages/isomorphic/disposable.ts async function disposeAll(disposables) { const copy = [...disposables]; disposables.length = 0; await Promise.all(copy.map((d) => d.dispose())); } var init_disposable = __esm({ "packages/isomorphic/disposable.ts"() { "use strict"; } }); // packages/playwright-core/src/server/userAgent.ts function getUserAgent() { if (cachedUserAgent) return cachedUserAgent; try { cachedUserAgent = determineUserAgent(); } catch (e) { cachedUserAgent = "Playwright/unknown"; } return cachedUserAgent; } function determineUserAgent() { let osIdentifier = "unknown"; let osVersion = "unknown"; if (process.platform === "win32") { const version3 = import_os4.default.release().split("."); osIdentifier = "windows"; osVersion = `${version3[0]}.${version3[1]}`; } else if (process.platform === "darwin") { const version3 = (0, import_child_process2.execSync)("sw_vers -productVersion", { stdio: ["ignore", "pipe", "ignore"] }).toString().trim().split("."); osIdentifier = "macOS"; osVersion = `${version3[0]}.${version3[1]}`; } else if (process.platform === "linux") { const distroInfo = getLinuxDistributionInfoSync(); if (distroInfo) { osIdentifier = distroInfo.id || "linux"; osVersion = distroInfo.version || "unknown"; } else { osIdentifier = "linux"; } } const additionalTokens = []; if (process.env.CI) additionalTokens.push("CI/1"); const serializedTokens = additionalTokens.length ? " " + additionalTokens.join(" ") : ""; const { embedderName, embedderVersion } = getEmbedderName(); return `Playwright/${getPlaywrightVersion()} (${import_os4.default.arch()}; ${osIdentifier} ${osVersion}) ${embedderName}/${embedderVersion}${serializedTokens}`; } function getEmbedderName() { let embedderName = "unknown"; let embedderVersion = "unknown"; if (!process.env.PW_LANG_NAME) { embedderName = "node"; embedderVersion = process.version.substring(1).split(".").slice(0, 2).join("."); } else if (["node", "python", "java", "csharp"].includes(process.env.PW_LANG_NAME)) { embedderName = process.env.PW_LANG_NAME; embedderVersion = process.env.PW_LANG_NAME_VERSION ?? "unknown"; } return { embedderName, embedderVersion }; } function getPlaywrightVersion(majorMinorOnly = false) { const version3 = process.env.PW_VERSION_OVERRIDE || packageJSON.version; return majorMinorOnly ? version3.split(".").slice(0, 2).join(".") : version3; } var import_child_process2, import_os4, cachedUserAgent; var init_userAgent = __esm({ "packages/playwright-core/src/server/userAgent.ts"() { "use strict"; import_child_process2 = require("child_process"); import_os4 = __toESM(require("os")); init_linuxUtils(); init_package(); } }); // packages/playwright-core/src/generated/clockSource.ts var source; var init_clockSource = __esm({ "packages/playwright-core/src/generated/clockSource.ts"() { "use strict"; source = '\nvar __commonJS = obj => {\n let required = false;\n let result;\n return function __require() {\n if (!required) {\n required = true;\n let fn;\n for (const name in obj) { fn = obj[name]; break; }\n const module = { exports: {} };\n fn(module.exports, module);\n result = module.exports;\n }\n return result;\n }\n};\nvar __export = (target, all) => {for (var name in all) target[name] = all[name];};\nvar __toESM = mod => ({ ...mod, \'default\': mod });\nvar __toCommonJS = mod => ({ ...mod, __esModule: true });\n\n\n// packages/injected/src/clock.ts\nvar clock_exports = {};\n__export(clock_exports, {\n ClockController: () => ClockController,\n createClock: () => createClock,\n inject: () => inject,\n install: () => install\n});\nmodule.exports = __toCommonJS(clock_exports);\nvar ClockController = class {\n constructor(embedder) {\n this._duringTick = false;\n this._uniqueTimerId = idCounterStart;\n this.disposables = [];\n this._log = [];\n this._timers = /* @__PURE__ */ new Map();\n this._now = { time: asWallTime(0), isFixedTime: false, ticks: 0, origin: asWallTime(-1) };\n this._embedder = embedder;\n }\n uninstall() {\n this.disposables.forEach((dispose) => dispose());\n this.disposables.length = 0;\n }\n now() {\n this._replayLogOnce();\n this._syncRealTime();\n return this._now.time;\n }\n install(time) {\n this._replayLogOnce();\n this._innerInstall(asWallTime(time));\n }\n setSystemTime(time) {\n this._replayLogOnce();\n this._innerSetTime(asWallTime(time));\n }\n setFixedTime(time) {\n this._replayLogOnce();\n this._innerSetFixedTime(asWallTime(time));\n }\n performanceNow() {\n this._replayLogOnce();\n this._syncRealTime();\n return this._now.ticks;\n }\n _syncRealTime() {\n if (!this._realTime)\n return;\n const now = this._embedder.performanceNow();\n const sinceLastSync = now - this._realTime.lastSyncTicks;\n if (sinceLastSync > 0) {\n this._advanceNow(shiftTicks(this._now.ticks, sinceLastSync));\n this._realTime.lastSyncTicks = now;\n }\n }\n _innerSetTime(time) {\n this._now.time = time;\n this._now.isFixedTime = false;\n if (this._now.origin < 0)\n this._now.origin = this._now.time;\n }\n _innerInstall(time) {\n if (this._now.origin < 0)\n this._now.ticks = 0;\n this._innerSetTime(time);\n }\n _innerSetFixedTime(time) {\n this._innerSetTime(time);\n this._now.isFixedTime = true;\n }\n _advanceNow(to) {\n if (this._now.ticks > to) {\n return;\n }\n if (!this._now.isFixedTime)\n this._now.time = asWallTime(this._now.time + to - this._now.ticks);\n this._now.ticks = to;\n }\n async log(type, time, param) {\n this._log.push({ type, time, param });\n }\n async runFor(ticks) {\n this._replayLogOnce();\n if (ticks < 0)\n throw new TypeError("Negative ticks are not supported");\n await this._runWithDisabledRealTimeSync(async () => {\n await this._runTo(shiftTicks(this._now.ticks, ticks));\n });\n }\n async _runTo(to) {\n to = Math.ceil(to);\n if (this._now.ticks > to)\n return;\n let firstException;\n while (true) {\n const result = await this._callFirstTimer(to);\n if (!result.timerFound)\n break;\n firstException = firstException || result.error;\n }\n this._advanceNow(to);\n if (firstException)\n throw firstException;\n }\n async pauseAt(time) {\n this._replayLogOnce();\n await this._innerPause();\n const toConsume = time - this._now.time;\n await this._innerFastForwardTo(shiftTicks(this._now.ticks, toConsume));\n return toConsume;\n }\n async _innerPause() {\n var _a;\n this._realTime = void 0;\n await ((_a = this._currentRealTimeTimer) == null ? void 0 : _a.dispose());\n this._currentRealTimeTimer = void 0;\n }\n resume() {\n this._replayLogOnce();\n this._innerResume();\n }\n _innerResume() {\n const now = this._embedder.performanceNow();\n this._realTime = { startTicks: now, lastSyncTicks: now };\n this._updateRealTimeTimer();\n }\n _updateRealTimeTimer() {\n var _a;\n if ((_a = this._currentRealTimeTimer) == null ? void 0 : _a.promise) {\n return;\n }\n const firstTimer = this._firstTimer();\n const nextTick = Math.min(firstTimer ? firstTimer.callAt : this._now.ticks + maxTimeout, this._now.ticks + 100);\n const callAt = this._currentRealTimeTimer ? Math.min(this._currentRealTimeTimer.callAt, nextTick) : nextTick;\n if (this._currentRealTimeTimer) {\n this._currentRealTimeTimer.cancel();\n this._currentRealTimeTimer = void 0;\n }\n const realTimeTimer = {\n callAt,\n promise: void 0,\n cancel: this._embedder.setTimeout(() => {\n this._syncRealTime();\n realTimeTimer.promise = this._runTo(this._now.ticks).catch((e) => console.error(e));\n void realTimeTimer.promise.then(() => {\n this._currentRealTimeTimer = void 0;\n if (this._realTime)\n this._updateRealTimeTimer();\n });\n }, callAt - this._now.ticks),\n dispose: async () => {\n realTimeTimer.cancel();\n await realTimeTimer.promise;\n }\n };\n this._currentRealTimeTimer = realTimeTimer;\n }\n async _runWithDisabledRealTimeSync(fn) {\n if (!this._realTime) {\n await fn();\n return;\n }\n await this._innerPause();\n try {\n await fn();\n } finally {\n this._innerResume();\n }\n }\n async fastForward(ticks) {\n this._replayLogOnce();\n await this._runWithDisabledRealTimeSync(async () => {\n await this._innerFastForwardTo(shiftTicks(this._now.ticks, ticks | 0));\n });\n }\n async _innerFastForwardTo(to) {\n if (to < this._now.ticks)\n throw new Error("Cannot fast-forward to the past");\n for (const timer of this._timers.values()) {\n if (to > timer.callAt)\n timer.callAt = to;\n }\n await this._runTo(to);\n }\n addTimer(options) {\n this._replayLogOnce();\n if (options.type === "AnimationFrame" /* AnimationFrame */ && !options.func)\n throw new Error("Callback must be provided to requestAnimationFrame calls");\n if (options.type === "IdleCallback" /* IdleCallback */ && !options.func)\n throw new Error("Callback must be provided to requestIdleCallback calls");\n if (["Timeout" /* Timeout */, "Interval" /* Interval */].includes(options.type) && !options.func && options.delay === void 0)\n throw new Error("Callback must be provided to timer calls");\n let delay = options.delay ? +options.delay : 0;\n if (!Number.isFinite(delay))\n delay = 0;\n delay = delay > maxTimeout ? 1 : delay;\n delay = Math.max(0, delay);\n const timer = {\n type: options.type,\n func: options.func,\n args: options.args || [],\n delay,\n callAt: shiftTicks(this._now.ticks, delay || (this._duringTick ? 1 : 0)),\n createdAt: this._now.ticks,\n id: this._uniqueTimerId++,\n error: new Error()\n };\n this._timers.set(timer.id, timer);\n if (this._realTime)\n this._updateRealTimeTimer();\n return timer.id;\n }\n countTimers() {\n return this._timers.size;\n }\n _firstTimer(beforeTick) {\n let firstTimer = null;\n for (const timer of this._timers.values()) {\n const isInRange = beforeTick === void 0 || timer.callAt <= beforeTick;\n if (isInRange && (!firstTimer || compareTimers(firstTimer, timer) === 1))\n firstTimer = timer;\n }\n return firstTimer;\n }\n _takeFirstTimer(beforeTick) {\n const timer = this._firstTimer(beforeTick);\n if (!timer)\n return null;\n this._advanceNow(timer.callAt);\n if (timer.type === "Interval" /* Interval */)\n timer.callAt = shiftTicks(timer.callAt, timer.delay);\n else\n this._timers.delete(timer.id);\n return timer;\n }\n async _callFirstTimer(beforeTick) {\n const timer = this._takeFirstTimer(beforeTick);\n if (!timer)\n return { timerFound: false };\n this._duringTick = true;\n try {\n if (typeof timer.func !== "function") {\n let error2;\n try {\n (() => {\n globalThis.eval(timer.func);\n })();\n } catch (e) {\n error2 = e;\n }\n await new Promise((f) => this._embedder.setTimeout(f));\n return { timerFound: true, error: error2 };\n }\n let args = timer.args;\n if (timer.type === "AnimationFrame" /* AnimationFrame */)\n args = [this._now.ticks];\n else if (timer.type === "IdleCallback" /* IdleCallback */)\n args = [{ didTimeout: false, timeRemaining: () => 0 }];\n let error;\n try {\n timer.func.apply(null, args);\n } catch (e) {\n error = e;\n }\n await new Promise((f) => this._embedder.setTimeout(f));\n return { timerFound: true, error };\n } finally {\n this._duringTick = false;\n }\n }\n getTimeToNextFrame() {\n this._replayLogOnce();\n return 16 - this._now.ticks % 16;\n }\n clearTimer(timerId, type) {\n this._replayLogOnce();\n if (!timerId) {\n return;\n }\n const id = Number(timerId);\n if (Number.isNaN(id) || id < idCounterStart) {\n const handlerName = getClearHandler(type);\n new Error(`Clock: ${handlerName} was invoked to clear a native timer instead of one created by the clock library.`);\n }\n const timer = this._timers.get(id);\n if (timer) {\n if (timer.type === type || timer.type === "Timeout" && type === "Interval" || timer.type === "Interval" && type === "Timeout") {\n this._timers.delete(id);\n } else {\n const clear = getClearHandler(type);\n const schedule = getScheduleHandler(timer.type);\n throw new Error(\n `Cannot clear timer: timer created with ${schedule}() but cleared with ${clear}()`\n );\n }\n }\n }\n _replayLogOnce() {\n if (!this._log.length)\n return;\n let lastLogTime = -1;\n let isPaused = false;\n for (const { type, time, param } of this._log) {\n if (!isPaused && lastLogTime !== -1)\n this._advanceNow(shiftTicks(this._now.ticks, time - lastLogTime));\n lastLogTime = time;\n if (type === "install") {\n this._innerInstall(asWallTime(param));\n } else if (type === "fastForward" || type === "runFor") {\n this._advanceNow(shiftTicks(this._now.ticks, param));\n } else if (type === "pauseAt") {\n isPaused = true;\n this._innerSetTime(asWallTime(param));\n } else if (type === "resume") {\n isPaused = false;\n } else if (type === "setFixedTime") {\n this._innerSetFixedTime(asWallTime(param));\n } else if (type === "setSystemTime") {\n this._innerSetTime(asWallTime(param));\n }\n }\n if (!isPaused) {\n if (lastLogTime > 0)\n this._advanceNow(shiftTicks(this._now.ticks, this._embedder.dateNow() - lastLogTime));\n this._innerResume();\n } else {\n this._realTime = void 0;\n }\n this._log.length = 0;\n }\n};\nfunction mirrorDateProperties(target, source) {\n for (const prop in source) {\n if (source.hasOwnProperty(prop))\n target[prop] = source[prop];\n }\n target.toString = () => source.toString();\n target.prototype = source.prototype;\n target.parse = source.parse;\n target.UTC = source.UTC;\n target.prototype.toUTCString = source.prototype.toUTCString;\n target.isFake = true;\n return target;\n}\nfunction createDate(clock, NativeDate) {\n function ClockDate(year, month, date, hour, minute, second, ms) {\n if (!(this instanceof ClockDate))\n return new NativeDate(clock.now()).toString();\n switch (arguments.length) {\n case 0:\n return new NativeDate(clock.now());\n case 1:\n return new NativeDate(year);\n case 2:\n return new NativeDate(year, month);\n case 3:\n return new NativeDate(year, month, date);\n case 4:\n return new NativeDate(year, month, date, hour);\n case 5:\n return new NativeDate(year, month, date, hour, minute);\n case 6:\n return new NativeDate(\n year,\n month,\n date,\n hour,\n minute,\n second\n );\n default:\n return new NativeDate(\n year,\n month,\n date,\n hour,\n minute,\n second,\n ms\n );\n }\n }\n ClockDate.now = () => clock.now();\n return mirrorDateProperties(ClockDate, NativeDate);\n}\nfunction createIntl(clock, NativeIntl) {\n const ClockIntl = {};\n for (const key of Object.getOwnPropertyNames(NativeIntl))\n ClockIntl[key] = NativeIntl[key];\n ClockIntl.DateTimeFormat = function(...args) {\n const realFormatter = new NativeIntl.DateTimeFormat(...args);\n const formatter = {\n formatRange: realFormatter.formatRange.bind(realFormatter),\n formatRangeToParts: realFormatter.formatRangeToParts.bind(realFormatter),\n resolvedOptions: realFormatter.resolvedOptions.bind(realFormatter),\n format: (date) => realFormatter.format(date || clock.now()),\n formatToParts: (date) => realFormatter.formatToParts(date || clock.now())\n };\n return formatter;\n };\n ClockIntl.DateTimeFormat.prototype = Object.create(\n NativeIntl.DateTimeFormat.prototype\n );\n ClockIntl.DateTimeFormat.supportedLocalesOf = NativeIntl.DateTimeFormat.supportedLocalesOf;\n return ClockIntl;\n}\nfunction compareTimers(a, b) {\n if (a.callAt < b.callAt)\n return -1;\n if (a.callAt > b.callAt)\n return 1;\n if (a.type === "Immediate" /* Immediate */ && b.type !== "Immediate" /* Immediate */)\n return -1;\n if (a.type !== "Immediate" /* Immediate */ && b.type === "Immediate" /* Immediate */)\n return 1;\n if (a.createdAt < b.createdAt)\n return -1;\n if (a.createdAt > b.createdAt)\n return 1;\n if (a.id < b.id)\n return -1;\n if (a.id > b.id)\n return 1;\n}\nvar maxTimeout = Math.pow(2, 31) - 1;\nvar idCounterStart = 1e12;\nfunction platformOriginals(globalObject) {\n const raw = {\n setTimeout: globalObject.setTimeout,\n clearTimeout: globalObject.clearTimeout,\n setInterval: globalObject.setInterval,\n clearInterval: globalObject.clearInterval,\n requestAnimationFrame: globalObject.requestAnimationFrame ? globalObject.requestAnimationFrame : void 0,\n cancelAnimationFrame: globalObject.cancelAnimationFrame ? globalObject.cancelAnimationFrame : void 0,\n requestIdleCallback: globalObject.requestIdleCallback ? globalObject.requestIdleCallback : void 0,\n cancelIdleCallback: globalObject.cancelIdleCallback ? globalObject.cancelIdleCallback : void 0,\n Date: globalObject.Date,\n performance: globalObject.performance,\n Intl: globalObject.Intl,\n AbortSignal: globalObject.AbortSignal\n };\n const bound = { ...raw };\n for (const key of Object.keys(bound)) {\n if (key !== "Date" && key !== "AbortSignal" && typeof bound[key] === "function")\n bound[key] = bound[key].bind(globalObject);\n }\n return { raw, bound };\n}\nfunction getScheduleHandler(type) {\n if (type === "IdleCallback" || type === "AnimationFrame")\n return `request${type}`;\n return `set${type}`;\n}\nfunction createApi(clock, originals, browserName) {\n return {\n setTimeout: (func, timeout, ...args) => {\n const delay = timeout ? +timeout : timeout;\n return clock.addTimer({\n type: "Timeout" /* Timeout */,\n func,\n args,\n delay\n });\n },\n clearTimeout: (timerId) => {\n if (timerId)\n clock.clearTimer(timerId, "Timeout" /* Timeout */);\n },\n setInterval: (func, timeout, ...args) => {\n const delay = timeout ? +timeout : timeout;\n return clock.addTimer({\n type: "Interval" /* Interval */,\n func,\n args,\n delay\n });\n },\n clearInterval: (timerId) => {\n if (timerId)\n return clock.clearTimer(timerId, "Interval" /* Interval */);\n },\n requestAnimationFrame: (callback) => {\n return clock.addTimer({\n type: "AnimationFrame" /* AnimationFrame */,\n func: callback,\n delay: clock.getTimeToNextFrame()\n });\n },\n cancelAnimationFrame: (timerId) => {\n if (timerId)\n return clock.clearTimer(timerId, "AnimationFrame" /* AnimationFrame */);\n },\n requestIdleCallback: (callback, options) => {\n let timeToNextIdlePeriod = 0;\n if (clock.countTimers() > 0)\n timeToNextIdlePeriod = 50;\n return clock.addTimer({\n type: "IdleCallback" /* IdleCallback */,\n func: callback,\n delay: (options == null ? void 0 : options.timeout) ? Math.min(options == null ? void 0 : options.timeout, timeToNextIdlePeriod) : timeToNextIdlePeriod\n });\n },\n cancelIdleCallback: (timerId) => {\n if (timerId)\n return clock.clearTimer(timerId, "IdleCallback" /* IdleCallback */);\n },\n Intl: originals.Intl ? createIntl(clock, originals.Intl) : void 0,\n Date: createDate(clock, originals.Date),\n performance: originals.performance ? fakePerformance(clock, originals.performance) : void 0,\n AbortSignal: originals.AbortSignal ? fakeAbortSignal(clock, originals.AbortSignal, browserName) : void 0\n };\n}\nfunction getClearHandler(type) {\n if (type === "IdleCallback" || type === "AnimationFrame")\n return `cancel${type}`;\n return `clear${type}`;\n}\nvar FakePerformanceEntry = class {\n constructor(name, entryType, startTime, duration) {\n this.name = name;\n this.entryType = entryType;\n this.startTime = startTime;\n this.duration = duration;\n }\n toJSON() {\n return JSON.stringify({ ...this });\n }\n};\nfunction fakePerformance(clock, performance) {\n const result = {\n now: () => clock.performanceNow()\n };\n result.__defineGetter__("timeOrigin", () => clock._now.origin || 0);\n for (const key of Object.keys(performance.__proto__)) {\n if (key === "now" || key === "timeOrigin")\n continue;\n if (key === "getEntries" || key === "getEntriesByName" || key === "getEntriesByType")\n result[key] = () => [];\n else if (key === "mark")\n result[key] = (name) => new FakePerformanceEntry(name, "mark", 0, 0);\n else if (key === "measure")\n result[key] = (name) => new FakePerformanceEntry(name, "measure", 0, 50);\n else\n result[key] = () => {\n };\n }\n return result;\n}\nfunction fakeAbortSignal(clock, abortSignal, browserName) {\n Object.defineProperty(abortSignal, "timeout", {\n value(ms) {\n const controller = new AbortController();\n clock.addTimer({\n delay: ms,\n type: "Timeout" /* Timeout */,\n func: () => controller.abort(\n new DOMException(\n browserName === "chromium" ? "signal timed out" : "The operation timed out.",\n "TimeoutError"\n )\n )\n });\n return controller.signal;\n }\n });\n return abortSignal;\n}\nfunction createClock(globalObject, config = {}) {\n const originals = platformOriginals(globalObject);\n const embedder = {\n dateNow: () => originals.raw.Date.now(),\n performanceNow: () => Math.ceil(originals.raw.performance.now()),\n setTimeout: (task, timeout) => {\n const timerId = originals.bound.setTimeout(task, timeout);\n return () => originals.bound.clearTimeout(timerId);\n },\n setInterval: (task, delay) => {\n const intervalId = originals.bound.setInterval(task, delay);\n return () => originals.bound.clearInterval(intervalId);\n }\n };\n const clock = new ClockController(embedder);\n const api = createApi(clock, originals.bound, config.browserName);\n return { clock, api, originals: originals.raw };\n}\nfunction install(globalObject, config = {}) {\n var _a, _b;\n if ((_a = globalObject.Date) == null ? void 0 : _a.isFake) {\n throw new TypeError(`Can\'t install fake timers twice on the same global object.`);\n }\n const { clock, api, originals } = createClock(globalObject, config);\n const toFake = ((_b = config.toFake) == null ? void 0 : _b.length) ? config.toFake : Object.keys(originals);\n for (const method of toFake) {\n if (method === "Date") {\n globalObject.Date = mirrorDateProperties(api.Date, globalObject.Date);\n } else if (method === "Intl") {\n globalObject.Intl = api[method];\n } else if (method === "AbortSignal") {\n globalObject.AbortSignal = api[method];\n } else if (method === "performance") {\n globalObject.performance = api[method];\n const kEventTimeStamp = Symbol("playwrightEventTimeStamp");\n Object.defineProperty(Event.prototype, "timeStamp", {\n get() {\n var _a2;\n if (!this[kEventTimeStamp])\n this[kEventTimeStamp] = (_a2 = api.performance) == null ? void 0 : _a2.now();\n return this[kEventTimeStamp];\n }\n });\n } else {\n globalObject[method] = (...args) => {\n return api[method].apply(api, args);\n };\n }\n clock.disposables.push(() => {\n globalObject[method] = originals[method];\n });\n }\n return { clock, api, originals };\n}\nfunction inject(globalObject, browserName) {\n const builtins = platformOriginals(globalObject).bound;\n const { clock: controller } = install(globalObject, { browserName });\n controller.resume();\n return {\n controller,\n builtins\n };\n}\nfunction asWallTime(n) {\n return n;\n}\nfunction shiftTicks(ticks, ms) {\n return ticks + ms;\n}\n'; } }); // packages/playwright-core/src/protocol/serializers.ts function parseSerializedValue(value2, handles) { return innerParseSerializedValue(value2, handles, /* @__PURE__ */ new Map(), []); } function innerParseSerializedValue(value2, handles, refs, accessChain) { if (value2.ref !== void 0) return refs.get(value2.ref); if (value2.n !== void 0) return value2.n; if (value2.s !== void 0) return value2.s; if (value2.b !== void 0) return value2.b; if (value2.v !== void 0) { if (value2.v === "undefined") return void 0; if (value2.v === "null") return null; if (value2.v === "NaN") return NaN; if (value2.v === "Infinity") return Infinity; if (value2.v === "-Infinity") return -Infinity; if (value2.v === "-0") return -0; } if (value2.d !== void 0) return new Date(value2.d); if (value2.u !== void 0) return new URL(value2.u); if (value2.bi !== void 0) return BigInt(value2.bi); if (value2.e !== void 0) { const error = new Error(value2.e.m); error.name = value2.e.n; error.stack = value2.e.s; return error; } if (value2.r !== void 0) return new RegExp(value2.r.p, value2.r.f); if (value2.ta !== void 0) { const ctor = typedArrayKindToConstructor[value2.ta.k]; return new ctor(value2.ta.b.buffer, value2.ta.b.byteOffset, value2.ta.b.length / ctor.BYTES_PER_ELEMENT); } if (value2.a !== void 0) { const result2 = []; refs.set(value2.id, result2); for (let i = 0; i < value2.a.length; i++) result2.push(innerParseSerializedValue(value2.a[i], handles, refs, [...accessChain, i])); return result2; } if (value2.o !== void 0) { const result2 = {}; refs.set(value2.id, result2); for (const { k, v } of value2.o) result2[k] = innerParseSerializedValue(v, handles, refs, [...accessChain, k]); return result2; } if (value2.h !== void 0) { if (handles === void 0) throw new Error("Unexpected handle"); return handles[value2.h]; } throw new Error(`Attempting to deserialize unexpected value${accessChainToDisplayString(accessChain)}: ${value2}`); } function serializeValue(value2, handleSerializer) { return innerSerializeValue(value2, handleSerializer, { lastId: 0, visited: /* @__PURE__ */ new Map() }, []); } function innerSerializeValue(value2, handleSerializer, visitorInfo, accessChain) { const handle = handleSerializer(value2); if ("fallThrough" in handle) value2 = handle.fallThrough; else return handle; if (typeof value2 === "symbol") return { v: "undefined" }; if (Object.is(value2, void 0)) return { v: "undefined" }; if (Object.is(value2, null)) return { v: "null" }; if (Object.is(value2, NaN)) return { v: "NaN" }; if (Object.is(value2, Infinity)) return { v: "Infinity" }; if (Object.is(value2, -Infinity)) return { v: "-Infinity" }; if (Object.is(value2, -0)) return { v: "-0" }; if (typeof value2 === "boolean") return { b: value2 }; if (typeof value2 === "number") return { n: value2 }; if (typeof value2 === "string") return { s: value2 }; if (typeof value2 === "bigint") return { bi: value2.toString() }; if (isError2(value2)) return { e: { n: value2.name, m: value2.message, s: value2.stack || "" } }; if (isDate(value2)) return { d: value2.toJSON() }; if (isURL(value2)) return { u: value2.toJSON() }; if (isRegExp4(value2)) return { r: { p: value2.source, f: value2.flags } }; const typedArrayKind = constructorToTypedArrayKind.get(value2.constructor); if (typedArrayKind) return { ta: { b: Buffer.from(value2.buffer, value2.byteOffset, value2.byteLength), k: typedArrayKind } }; const id = visitorInfo.visited.get(value2); if (id) return { ref: id }; if (Array.isArray(value2)) { const a = []; const id2 = ++visitorInfo.lastId; visitorInfo.visited.set(value2, id2); for (let i = 0; i < value2.length; ++i) a.push(innerSerializeValue(value2[i], handleSerializer, visitorInfo, [...accessChain, i])); return { a, id: id2 }; } if (typeof value2 === "object") { const o = []; const id2 = ++visitorInfo.lastId; visitorInfo.visited.set(value2, id2); for (const name of Object.keys(value2)) o.push({ k: name, v: innerSerializeValue(value2[name], handleSerializer, visitorInfo, [...accessChain, name]) }); return { o, id: id2 }; } throw new Error(`Attempting to serialize unexpected value${accessChainToDisplayString(accessChain)}: ${value2}`); } function accessChainToDisplayString(accessChain) { const chainString = accessChain.map((accessor, i) => { if (typeof accessor === "string") return i ? `.${accessor}` : accessor; return `[${accessor}]`; }).join(""); return chainString.length > 0 ? ` at position "${chainString}"` : ""; } function isRegExp4(obj) { return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]"; } function isDate(obj) { return obj instanceof Date || Object.prototype.toString.call(obj) === "[object Date]"; } function isURL(obj) { return obj instanceof URL || Object.prototype.toString.call(obj) === "[object URL]"; } function isError2(obj) { const proto = obj ? Object.getPrototypeOf(obj) : null; return obj instanceof Error || proto?.name === "Error" || proto && isError2(proto); } var typedArrayKindToConstructor, constructorToTypedArrayKind; var init_serializers = __esm({ "packages/playwright-core/src/protocol/serializers.ts"() { "use strict"; typedArrayKindToConstructor = { i8: Int8Array, ui8: Uint8Array, ui8c: Uint8ClampedArray, i16: Int16Array, ui16: Uint16Array, i32: Int32Array, ui32: Uint32Array, f32: Float32Array, f64: Float64Array, bi64: BigInt64Array, bui64: BigUint64Array }; constructorToTypedArrayKind = new Map(Object.entries(typedArrayKindToConstructor).map(([k, v]) => [v, k])); } }); // packages/playwright-core/src/server/errors.ts function isTargetClosedError(error) { return error instanceof TargetClosedError || error.name === "TargetClosedError"; } function serializeError(e) { if (isError(e)) return { error: { message: e.message, stack: e.stack, name: e.name } }; return { value: serializeValue(e, (value2) => ({ fallThrough: value2 })) }; } function parseError(error) { if (!error.error) { if (error.value === void 0) throw new Error("Serialized error must have either an error or a value"); return parseSerializedValue(error.value, void 0); } const e = new Error(error.error.message); e.stack = error.error.stack || ""; e.name = error.error.name; return e; } var CustomError, TimeoutError, TargetClosedError; var init_errors = __esm({ "packages/playwright-core/src/server/errors.ts"() { "use strict"; init_rtti(); init_serializers(); CustomError = class extends Error { constructor(message) { super(message); this.name = this.constructor.name; } }; TimeoutError = class extends CustomError { }; TargetClosedError = class extends CustomError { constructor(cause, logs) { super((cause || "Target page, context or browser has been closed") + (logs || "")); } }; } }); // packages/playwright-core/src/server/progress.ts function isAbortError(error) { return error instanceof TimeoutError || !!error[kAbortErrorSymbol]; } async function raceUncancellableOperationWithCleanup(progress2, run, cleanup) { let aborted = false; try { return await progress2.race(run().then(async (t) => { if (aborted) await cleanup(t); return t; })); } catch (error) { aborted = true; throw error; } } var ProgressController, kAbortErrorSymbol, nullProgress; var init_progress = __esm({ "packages/playwright-core/src/server/progress.ts"() { "use strict"; init_manualPromise(); init_assert(); init_time(); init_debugLogger(); init_errors(); ProgressController = class _ProgressController { constructor(metadata, onCallLog) { this._forceAbortPromise = new ManualPromise(); this._donePromise = new ManualPromise(); this._state = "before"; this.metadata = metadata || { id: "", startTime: 0, endTime: 0, type: "Internal", method: "", params: {}, log: [], internal: true }; this._onCallLog = onCallLog; this._forceAbortPromise.catch((e) => null); this._controller = new AbortController(); } static createForSdkObject(sdkObject, callMetadata) { const logName = sdkObject.logName || "api"; return new _ProgressController(callMetadata, (message) => { if (logName === "api" && sdkObject.attribution.playwright?.options.isInternalPlaywright) return; debugLogger.log(logName, message); sdkObject.instrumentation.onCallLog(sdkObject, callMetadata, logName, message); }); } async abort(error) { if (this._state === "running") { error[kAbortErrorSymbol] = true; this._state = { error }; this._forceAbortPromise.reject(error); this._controller.abort(error); } await this._donePromise; } async run(task, timeout) { const deadline = timeout ? monotonicTime() + timeout : 0; assert(this._state === "before"); this._state = "running"; let timer; let outerProgress; let allowConcurrent = false; const progress2 = { timeout: timeout ?? 0, deadline, disableTimeout: () => { clearTimeout(timer); }, log: (message) => { if (this._state === "running") this.metadata.log.push(message); this._onCallLog?.(message); }, metadata: this.metadata, setAllowConcurrentOrNestedRaces: (allow) => { allowConcurrent = allow; }, race: (promise) => { if (process.env.PW_DETECT_NESTED_PROGRESS) { const innerProgress = new Error().stack; if (outerProgress && !allowConcurrent && outerProgress !== innerProgress) { console.error("Cannot call race() inside another race()"); console.error("<<<<>>>>:", outerProgress); console.error("<<<<>>>>:", innerProgress); } outerProgress = innerProgress; } const promises = Array.isArray(promise) ? promise : [promise]; if (!promises.length) return Promise.resolve(); return Promise.race([...promises, this._forceAbortPromise]).finally(() => outerProgress = void 0); }, wait: async (timeout2) => { let timer2; const promise = new Promise((f) => timer2 = setTimeout(f, timeout2)); return progress2.race(promise).finally(() => clearTimeout(timer2)); }, signal: this._controller.signal }; if (deadline) { const timeoutError = new TimeoutError(`Timeout ${timeout}ms exceeded.`); timer = setTimeout(() => { if (this.metadata.pauseStartTime && !this.metadata.pauseEndTime) return; if (this._state === "running") { this._state = { error: timeoutError }; this._forceAbortPromise.reject(timeoutError); this._controller.abort(timeoutError); } }, deadline - monotonicTime()); } try { const result2 = await task(progress2); this._state = "finished"; return result2; } catch (error) { this._state = { error }; throw error; } finally { clearTimeout(timer); this._donePromise.resolve(); } } }; kAbortErrorSymbol = Symbol("kAbortError"); nullProgress = { timeout: 0, deadline: 0, disableTimeout() { }, log() { }, race(promise) { const promises = Array.isArray(promise) ? promise : [promise]; return Promise.race(promises); }, wait: async (timeout) => await new Promise((f) => setTimeout(f, timeout)), signal: new AbortController().signal, metadata: { id: "", startTime: 0, endTime: 0, type: "", method: "", params: {}, log: [], internal: true }, setAllowConcurrentOrNestedRaces() { } }; } }); // packages/playwright-core/src/server/clock.ts function parseTicks(value2) { if (typeof value2 === "number") return value2; if (!value2) return 0; const str = value2; const strings = str.split(":"); const l = strings.length; let i = l; let ms = 0; let parsed; if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) { throw new Error( `Clock only understands numbers, 'mm:ss' and 'hh:mm:ss'` ); } while (i--) { parsed = parseInt(strings[i], 10); if (parsed >= 60) throw new Error(`Invalid time ${str}`); ms += parsed * Math.pow(60, l - i - 1); } return ms * 1e3; } function parseTime(epoch) { if (!epoch) return 0; if (typeof epoch === "number") return epoch; const parsed = new Date(epoch); if (!isFinite(parsed.getTime())) throw new Error(`Invalid date: ${epoch}`); return parsed.getTime(); } var Clock; var init_clock = __esm({ "packages/playwright-core/src/server/clock.ts"() { "use strict"; init_clockSource(); init_progress(); Clock = class { constructor(browserContext) { this._initScripts = []; this._browserContext = browserContext; } async uninstall(progress2) { await progress2.race(Promise.all(this._initScripts.map((script) => script.dispose()))); this._initScripts = []; } async fastForward(ticks) { await this._installIfNeeded(); const ticksMillis = parseTicks(ticks); this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('fastForward', ${Date.now()}, ${ticksMillis})`)); await this._evaluateInFrames(`globalThis.__pwClock.controller.fastForward(${ticksMillis})`); } async install(time) { await this._installIfNeeded(); const timeMillis = time !== void 0 ? parseTime(time) : Date.now(); this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('install', ${Date.now()}, ${timeMillis})`)); await this._evaluateInFrames(`globalThis.__pwClock.controller.install(${timeMillis})`); } async pauseAt(ticks) { await this._installIfNeeded(); const timeMillis = parseTime(ticks); this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('pauseAt', ${Date.now()}, ${timeMillis})`)); await this._evaluateInFrames(`globalThis.__pwClock.controller.pauseAt(${timeMillis})`); } resumeNoReply() { if (!this._initScripts.length) return; const doResume = async () => { this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('resume', ${Date.now()})`)); await this._evaluateInFrames(`globalThis.__pwClock.controller.resume()`); }; doResume().catch(() => { }); } async resume(progress2) { await progress2.race(this._installIfNeeded()); this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('resume', ${Date.now()})`)); await progress2.race(this._evaluateInFrames(`globalThis.__pwClock.controller.resume()`)); } async setFixedTime(time) { await this._installIfNeeded(); const timeMillis = parseTime(time); this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('setFixedTime', ${Date.now()}, ${timeMillis})`)); await this._evaluateInFrames(`globalThis.__pwClock.controller.setFixedTime(${timeMillis})`); } async setSystemTime(time) { await this._installIfNeeded(); const timeMillis = parseTime(time); this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('setSystemTime', ${Date.now()}, ${timeMillis})`)); await this._evaluateInFrames(`globalThis.__pwClock.controller.setSystemTime(${timeMillis})`); } async runFor(ticks) { await this._installIfNeeded(); const ticksMillis = parseTicks(ticks); this._initScripts.push(await this._browserContext.addInitScript(nullProgress, `globalThis.__pwClock.controller.log('runFor', ${Date.now()}, ${ticksMillis})`)); await this._evaluateInFrames(`globalThis.__pwClock.controller.runFor(${ticksMillis})`); } async _installIfNeeded() { if (this._initScripts.length) return; const script = `(() => { const module = {}; ${source} if (!globalThis.__pwClock) globalThis.__pwClock = (module.exports.inject())(globalThis, ${JSON.stringify(this._browserContext._browser.options.name)}); })();`; const initScript = await this._browserContext.addInitScript(nullProgress, script); await this._evaluateInFrames(script); this._initScripts.push(initScript); } async _evaluateInFrames(script) { await this._browserContext.safeNonStallingEvaluateInAllFrames(script, "main", { throwOnJSErrors: true }); } }; } }); // packages/playwright-core/src/generated/webAuthnSource.ts var source2; var init_webAuthnSource = __esm({ "packages/playwright-core/src/generated/webAuthnSource.ts"() { "use strict"; source2 = ` var __commonJS = obj => { let required = false; let result; return function __require() { if (!required) { required = true; let fn; for (const name in obj) { fn = obj[name]; break; } const module = { exports: {} }; fn(module.exports, module); result = module.exports; } return result; } }; var __export = (target, all) => {for (var name in all) target[name] = all[name];}; var __toESM = mod => ({ ...mod, 'default': mod }); var __toCommonJS = mod => ({ ...mod, __esModule: true }); // packages/injected/src/webAuthn.ts var webAuthn_exports = {}; __export(webAuthn_exports, { inject: () => inject }); module.exports = __toCommonJS(webAuthn_exports); function inject(globalThis) { if (globalThis.__pwWebAuthnInstalled) return; globalThis.__pwWebAuthnInstalled = true; const binding = globalThis.__pwWebAuthnBinding; if (!binding || !globalThis.navigator) return; if (!globalThis.navigator.credentials) { Object.defineProperty(globalThis.navigator, "credentials", { value: { create: async () => null, get: async () => null }, writable: true, configurable: true }); } function toBase64Url(buf) { const bytes = buf instanceof ArrayBuffer ? new Uint8Array(buf) : new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); let s = ""; for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]); return globalThis.btoa(s).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", ""); } function fromBase64Url(s) { let str = s.replaceAll("-", "+").replaceAll("_", "/"); while (str.length % 4) str += "="; const bin = globalThis.atob(str); const out = new Uint8Array(bin.length); for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i); return out.buffer; } const PublicKeyCredentialCtor = globalThis.PublicKeyCredential; const AuthAttestationResponseCtor = globalThis.AuthenticatorAttestationResponse; const AuthAssertionResponseCtor = globalThis.AuthenticatorAssertionResponse; function defineReadonly(target, props) { for (const k of Object.keys(props)) Object.defineProperty(target, k, { value: props[k], enumerable: true, configurable: true }); } function makeAttestationResponse(clientDataJSON, attestationObject) { const proto = (AuthAttestationResponseCtor == null ? void 0 : AuthAttestationResponseCtor.prototype) || Object.prototype; const r = Object.create(proto); defineReadonly(r, { clientDataJSON, attestationObject }); r.getTransports = () => ["internal"]; r.getAuthenticatorData = () => { return attestationObject; }; r.getPublicKey = () => null; r.getPublicKeyAlgorithm = () => -7; return r; } function makeAssertionResponse(clientDataJSON, authenticatorData, signature, userHandle) { const proto = (AuthAssertionResponseCtor == null ? void 0 : AuthAssertionResponseCtor.prototype) || Object.prototype; const r = Object.create(proto); defineReadonly(r, { clientDataJSON, authenticatorData, signature, userHandle }); return r; } function makePublicKeyCredential(id, response) { const proto = (PublicKeyCredentialCtor == null ? void 0 : PublicKeyCredentialCtor.prototype) || Object.prototype; const cred = Object.create(proto); defineReadonly(cred, { id, rawId: fromBase64Url(id), type: "public-key", authenticatorAttachment: "platform", response }); cred.getClientExtensionResults = () => ({}); cred.toJSON = () => ({ id, rawId: id, type: "public-key", response: {} }); return cred; } function toBuf(x) { if (!x) return new ArrayBuffer(0); if (x instanceof ArrayBuffer) return x; const v = x; const out = new Uint8Array(v.byteLength); out.set(new Uint8Array(v.buffer, v.byteOffset, v.byteLength)); return out.buffer; } function failure(name, message) { const Ctor = globalThis.DOMException || Error; throw new Ctor(message, name); } const origCreate = globalThis.navigator.credentials.create.bind(globalThis.navigator.credentials); const origGet = globalThis.navigator.credentials.get.bind(globalThis.navigator.credentials); globalThis.navigator.credentials.create = async function(options) { var _a, _b, _c, _d, _e, _f, _g; if (!options || !options.publicKey) return origCreate(options); const pk = options.publicKey; const req = { type: "create", origin: globalThis.location.origin, challenge: toBase64Url(toBuf(pk.challenge)), rp: { id: (_a = pk.rp) == null ? void 0 : _a.id, name: ((_b = pk.rp) == null ? void 0 : _b.name) || "" }, user: { id: toBase64Url(toBuf((_c = pk.user) == null ? void 0 : _c.id)), name: ((_d = pk.user) == null ? void 0 : _d.name) || "", displayName: ((_e = pk.user) == null ? void 0 : _e.displayName) || "" }, pubKeyCredParams: (pk.pubKeyCredParams || []).map((p) => ({ type: p.type, alg: p.alg })), excludeCredentials: (pk.excludeCredentials || []).map((c) => ({ type: c.type, id: toBase64Url(toBuf(c.id)) })), userVerification: (_f = pk.authenticatorSelection) == null ? void 0 : _f.userVerification, residentKey: (_g = pk.authenticatorSelection) == null ? void 0 : _g.residentKey }; const result = await binding(req); if (!result.ok) failure(result.name, result.message); const resp = makeAttestationResponse(fromBase64Url(result.clientDataJSON), fromBase64Url(result.attestationObject)); return makePublicKeyCredential(result.id, resp); }; globalThis.navigator.credentials.get = async function(options) { if (!options || !options.publicKey) return origGet(options); const pk = options.publicKey; const req = { type: "get", origin: globalThis.location.origin, challenge: toBase64Url(toBuf(pk.challenge)), rpId: pk.rpId || new URL(globalThis.location.origin).hostname, allowCredentials: (pk.allowCredentials || []).map((c) => ({ type: c.type, id: toBase64Url(toBuf(c.id)) })), userVerification: pk.userVerification }; const result = await binding(req); if (!result.ok) failure(result.name, result.message); const resp = makeAssertionResponse( fromBase64Url(result.clientDataJSON), fromBase64Url(result.authenticatorData), fromBase64Url(result.signature), result.userHandle ? fromBase64Url(result.userHandle) : null ); return makePublicKeyCredential(result.id, resp); }; if (PublicKeyCredentialCtor) { PublicKeyCredentialCtor.isUserVerifyingPlatformAuthenticatorAvailable = async () => true; PublicKeyCredentialCtor.isConditionalMediationAvailable = async () => true; } } `; } }); // packages/playwright-core/src/server/credentials.ts function toPublic(r) { return { id: r.id, rpId: r.rpId, userHandle: r.userHandle, privateKey: r.privateKey, publicKey: r.publicKey }; } function randomBase64Url(bytes) { return bufToB64Url(import_crypto6.default.randomBytes(bytes)); } function bufToB64Url(b) { return b.toString("base64").replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", ""); } function b64UrlToBuf(s) { return Buffer.from(s, "base64url"); } function u32ToBytes(n) { const b = Buffer.alloc(4); b.writeUInt32BE(n >>> 0, 0); return b; } function cborHead(major2, value2) { const m = major2 << 5; if (value2 < 24) return Buffer.from([m | value2]); if (value2 < 256) return Buffer.from([m | 24, value2]); if (value2 < 65536) return Buffer.from([m | 25, value2 >> 8 & 255, value2 & 255]); return Buffer.from([m | 26, value2 >>> 24 & 255, value2 >> 16 & 255, value2 >> 8 & 255, value2 & 255]); } function cborUint(v) { return cborHead(0, v); } function cborNint(v) { return cborHead(1, -1 - v); } function cborBytes(b) { return Buffer.concat([cborHead(2, b.length), b]); } function cborText(s) { const b = Buffer.from(s, "utf8"); return Buffer.concat([cborHead(3, b.length), b]); } function cborMap(entries) { return Buffer.concat([cborHead(5, entries.length), ...entries.flatMap(([k, v]) => [k, v])]); } function encodeCoseEs256PublicKey(publicKey) { const jwk = publicKey.export({ format: "jwk" }); const x = Buffer.from(jwk.x, "base64url"); const y = Buffer.from(jwk.y, "base64url"); return cborMap([ [cborUint(1), cborUint(2)], // kty = EC2 [cborUint(3), cborNint(-7)], // alg = ES256 [cborNint(-1), cborUint(1)], // crv = P-256 [cborNint(-2), cborBytes(x)], [cborNint(-3), cborBytes(y)] ]); } function encodeAttestationObjectNone(authData) { return cborMap([ [cborText("fmt"), cborText("none")], [cborText("attStmt"), cborMap([])], [cborText("authData"), cborBytes(authData)] ]); } var import_crypto6, kBindingName, kAuthenticatorAAGUID, Credentials; var init_credentials = __esm({ "packages/playwright-core/src/server/credentials.ts"() { "use strict"; import_crypto6 = __toESM(require("crypto")); init_webAuthnSource(); init_progress(); kBindingName = "__pwWebAuthnBinding"; kAuthenticatorAAGUID = Buffer.alloc(16); Credentials = class { constructor(browserContext) { this._initScripts = []; this._installed = false; this._registry = /* @__PURE__ */ new Map(); this._browserContext = browserContext; } async create(options) { let privateKey = options.privateKey; let publicKey = options.publicKey; if (!privateKey || !publicKey) { const pair = import_crypto6.default.generateKeyPairSync("ec", { namedCurve: "P-256" }); privateKey = bufToB64Url(pair.privateKey.export({ format: "der", type: "pkcs8" })); publicKey = bufToB64Url(pair.publicKey.export({ format: "der", type: "spki" })); } const record = { id: options.id || randomBase64Url(16), rpId: options.rpId, userHandle: options.userHandle || randomBase64Url(16), privateKey, publicKey, signCount: 0, isResident: true }; this._registry.set(record.id, record); return toPublic(record); } async get(filter) { return [...this._registry.values()].filter((c) => { if (filter?.rpId && c.rpId !== filter.rpId) return false; if (filter?.id && c.id !== filter.id) return false; return true; }).map(toPublic); } async delete(id) { this._registry.delete(id); } async dispose(progress2) { await progress2.race(Promise.all(this._initScripts.map((s) => s.dispose()))); this._initScripts = []; this._installed = false; this._registry.clear(); } async install(progress2) { if (this._installed) return; this._installed = true; await this._browserContext.exposeBinding(progress2, kBindingName, async (_source, payload) => { try { if (payload?.type === "create") return await this._handleCreate(payload); if (payload?.type === "get") return this._handleGet(payload); } catch (e) { return { ok: false, name: "NotAllowedError", message: e.message }; } return { ok: false, name: "NotAllowedError", message: "Unknown WebAuthn request" }; }); const script = `(() => { const module = {}; ${source2} module.exports.inject()(globalThis); })();`; const initScript = await this._browserContext.addInitScript(nullProgress, script); this._initScripts.push(initScript); await progress2.race(this._browserContext.safeNonStallingEvaluateInAllFrames(script, "main", { throwOnJSErrors: false })); } async _handleCreate(req) { const rpId = req.rp?.id || new URL(req.origin).hostname; const userHandle = req.user.id; if (req.excludeCredentials?.length) { for (const desc of req.excludeCredentials) { if (this._registry.has(desc.id)) return { ok: false, name: "InvalidStateError", message: "Credential excluded" }; } } const pair = import_crypto6.default.generateKeyPairSync("ec", { namedCurve: "P-256" }); const privateKey = bufToB64Url(pair.privateKey.export({ format: "der", type: "pkcs8" })); const publicKey = bufToB64Url(pair.publicKey.export({ format: "der", type: "spki" })); const credentialId = import_crypto6.default.randomBytes(16); const credentialIdB64 = bufToB64Url(credentialId); const record = { id: credentialIdB64, rpId, userHandle, privateKey, publicKey, signCount: 0, isResident: req.residentKey === "required" || req.residentKey === "preferred" }; this._registry.set(credentialIdB64, record); const clientDataJSON = Buffer.from(JSON.stringify({ type: "webauthn.create", challenge: req.challenge, origin: req.origin, crossOrigin: false })); const rpIdHash = import_crypto6.default.createHash("sha256").update(rpId).digest(); const flags = 1 | 4 | 64; const signCountBuf = u32ToBytes(record.signCount); const cosePublicKey = encodeCoseEs256PublicKey(pair.publicKey); const credIdLenBuf = Buffer.from([credentialId.length >> 8 & 255, credentialId.length & 255]); const attestedCredentialData = Buffer.concat([kAuthenticatorAAGUID, credIdLenBuf, credentialId, cosePublicKey]); const authData = Buffer.concat([rpIdHash, Buffer.from([flags]), signCountBuf, attestedCredentialData]); const attestationObject = encodeAttestationObjectNone(authData); return { ok: true, id: credentialIdB64, clientDataJSON: bufToB64Url(clientDataJSON), attestationObject: bufToB64Url(attestationObject) }; } _handleGet(req) { const rpId = req.rpId || new URL(req.origin).hostname; let candidate; if (req.allowCredentials?.length) { for (const desc of req.allowCredentials) { const c = this._registry.get(desc.id); if (c && c.rpId === rpId) { candidate = c; break; } } } else { for (const c of this._registry.values()) { if (c.rpId === rpId && c.isResident) { candidate = c; break; } } } if (!candidate) return { ok: false, name: "NotAllowedError", message: "No matching credential" }; const clientDataJSON = Buffer.from(JSON.stringify({ type: "webauthn.get", challenge: req.challenge, origin: req.origin, crossOrigin: false })); const rpIdHash = import_crypto6.default.createHash("sha256").update(rpId).digest(); const flags = 1 | 4; candidate.signCount += 1; const signCountBuf = u32ToBytes(candidate.signCount); const authData = Buffer.concat([rpIdHash, Buffer.from([flags]), signCountBuf]); const clientDataHash = import_crypto6.default.createHash("sha256").update(clientDataJSON).digest(); const toSign = Buffer.concat([authData, clientDataHash]); const privateKey = import_crypto6.default.createPrivateKey({ key: b64UrlToBuf(candidate.privateKey), format: "der", type: "pkcs8" }); const signature = import_crypto6.default.sign("sha256", toSign, privateKey); return { ok: true, id: candidate.id, clientDataJSON: bufToB64Url(clientDataJSON), authenticatorData: bufToB64Url(authData), signature: bufToB64Url(signature), userHandle: candidate.userHandle || null }; } }; } }); // packages/playwright-core/src/server/instrumentation.ts function createRootSdkObject() { const fakeParent = { attribution: {}, instrumentation: createInstrumentation() }; const root = new SdkObject(fakeParent); root.guid = ""; return root; } function createInstrumentation() { const listeners = /* @__PURE__ */ new Map(); const lastListeners = /* @__PURE__ */ new Map(); return new Proxy({}, { get: (obj, prop) => { if (typeof prop !== "string") return obj[prop]; if (prop === "addListener") { return (listener, context2, options) => { if (options?.order === "last") lastListeners.set(listener, context2); else listeners.set(listener, context2); }; } if (prop === "removeListener") { return (listener) => { listeners.delete(listener); lastListeners.delete(listener); }; } if (!prop.startsWith("on")) return obj[prop]; return async (sdkObject, ...params2) => { for (const [listener, context2] of listeners) { if (!context2 || sdkObject.attribution.context === context2) await listener[prop]?.(sdkObject, ...params2); } for (const [listener, context2] of lastListeners) { if (!context2 || sdkObject.attribution.context === context2) await listener[prop]?.(sdkObject, ...params2); } }; } }); } var import_events3, SdkObject; var init_instrumentation = __esm({ "packages/playwright-core/src/server/instrumentation.ts"() { "use strict"; import_events3 = require("events"); init_crypto(); init_debugLogger(); SdkObject = class extends import_events3.EventEmitter { constructor(parent, guidPrefix, guid) { super(); this.guid = guid || `${guidPrefix || ""}@${createGuid()}`; this.setMaxListeners(0); this.attribution = { ...parent.attribution }; this.instrumentation = parent.instrumentation; } apiLog(message) { if (!this.attribution.playwright.options.isInternalPlaywright) debugLogger.log("api", message); } closeReason() { return this.attribution.worker?._closeReason || this.attribution.page?._closeReason || this.attribution.context?._closeReason || this.attribution.browser?._closeReason; } }; } }); // packages/playwright-core/src/server/debugger.ts function matchesLocation(metadata, location2) { return !!metadata.location?.file.includes(location2.file) && (location2.line === void 0 || metadata.location.line === location2.line) && (location2.column === void 0 || metadata.location.column === location2.column); } var symbol, Debugger; var init_debugger = __esm({ "packages/playwright-core/src/server/debugger.ts"() { "use strict"; init_protocolMetainfo(); init_time(); init_instrumentation(); init_browserContext(); symbol = Symbol("Debugger"); Debugger = class _Debugger extends SdkObject { constructor(context2) { super(context2, "debugger"); this._pauseAt = {}; this._enabled = false; this._pauseBeforeWaitingActions = false; this._muted = false; this._context = context2; this._context[symbol] = this; context2.instrumentation.addListener(this, context2, { order: "last" }); this._context.once(BrowserContext.Events.Close, () => { this._context.instrumentation.removeListener(this); }); } static { this.Events = { PausedStateChanged: "pausedstatechanged" }; } requestPause(progress2) { if (this.isPaused()) throw new Error("Debugger is already paused"); this.setPauseBeforeWaitingActions(); this.setPauseAt({ next: true }); } doResume(progress2) { if (!this.isPaused()) throw new Error("Debugger is not paused"); this.resume(); } next(progress2) { if (!this.isPaused()) throw new Error("Debugger is not paused"); this.setPauseBeforeWaitingActions(); this.setPauseAt({ next: true }); this.resume(); } runTo(progress2, location2) { if (!this.isPaused()) throw new Error("Debugger is not paused"); this.setPauseBeforeWaitingActions(); this.setPauseAt({ location: location2 }); this.resume(); } async setMuted(muted) { this._muted = muted; } async onBeforeCall(sdkObject, metadata) { if (this._muted || metadata.internal) return; const metainfo = getMetainfo(metadata); const pauseOnPauseCall = this._enabled && metadata.type === "BrowserContext" && metadata.method === "pause"; const pauseBeforeAction = !!this._pauseAt.next && !!metainfo?.pause && (this._pauseBeforeWaitingActions || !metainfo?.isAutoWaiting); const pauseOnLocation = !!this._pauseAt.location && matchesLocation(metadata, this._pauseAt.location); if (pauseOnPauseCall || pauseBeforeAction || pauseOnLocation) await this._pause(sdkObject, metadata); } async onBeforeInputAction(sdkObject, metadata) { if (this._muted || metadata.internal) return; const metainfo = getMetainfo(metadata); const pauseBeforeInput = !!this._pauseAt.next && !!metainfo?.pause && !!metainfo?.isAutoWaiting && !this._pauseBeforeWaitingActions; if (pauseBeforeInput) await this._pause(sdkObject, metadata); } async _pause(sdkObject, metadata) { if (this._muted || metadata.internal) return; if (this._pausedCall) return; this._pauseAt = {}; metadata.pauseStartTime = monotonicTime(); const result2 = new Promise((resolve) => { this._pausedCall = { metadata, sdkObject, resolve }; }); this.emit(_Debugger.Events.PausedStateChanged); return result2; } resume() { if (!this._pausedCall) return; this._pausedCall.metadata.pauseEndTime = monotonicTime(); this._pausedCall.resolve(); this._pausedCall = void 0; this.emit(_Debugger.Events.PausedStateChanged); } setPauseBeforeWaitingActions() { this._pauseBeforeWaitingActions = true; } setPauseAt(at = {}) { this._enabled = true; this._pauseAt = at; } isPaused(metadata) { if (metadata) return this._pausedCall?.metadata === metadata; return !!this._pausedCall; } pausedDetails() { return this._pausedCall; } }; } }); // packages/playwright-core/src/server/dialog.ts var Dialog, DialogManager; var init_dialog = __esm({ "packages/playwright-core/src/server/dialog.ts"() { "use strict"; init_assert(); init_instrumentation(); Dialog = class extends SdkObject { constructor(page, type3, message, onHandle, defaultValue) { super(page, "dialog"); this._handled = false; this._page = page; this._type = type3; this._message = message; this._onHandle = onHandle; this._defaultValue = defaultValue || ""; } async accept(progress2, promptText) { await progress2.race(this._accept(promptText)); } async dismiss(progress2) { await progress2.race(this._dismiss()); } page() { return this._page; } type() { return this._type; } message() { return this._message; } defaultValue() { return this._defaultValue; } async _accept(promptText) { assert(!this._handled, "Cannot accept dialog which is already handled!"); this._handled = true; this._page.browserContext.dialogManager._dialogWillClose(this); await this._onHandle(true, promptText); } async _dismiss() { assert(!this._handled, "Cannot dismiss dialog which is already handled!"); this._handled = true; this._page.browserContext.dialogManager._dialogWillClose(this); await this._onHandle(false); } async _close() { if (this._type === "beforeunload") await this._accept(); else await this._dismiss(); } }; DialogManager = class { constructor(instrumentation) { this._dialogHandlers = /* @__PURE__ */ new Set(); this._openedDialogs = /* @__PURE__ */ new Set(); this._instrumentation = instrumentation; } dialogDidOpen(dialog) { for (const frame of dialog.page().frameManager.frames()) frame.invalidateNonStallingEvaluations("JavaScript dialog interrupted evaluation"); this._openedDialogs.add(dialog); this._instrumentation.onDialog(dialog); let hasHandlers = false; for (const handler of this._dialogHandlers) { if (handler(dialog)) hasHandlers = true; } if (!hasHandlers) dialog._close().then(() => { }); } _dialogWillClose(dialog) { this._openedDialogs.delete(dialog); } addDialogHandler(handler) { this._dialogHandlers.add(handler); } removeDialogHandler(handler) { this._dialogHandlers.delete(handler); if (!this._dialogHandlers.size) { for (const dialog of this._openedDialogs) dialog._close().catch(() => { }); } } hasOpenDialogsForPage(page) { return [...this._openedDialogs].some((dialog) => dialog.page() === page); } async closeBeforeUnloadDialogs() { await Promise.all([...this._openedDialogs].map(async (dialog) => { if (dialog.type() === "beforeunload") await dialog._dismiss(); })); } }; } }); // packages/playwright-core/src/server/network.ts function filterCookies(cookies, urls) { const parsedURLs = urls.map((s) => new URL(s)); return cookies.filter((c) => { if (!parsedURLs.length) return true; for (const parsedURL of parsedURLs) { let domain = c.domain; if (!domain.startsWith(".")) domain = "." + domain; if (!("." + parsedURL.hostname).endsWith(domain)) continue; if (!parsedURL.pathname.startsWith(c.path)) continue; if (parsedURL.protocol !== "https:" && !isLocalHostname(parsedURL.hostname) && c.secure) continue; return true; } return false; }); } function isLocalHostname(hostname) { return hostname === "localhost" || hostname.endsWith(".localhost"); } function isForbiddenHeader(name, value2) { const lowerName = name.toLowerCase(); if (FORBIDDEN_HEADER_NAMES.has(lowerName)) return true; if (lowerName.startsWith("proxy-")) return true; if (lowerName.startsWith("sec-")) return true; if (lowerName === "x-http-method" || lowerName === "x-http-method-override" || lowerName === "x-method-override") { if (value2 && FORBIDDEN_METHODS.has(value2.toUpperCase())) return true; } return false; } function applyHeadersOverrides(original, overrides) { const forbiddenHeaders = original.filter((header) => isForbiddenHeader(header.name, header.value)); const allowedHeaders = overrides.filter((header) => !isForbiddenHeader(header.name, header.value)); return mergeHeaders([allowedHeaders, forbiddenHeaders]); } function rewriteCookies(cookies) { return cookies.map((c) => { assert(c.url || c.domain && c.path, "Cookie should have a url or a domain/path pair"); assert(!(c.url && c.domain), "Cookie should have either url or domain"); assert(!(c.url && c.path), "Cookie should have either url or path"); assert(!(c.expires && c.expires < 0 && c.expires !== -1), "Cookie should have a valid expires, only -1 or a positive number for the unix timestamp in seconds is allowed"); assert(!(c.expires && c.expires > 0 && c.expires > kMaxCookieExpiresDateInSeconds), "Cookie should have a valid expires, only -1 or a positive number for the unix timestamp in seconds is allowed"); const copy = { ...c }; if (copy.url) { assert(copy.url !== "about:blank", `Blank page can not have cookie "${c.name}"`); assert(!copy.url.startsWith("data:"), `Data URL page can not have cookie "${c.name}"`); const url2 = new URL(copy.url); copy.domain = url2.hostname; copy.path = url2.pathname.substring(0, url2.pathname.lastIndexOf("/") + 1); copy.secure = url2.protocol === "https:"; } return copy; }); } function parseURL2(url2) { try { return new URL(url2); } catch (e) { return null; } } function stripFragmentFromUrl(url2) { if (!url2.includes("#")) return url2; return url2.substring(0, url2.indexOf("#")); } function statusText(status) { return STATUS_TEXTS[String(status)] || "Unknown"; } function singleHeader(name, value2) { return [{ name, value: value2 }]; } function mergeHeaders(headers) { const lowerCaseToValue = /* @__PURE__ */ new Map(); const lowerCaseToOriginalCase = /* @__PURE__ */ new Map(); for (const h of headers) { if (!h) continue; for (const { name, value: value2 } of h) { const lower = name.toLowerCase(); lowerCaseToOriginalCase.set(lower, name); lowerCaseToValue.set(lower, value2); } } const result2 = []; for (const [lower, value2] of lowerCaseToValue) result2.push({ name: lowerCaseToOriginalCase.get(lower), value: value2 }); return result2; } function headersSize(headers) { let result2 = 0; for (const header of headers) result2 += header.name.length + header.value.length + 4; return result2; } function requestHeadersSize(headers, url2, method) { let result2 = 4; result2 += method.length; result2 += new URL(url2).pathname.length; result2 += 8; result2 += headersSize(headers); return result2; } function responseHeadersSize(headers, statusText2) { let result2 = 4; result2 += 8; result2 += 3; result2 += statusText2.length; result2 += headersSize(headers); result2 += 2; return result2; } var FORBIDDEN_HEADER_NAMES, FORBIDDEN_METHODS, kMaxCookieExpiresDateInSeconds, Request, Route, Response2, WebSocket, STATUS_TEXTS; var init_network2 = __esm({ "packages/playwright-core/src/server/network.ts"() { "use strict"; init_manualPromise(); init_assert(); init_browserContext(); init_fetch(); init_instrumentation(); FORBIDDEN_HEADER_NAMES = /* @__PURE__ */ new Set([ "accept-charset", "accept-encoding", "access-control-request-headers", "access-control-request-method", "connection", "content-length", "cookie", "date", "dnt", "expect", "host", "keep-alive", "origin", "referer", "set-cookie", "te", "trailer", "transfer-encoding", "upgrade", "via" ]); FORBIDDEN_METHODS = /* @__PURE__ */ new Set(["CONNECT", "TRACE", "TRACK"]); kMaxCookieExpiresDateInSeconds = 253402300799; Request = class _Request extends SdkObject { constructor(context2, frame, serviceWorker, redirectedFrom, documentId, url2, resourceType, method, postData, headers, wallTimeMs) { super(frame || context2, "request"); this._response = null; this._redirectedTo = null; this._failureText = null; this._frame = null; this._serviceWorker = null; this._rawRequestHeadersPromise = new ManualPromise(); this._waitForResponsePromise = new ManualPromise(); this._responseEndTiming = -1; assert(!url2.startsWith("data:"), "Data urls should not fire requests"); this._context = context2; this._frame = frame; this._serviceWorker = serviceWorker; this._redirectedFrom = redirectedFrom; if (redirectedFrom) redirectedFrom._redirectedTo = this; this._documentId = documentId; this._url = stripFragmentFromUrl(url2); this._resourceType = resourceType; this._method = method; this._postData = postData; this._headers = headers; this._wallTimeMs = wallTimeMs; this._isFavicon = url2.endsWith("/favicon.ico") || !!redirectedFrom?._isFavicon; } static { this.Events = { Response: "response" }; } wallTimeMs() { return this._wallTimeMs; } async raceWithPageClosure(progress2, promise) { const scope = this._serviceWorker?.openScope ?? this._frame?._page.openScope; if (scope) return await progress2.race(scope.race(promise)); return await progress2.race(promise); } async rawRequestHeaders(progress2) { return await this.raceWithPageClosure(progress2, this.internalRawRequestHeaders()); } async response(progress2) { return await this.raceWithPageClosure(progress2, this._waitForResponse()); } _setFailureText(failureText) { this._failureText = failureText; this._waitForResponsePromise.resolve(null); } _applyOverrides(overrides) { this._overrides = { ...this._overrides, ...overrides }; return this._overrides; } overrides() { return this._overrides; } url() { return this._overrides?.url || this._url; } resourceType() { return this._resourceType; } method() { return this._overrides?.method || this._method; } postDataBuffer() { return this._overrides?.postData || this._postData; } headers() { return this._overrides?.headers || this._headers; } headerValue(name) { const lowerCaseName = name.toLowerCase(); return this.headers().find((h) => h.name.toLowerCase() === lowerCaseName)?.value; } // "null" means no raw headers available - we'll use provisional headers as raw headers. setRawRequestHeaders(headers) { if (!this._rawRequestHeadersPromise.isDone()) this._rawRequestHeadersPromise.resolve(headers || this._headers); } async internalRawRequestHeaders() { return this._overrides?.headers || this._rawRequestHeadersPromise; } _waitForResponse() { return this._waitForResponsePromise; } _existingResponse() { return this._response; } _setResponse(response2) { this._response = response2; this._waitForResponsePromise.resolve(response2); this.emit(_Request.Events.Response, response2); } _finalRequest() { return this._redirectedTo ? this._redirectedTo._finalRequest() : this; } frame() { return this._frame; } serviceWorker() { return this._serviceWorker; } isNavigationRequest() { return !!this._documentId; } redirectedFrom() { return this._redirectedFrom; } failure() { if (this._failureText === null) return null; return { errorText: this._failureText }; } // TODO(bidi): remove once post body is available. _setBodySize(size) { this._bodySize = size; } bodySize() { return this._bodySize || this.postDataBuffer()?.length || 0; } async _requestHeadersSize() { return requestHeadersSize(await this.internalRawRequestHeaders(), this.url(), this.method()); } }; Route = class extends SdkObject { constructor(request2, delegate) { super(request2._frame || request2._context, "route"); this._handled = false; this._futureHandlers = []; this._request = request2; this._delegate = delegate; this._request._context.addRouteInFlight(this); } handle(handlers) { this._futureHandlers = [...handlers]; this.continue({ isFallback: true }).catch(() => { }); } async removeHandler(handler) { this._futureHandlers = this._futureHandlers.filter((h) => h !== handler); if (handler === this._currentHandler) { await this.continue({ isFallback: true }).catch(() => { }); return; } } request() { return this._request; } async abort(errorCode = "failed") { this._startHandling(); this._request._context.emit(BrowserContext.Events.RequestAborted, this._request); await this._delegate.abort(errorCode); this._endHandling(); } redirectNavigationRequest(url2) { this._startHandling(); assert(this._request.isNavigationRequest()); this._request.frame().redirectNavigation(url2, this._request._documentId, this._request.headerValue("referer")); this._endHandling(); } async fulfill(overrides) { this._startHandling(); let body = overrides.body; let isBase64 = overrides.isBase64 || false; if (body === void 0) { if (overrides.fetchResponseUid) { const buffer = this._request._context.fetchRequest.fetchResponses.get(overrides.fetchResponseUid) || APIRequestContext.findResponseBody(overrides.fetchResponseUid); assert(buffer, "Fetch response has been disposed"); body = buffer.toString("base64"); isBase64 = true; } else { body = ""; isBase64 = false; } } else if (!overrides.status || overrides.status < 200 || overrides.status >= 400) { this._request._responseBodyOverride = { body, isBase64 }; } const headers = [...overrides.headers || []]; this._maybeAddCorsHeaders(headers); this._request._context.emit(BrowserContext.Events.RequestFulfilled, this._request); await this._delegate.fulfill({ status: overrides.status || 200, headers, body, isBase64 }); this._endHandling(); } // See https://github.com/microsoft/playwright/issues/12929 _maybeAddCorsHeaders(headers) { const origin = this._request.headerValue("origin"); if (!origin) return; const requestUrl = new URL(this._request.url()); if (!requestUrl.protocol.startsWith("http")) return; if (requestUrl.origin === origin.trim()) return; const corsHeader = headers.find(({ name }) => name === "access-control-allow-origin"); if (corsHeader) return; headers.push({ name: "access-control-allow-origin", value: origin }); headers.push({ name: "access-control-allow-credentials", value: "true" }); headers.push({ name: "vary", value: "Origin" }); } async continue(overrides) { if (overrides.url) { const newUrl = new URL(overrides.url); const oldUrl = new URL(this._request.url()); if (oldUrl.protocol !== newUrl.protocol) throw new Error("New URL must have same protocol as overridden URL"); } if (overrides.headers) { overrides.headers = applyHeadersOverrides(this._request._headers, overrides.headers); } overrides = this._request._applyOverrides(overrides); const nextHandler = this._futureHandlers.shift(); if (nextHandler) { this._currentHandler = nextHandler; nextHandler(this, this._request); return; } if (!overrides.isFallback) this._request._context.emit(BrowserContext.Events.RequestContinued, this._request); this._startHandling(); await this._delegate.continue(overrides); this._endHandling(); } _startHandling() { assert(!this._handled, "Route is already handled!"); this._handled = true; this._currentHandler = void 0; } _endHandling() { this._futureHandlers = []; this._currentHandler = void 0; this._request._context.removeRouteInFlight(this); } }; Response2 = class extends SdkObject { constructor(request2, status, statusText2, headers, timing, getResponseBodyCallback, fromServiceWorker) { super(request2.frame() || request2._context, "response"); this._contentPromise = null; this._finishedPromise = new ManualPromise(); this._headersMap = /* @__PURE__ */ new Map(); this._serverAddrPromise = new ManualPromise(); this._securityDetailsPromise = new ManualPromise(); this._rawResponseHeadersPromise = new ManualPromise(); this._httpVersionPromise = new ManualPromise(); this._encodedBodySizePromise = new ManualPromise(); this._transferSizePromise = new ManualPromise(); this._responseHeadersSizePromise = new ManualPromise(); this._request = request2; this._timing = timing; this._status = status; this._statusText = statusText2; this._url = request2.url(); this._headers = headers; for (const { name, value: value2 } of this._headers) this._headersMap.set(name.toLowerCase(), value2); this._getResponseBodyCallback = getResponseBodyCallback; this._request._setResponse(this); this._fromServiceWorker = fromServiceWorker; } async body(progress2) { return await this._request.raceWithPageClosure(progress2, this.internalBody()); } async securityDetails(progress2) { return await this._request.raceWithPageClosure(progress2, this.internalSecurityDetails()); } async serverAddr(progress2) { return await this._request.raceWithPageClosure(progress2, this.internalServerAddr()); } async rawResponseHeaders(progress2) { return await this._request.raceWithPageClosure(progress2, this.internalRawResponseHeaders()); } async httpVersion(progress2) { return await this._request.raceWithPageClosure(progress2, this.internalHttpVersion()); } async sizes(progress2) { return await this._request.raceWithPageClosure(progress2, this.internalSizes()); } _serverAddrFinished(addr) { this._serverAddrPromise.resolve(addr); } _securityDetailsFinished(securityDetails) { this._securityDetailsPromise.resolve(securityDetails); } _requestFinished(responseEndTiming) { this._request._responseEndTiming = Math.max(responseEndTiming, this._timing.responseStart); if (this._timing.requestStart === -1) this._timing.requestStart = this._request._responseEndTiming; this._finishedPromise.resolve(); } _setHttpVersion(httpVersion) { this._httpVersionPromise.resolve(httpVersion); } url() { return this._url; } status() { return this._status; } statusText() { return this._statusText; } headers() { return this._headers; } headerValue(name) { return this._headersMap.get(name); } // "null" means no raw headers available - we'll use provisional headers as raw headers. setRawResponseHeaders(headers) { if (!this._rawResponseHeadersPromise.isDone()) this._rawResponseHeadersPromise.resolve(headers || this._headers); } setTransferSize(size) { this._transferSizePromise.resolve(size); } setEncodedBodySize(size) { this._encodedBodySizePromise.resolve(size); } setResponseHeadersSize(size) { this._responseHeadersSizePromise.resolve(size); } timing() { return this._timing; } async internalSecurityDetails() { return await this._securityDetailsPromise || null; } async internalServerAddr() { return await this._serverAddrPromise || null; } async internalRawResponseHeaders() { return await this._rawResponseHeadersPromise; } internalBody() { if (!this._contentPromise) { this._contentPromise = this._finishedPromise.then(async () => { if (this._status >= 300 && this._status <= 399) throw new Error("Response body is unavailable for redirect responses"); if (this._request._responseBodyOverride) { const { body, isBase64 } = this._request._responseBodyOverride; return Buffer.from(body, isBase64 ? "base64" : "utf-8"); } return this._getResponseBodyCallback(); }); } return this._contentPromise; } request() { return this._request; } finished() { return this._finishedPromise; } frame() { return this._request.frame(); } async internalHttpVersion() { const httpVersion = await this._httpVersionPromise || null; if (!httpVersion) return "HTTP/1.1"; if (httpVersion === "http/1.1") return "HTTP/1.1"; if (httpVersion === "h2") return "HTTP/2.0"; return httpVersion; } fromServiceWorker() { return this._fromServiceWorker; } async responseHeadersSize() { const availableSize = await this._responseHeadersSizePromise; if (availableSize !== null) return availableSize; return responseHeadersSize(await this._rawResponseHeadersPromise, this.statusText()); } async internalSizes() { const requestHeadersSize2 = await this._request._requestHeadersSize(); const responseHeadersSize2 = await this.responseHeadersSize(); let encodedBodySize = await this._encodedBodySizePromise; if (encodedBodySize === null) { const headers = await this._rawResponseHeadersPromise; const contentLength = headers.find((h) => h.name.toLowerCase() === "content-length")?.value; encodedBodySize = contentLength ? +contentLength : 0; } let transferSize = await this._transferSizePromise; if (transferSize === null) { transferSize = responseHeadersSize2 + encodedBodySize; } return { requestBodySize: this._request.bodySize(), requestHeadersSize: requestHeadersSize2, responseBodySize: encodedBodySize, responseHeadersSize: responseHeadersSize2, transferSize }; } }; WebSocket = class _WebSocket extends SdkObject { constructor(parent, url2) { super(parent, "ws"); this._notified = false; this._url = stripFragmentFromUrl(url2); } static { this.Events = { Close: "close", SocketError: "socketerror", FrameReceived: "framereceived", FrameSent: "framesent", Request: "request", Response: "response" }; } markAsNotified() { if (this._notified) return false; this._notified = true; return true; } url() { return this._url; } wallTimeMs() { return this._wallTimeMs; } setWallTimeMs(wallTimeMs) { this._wallTimeMs = wallTimeMs; } requestSent(headers) { this.emit(_WebSocket.Events.Request, { headers }); } responseReceived(status, statusText2, headers) { this.emit(_WebSocket.Events.Response, { status, statusText: statusText2, headers }); } frameSent(opcode, data, wallTimeMs) { this.emit(_WebSocket.Events.FrameSent, { opcode, data, wallTimeMs }); } frameReceived(opcode, data, wallTimeMs) { this.emit(_WebSocket.Events.FrameReceived, { opcode, data, wallTimeMs }); } error(errorMessage) { this.emit(_WebSocket.Events.SocketError, errorMessage); } closed() { this.emit(_WebSocket.Events.Close); } }; STATUS_TEXTS = { "100": "Continue", "101": "Switching Protocols", "102": "Processing", "103": "Early Hints", "200": "OK", "201": "Created", "202": "Accepted", "203": "Non-Authoritative Information", "204": "No Content", "205": "Reset Content", "206": "Partial Content", "207": "Multi-Status", "208": "Already Reported", "226": "IM Used", "300": "Multiple Choices", "301": "Moved Permanently", "302": "Found", "303": "See Other", "304": "Not Modified", "305": "Use Proxy", "306": "Switch Proxy", "307": "Temporary Redirect", "308": "Permanent Redirect", "400": "Bad Request", "401": "Unauthorized", "402": "Payment Required", "403": "Forbidden", "404": "Not Found", "405": "Method Not Allowed", "406": "Not Acceptable", "407": "Proxy Authentication Required", "408": "Request Timeout", "409": "Conflict", "410": "Gone", "411": "Length Required", "412": "Precondition Failed", "413": "Payload Too Large", "414": "URI Too Long", "415": "Unsupported Media Type", "416": "Range Not Satisfiable", "417": "Expectation Failed", "418": "I'm a teapot", "421": "Misdirected Request", "422": "Unprocessable Entity", "423": "Locked", "424": "Failed Dependency", "425": "Too Early", "426": "Upgrade Required", "428": "Precondition Required", "429": "Too Many Requests", "431": "Request Header Fields Too Large", "451": "Unavailable For Legal Reasons", "500": "Internal Server Error", "501": "Not Implemented", "502": "Bad Gateway", "503": "Service Unavailable", "504": "Gateway Timeout", "505": "HTTP Version Not Supported", "506": "Variant Also Negotiates", "507": "Insufficient Storage", "508": "Loop Detected", "510": "Not Extended", "511": "Network Authentication Required" }; } }); // packages/playwright-core/src/server/cookieStore.ts function parseRawCookie(header) { const pairs = header.split(";").filter((s) => s.trim().length > 0).map((p) => { let key = ""; let value3 = ""; const separatorPos = p.indexOf("="); if (separatorPos === -1) { key = p.trim(); } else { key = p.slice(0, separatorPos).trim(); value3 = p.slice(separatorPos + 1).trim(); } return [key, value3]; }); if (!pairs.length) return null; const [name, value2] = pairs[0]; const cookie = { name, value: value2 }; for (let i = 1; i < pairs.length; i++) { const [name2, value3] = pairs[i]; switch (name2.toLowerCase()) { case "expires": const expiresMs = +new Date(value3); if (isFinite(expiresMs)) { if (expiresMs <= 0) cookie.expires = 0; else cookie.expires = Math.min(expiresMs / 1e3, kMaxCookieExpiresDateInSeconds); } break; case "max-age": const maxAgeSec = parseInt(value3, 10); if (isFinite(maxAgeSec)) { if (maxAgeSec <= 0) cookie.expires = 0; else cookie.expires = Math.min(Date.now() / 1e3 + maxAgeSec, kMaxCookieExpiresDateInSeconds); } break; case "domain": cookie.domain = value3.toLocaleLowerCase() || ""; if (cookie.domain && !cookie.domain.startsWith(".") && cookie.domain.includes(".")) cookie.domain = "." + cookie.domain; break; case "path": cookie.path = value3 || ""; break; case "secure": cookie.secure = true; break; case "httponly": cookie.httpOnly = true; break; case "samesite": switch (value3.toLowerCase()) { case "none": cookie.sameSite = "None"; break; case "lax": cookie.sameSite = "Lax"; break; case "strict": cookie.sameSite = "Strict"; break; } break; } } return cookie; } function domainMatches(value2, domain) { if (value2 === domain) return true; if (!domain.startsWith(".")) return false; value2 = "." + value2; return value2.endsWith(domain); } function pathMatches(value2, path59) { if (value2 === path59) return true; if (!value2.endsWith("/")) value2 = value2 + "/"; if (!path59.endsWith("/")) path59 = path59 + "/"; return value2.startsWith(path59); } var Cookie, CookieStore; var init_cookieStore = __esm({ "packages/playwright-core/src/server/cookieStore.ts"() { "use strict"; init_network2(); Cookie = class { constructor(data) { this._raw = data; } _name() { return this._raw.name; } // https://datatracker.ietf.org/doc/html/rfc6265#section-5.4 matches(url2) { if (this._raw.secure && (url2.protocol !== "https:" && !isLocalHostname(url2.hostname))) return false; if (!domainMatches(url2.hostname, this._raw.domain)) return false; if (!pathMatches(url2.pathname, this._raw.path)) return false; return true; } _equals(other) { return this._raw.name === other._raw.name && this._raw.domain === other._raw.domain && this._raw.path === other._raw.path; } _networkCookie() { return this._raw; } _updateExpiresFrom(other) { this._raw.expires = other._raw.expires; } _expired() { if (this._raw.expires === -1) return false; return this._raw.expires * 1e3 < Date.now(); } }; CookieStore = class _CookieStore { constructor() { this._nameToCookies = /* @__PURE__ */ new Map(); } addCookies(cookies) { for (const cookie of cookies) this._addCookie(new Cookie(cookie)); } cookies(url2) { const result2 = []; for (const cookie of this._cookiesIterator()) { if (cookie.matches(url2)) result2.push(cookie._networkCookie()); } return result2; } allCookies() { const result2 = []; for (const cookie of this._cookiesIterator()) result2.push(cookie._networkCookie()); return result2; } _addCookie(cookie) { let set = this._nameToCookies.get(cookie._name()); if (!set) { set = /* @__PURE__ */ new Set(); this._nameToCookies.set(cookie._name(), set); } for (const other of set) { if (other._equals(cookie)) set.delete(other); } set.add(cookie); _CookieStore.pruneExpired(set); } *_cookiesIterator() { for (const [name, cookies] of this._nameToCookies) { _CookieStore.pruneExpired(cookies); for (const cookie of cookies) yield cookie; if (cookies.size === 0) this._nameToCookies.delete(name); } } static pruneExpired(cookies) { for (const cookie of cookies) { if (cookie._expired()) cookies.delete(cookie); } } }; } }); // packages/playwright-core/src/server/formData.ts function generateUniqueBoundaryString() { const charCodes = []; for (let i = 0; i < 16; i++) charCodes.push(alphaNumericEncodingMap[Math.floor(Math.random() * alphaNumericEncodingMap.length)]); return "----WebKitFormBoundary" + String.fromCharCode(...charCodes); } var mime2, MultipartFormData, alphaNumericEncodingMap; var init_formData = __esm({ "packages/playwright-core/src/server/formData.ts"() { "use strict"; mime2 = require("./utilsBundle").mime; MultipartFormData = class { constructor() { this._chunks = []; this._boundary = generateUniqueBoundaryString(); } contentTypeHeader() { return `multipart/form-data; boundary=${this._boundary}`; } addField(name, value2) { this._beginMultiPartHeader(name); this._finishMultiPartHeader(); this._chunks.push(Buffer.from(value2)); this._finishMultiPartField(); } addFileField(name, value2) { this._beginMultiPartHeader(name); this._chunks.push(Buffer.from(`; filename="${value2.name}"`)); this._chunks.push(Buffer.from(`\r content-type: ${value2.mimeType || mime2.getType(value2.name) || "application/octet-stream"}`)); this._finishMultiPartHeader(); this._chunks.push(value2.buffer); this._finishMultiPartField(); } finish() { this._addBoundary(true); return Buffer.concat(this._chunks); } _beginMultiPartHeader(name) { this._addBoundary(); this._chunks.push(Buffer.from(`content-disposition: form-data; name="${name}"`)); } _finishMultiPartHeader() { this._chunks.push(Buffer.from(`\r \r `)); } _finishMultiPartField() { this._chunks.push(Buffer.from(`\r `)); } _addBoundary(isLastBoundary) { this._chunks.push(Buffer.from("--" + this._boundary)); if (isLastBoundary) this._chunks.push(Buffer.from("--")); this._chunks.push(Buffer.from("\r\n")); } }; alphaNumericEncodingMap = [ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66 ]; } }); // packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts function loadDummyServerCertsIfNeeded() { if (dummyServerTlsOptions) return; const { cert, key } = generateSelfSignedCertificate(); dummyServerTlsOptions = { key, cert }; } function normalizeOrigin(origin) { try { return new URL(origin).origin; } catch (error) { return origin; } } function convertClientCertificatesToTLSOptions(clientCertificates) { if (!clientCertificates || !clientCertificates.length) return; const tlsOptions = { pfx: [], key: [], cert: [] }; for (const cert of clientCertificates) { if (cert.cert) tlsOptions.cert.push(cert.cert); if (cert.key) tlsOptions.key.push({ pem: cert.key, passphrase: cert.passphrase }); if (cert.pfx) tlsOptions.pfx.push({ buf: cert.pfx, passphrase: cert.passphrase }); } return tlsOptions; } function getMatchingTLSOptionsForOrigin(clientCertificates, origin) { const matchingCerts = clientCertificates?.filter( (c) => normalizeOrigin(c.origin) === origin ); return convertClientCertificatesToTLSOptions(matchingCerts); } function rewriteToLocalhostIfNeeded(host) { return host === "local.playwright" ? "localhost" : host; } function rewriteOpenSSLErrorIfNeeded(error) { if (error.message !== "unsupported" && error.code !== "ERR_CRYPTO_UNSUPPORTED_OPERATION") return error; return rewriteErrorMessage(error, [ "Unsupported TLS certificate.", "Most likely, the security algorithm of the given certificate was deprecated by OpenSSL.", "For more details, see https://github.com/openssl/openssl/blob/master/README-PROVIDERS.md#the-legacy-provider", "You could probably modernize the certificate by following the steps at https://github.com/nodejs/node/issues/40672#issuecomment-1243648223" ].join("\n")); } function parseALPNFromClientHello(buffer) { if (buffer.length < 6) return null; if (buffer[0] !== 22) return null; let offset = 5; if (buffer[offset] !== 1) return null; offset += 4; offset += 2; offset += 32; if (offset >= buffer.length) return null; const sessionIdLength = buffer[offset]; offset += 1 + sessionIdLength; if (offset + 2 > buffer.length) return null; const cipherSuitesLength = buffer.readUInt16BE(offset); offset += 2 + cipherSuitesLength; if (offset >= buffer.length) return null; const compressionMethodsLength = buffer[offset]; offset += 1 + compressionMethodsLength; if (offset + 2 > buffer.length) return null; const extensionsLength = buffer.readUInt16BE(offset); offset += 2; const extensionsEnd = offset + extensionsLength; if (extensionsEnd > buffer.length) return null; while (offset + 4 <= extensionsEnd) { const extensionType = buffer.readUInt16BE(offset); offset += 2; const extensionLength = buffer.readUInt16BE(offset); offset += 2; if (offset + extensionLength > extensionsEnd) return null; if (extensionType === 16) return parseALPNExtension(buffer.subarray(offset, offset + extensionLength)); offset += extensionLength; } return null; } function parseALPNExtension(buffer) { if (buffer.length < 2) return null; const listLength = buffer.readUInt16BE(0); if (listLength !== buffer.length - 2) return null; const protocols = []; let offset = 2; while (offset < buffer.length) { const protocolLength = buffer[offset]; offset += 1; if (offset + protocolLength > buffer.length) break; const protocol = buffer.subarray(offset, offset + protocolLength).toString("utf8"); protocols.push(protocol); offset += protocolLength; } return protocols.length > 0 ? protocols : null; } var import_events4, import_http23, import_net3, import_stream3, import_tls2, getProxyForUrl2, dummyServerTlsOptions, SocksProxyConnection, ClientCertificatesProxy; var init_socksClientCertificatesInterceptor = __esm({ "packages/playwright-core/src/server/socksClientCertificatesInterceptor.ts"() { "use strict"; import_events4 = require("events"); import_http23 = __toESM(require("http2")); import_net3 = __toESM(require("net")); import_stream3 = __toESM(require("stream")); import_tls2 = __toESM(require("tls")); init_socksProxy(); init_debugLogger(); init_happyEyeballs(); init_stringUtils(); init_crypto(); init_stackTrace(); init_network(); init_browserContext(); ({ getProxyForUrl: getProxyForUrl2 } = require("./utilsBundle")); dummyServerTlsOptions = void 0; SocksProxyConnection = class { constructor(socksProxy, uid, host, port) { this._firstPackageReceived = false; this._closed = false; this.socksProxy = socksProxy; this.uid = uid; this.host = host; this.port = port; this._serverCloseEventListener = () => { this._browserEncrypted.destroy(); }; this._browserEncrypted = new import_stream3.default.Duplex({ read: () => { }, write: (data, encoding, callback) => { this.socksProxy._socksProxy.sendSocketData({ uid: this.uid, data }); callback(); }, destroy: (error, callback) => { if (error) socksProxy._socksProxy.sendSocketError({ uid: this.uid, error: error.message }); else socksProxy._socksProxy.sendSocketEnd({ uid: this.uid }); callback(); } }); } async connect() { const proxyAgent = this.socksProxy._getProxyAgent(this.host, this.port); if (proxyAgent) this._serverEncrypted = await proxyAgent.connect(new import_events4.EventEmitter(), { host: rewriteToLocalhostIfNeeded(this.host), port: this.port, secureEndpoint: false }); else this._serverEncrypted = await createSocket(rewriteToLocalhostIfNeeded(this.host), this.port); this._serverEncrypted.once("close", this._serverCloseEventListener); this._serverEncrypted.once("error", (error) => this._browserEncrypted.destroy(error)); if (this._closed) { this._serverEncrypted.destroy(); return; } this.socksProxy._socksProxy.socketConnected({ uid: this.uid, host: this._serverEncrypted.localAddress, port: this._serverEncrypted.localPort }); } onClose() { this._serverEncrypted.destroy(); this._browserEncrypted.destroy(); this._closed = true; } onData(data) { if (!this._firstPackageReceived) { this._firstPackageReceived = true; const secureContext = data[0] === 22 ? this.socksProxy.secureContextMap.get(normalizeOrigin(`https://${this.host}:${this.port}`)) : void 0; if (secureContext) this._establishTlsTunnel(this._browserEncrypted, data, secureContext); else this._establishPlaintextTunnel(this._browserEncrypted); } this._browserEncrypted.push(data); } _establishPlaintextTunnel(browserEncrypted) { browserEncrypted.pipe(this._serverEncrypted); this._serverEncrypted.pipe(browserEncrypted); } _establishTlsTunnel(browserEncrypted, clientHello, secureContext) { const browserALPNProtocols = parseALPNFromClientHello(clientHello) || ["http/1.1"]; debugLogger.log("client-certificates", `Browser->Proxy ${this.host}:${this.port} offers ALPN ${browserALPNProtocols}`); const rejectUnauthorized = !this.socksProxy.ignoreHTTPSErrors; const serverDecrypted = import_tls2.default.connect({ socket: this._serverEncrypted, host: this.host, port: this.port, rejectUnauthorized, ALPNProtocols: browserALPNProtocols, servername: !import_net3.default.isIP(this.host) ? this.host : void 0, secureContext }, async () => { const browserDecrypted = await this._upgradeToTLSIfNeeded(browserEncrypted, serverDecrypted.alpnProtocol); debugLogger.log("client-certificates", `Proxy->Server ${this.host}:${this.port} chooses ALPN ${browserDecrypted.alpnProtocol}`); browserDecrypted.pipe(serverDecrypted); serverDecrypted.pipe(browserDecrypted); const cleanup = (error) => this._serverEncrypted.destroy(error); browserDecrypted.once("error", cleanup); serverDecrypted.once("error", cleanup); browserDecrypted.once("close", cleanup); serverDecrypted.once("close", cleanup); if (this._closed) serverDecrypted.destroy(); }); serverDecrypted.once("error", async (error) => { debugLogger.log("client-certificates", `error when connecting to server: ${error.message.replaceAll("\n", " ")}`); this._serverEncrypted.removeListener("close", this._serverCloseEventListener); this._serverEncrypted.destroy(); const browserDecrypted = await this._upgradeToTLSIfNeeded(this._browserEncrypted, serverDecrypted.alpnProtocol); const responseBody = escapeHTML("Playwright client-certificate error: " + error.message).replaceAll("\n", "
"); if (browserDecrypted.alpnProtocol === "h2") { if ("performServerHandshake" in import_http23.default) { const session2 = import_http23.default.performServerHandshake(browserDecrypted); session2.on("error", (error2) => { this._browserEncrypted.destroy(error2); }); session2.once("stream", (stream3) => { const cleanup = (error2) => { session2.close(); this._browserEncrypted.destroy(error2); }; stream3.once("end", cleanup); stream3.once("error", cleanup); stream3.respond({ [import_http23.default.constants.HTTP2_HEADER_CONTENT_TYPE]: "text/html", [import_http23.default.constants.HTTP2_HEADER_STATUS]: 503 }); stream3.end(responseBody); }); } else { this._browserEncrypted.destroy(error); } } else { browserDecrypted.end([ "HTTP/1.1 503 Internal Server Error", "Content-Type: text/html; charset=utf-8", "Content-Length: " + Buffer.byteLength(responseBody), "", responseBody ].join("\r\n")); } }); } async _upgradeToTLSIfNeeded(socket, alpnProtocol) { this._brorwserDecrypted ??= new Promise((resolve, reject) => { const dummyServer = import_tls2.default.createServer({ ...dummyServerTlsOptions, ALPNProtocols: [alpnProtocol || "http/1.1"] }); dummyServer.emit("connection", socket); dummyServer.once("secureConnection", (tlsSocket) => { dummyServer.close(); resolve(tlsSocket); }); dummyServer.once("error", (error) => { dummyServer.close(); reject(error); }); }); return this._brorwserDecrypted; } }; ClientCertificatesProxy = class _ClientCertificatesProxy { constructor(contextOptions) { this._connections = /* @__PURE__ */ new Map(); this.secureContextMap = /* @__PURE__ */ new Map(); verifyClientCertificates(contextOptions.clientCertificates); this.ignoreHTTPSErrors = contextOptions.ignoreHTTPSErrors; this._proxy = contextOptions.proxy; this._initSecureContexts(contextOptions.clientCertificates); this._socksProxy = new SocksProxy(); this._socksProxy.setPattern("*"); this._socksProxy.addListener(SocksProxy.Events.SocksRequested, async (payload) => { try { const connection = new SocksProxyConnection(this, payload.uid, payload.host, payload.port); await connection.connect(); this._connections.set(payload.uid, connection); } catch (error) { debugLogger.log("client-certificates", `Failed to connect to ${payload.host}:${payload.port}: ${error.message}`); this._socksProxy.socketFailed({ uid: payload.uid, errorCode: error.code }); } }); this._socksProxy.addListener(SocksProxy.Events.SocksData, (payload) => { this._connections.get(payload.uid)?.onData(payload.data); }); this._socksProxy.addListener(SocksProxy.Events.SocksClosed, (payload) => { this._connections.get(payload.uid)?.onClose(); this._connections.delete(payload.uid); }); loadDummyServerCertsIfNeeded(); } _getProxyAgent(host, port) { const proxyFromOptions = createProxyAgent(this._proxy); if (proxyFromOptions) return proxyFromOptions; const proxyFromEnv = getProxyForUrl2(`https://${host}:${port}`); if (proxyFromEnv) return createProxyAgent({ server: proxyFromEnv }); } _initSecureContexts(clientCertificates) { const origin2certs = /* @__PURE__ */ new Map(); for (const cert of clientCertificates || []) { const origin = normalizeOrigin(cert.origin); const certs = origin2certs.get(origin) || []; certs.push(cert); origin2certs.set(origin, certs); } for (const [origin, certs] of origin2certs) { try { this.secureContextMap.set(origin, import_tls2.default.createSecureContext(convertClientCertificatesToTLSOptions(certs))); } catch (error) { error = rewriteOpenSSLErrorIfNeeded(error); throw rewriteErrorMessage(error, `Failed to load client certificate: ${error.message}`); } } } static async create(progress2, contextOptions) { const proxy = new _ClientCertificatesProxy(contextOptions); try { await progress2.race(proxy._socksProxy.listen(0, "127.0.0.1")); return proxy; } catch (error) { await progress2.race(proxy.close()); throw error; } } proxySettings() { return { server: `socks5://127.0.0.1:${this._socksProxy.port()}` }; } async close() { await this._socksProxy.close(); } }; } }); // packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts 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]; } const kObserverConfig = { attributes: true, subtree: true }; function removeHash2(url2) { try { const u = new URL(url2); u.hash = ""; return u.toString(); } catch (e) { return url2; } } class Streamer { constructor() { this._lastSnapshotNumber = 0; this._staleStyleSheets = /* @__PURE__ */ new Set(); this._modifiedStyleSheets = /* @__PURE__ */ new Set(); this._readingStyleSheet = false; this._targetGeneration = 0; 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._interceptNativeSetter(window.StyleSheet.prototype, "disabled", (sheet) => { if (sheet instanceof CSSStyleSheet) this._invalidateStyleSheet(sheet); }); this._interceptNativeAsyncMethod(window.CSSStyleSheet.prototype, "replace", (sheet) => this._invalidateStyleSheet(sheet)); this._fakeBase = document.createElement("base"); this._observer = new MutationObserver((list) => this._handleMutations(list)); this._ensureObservingCurrentDocument(); } _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) => { const target = event.composedPath()[0]; if (target?.nodeType !== Node.ELEMENT_NODE) return; target.__playwright_target__ = this._targetGeneration; }); document.addEventListener("__playwright_reset_targets__", () => { ++this._targetGeneration; }); } _interceptNativeMethod(obj, method, cb) { const native = obj[method]; if (!native) return; obj[method] = function(...args) { const result2 = native.call(this, ...args); cb(this, result2); return result2; }; } _interceptNativeAsyncMethod(obj, method, cb) { const native = obj[method]; if (!native) return; obj[method] = async function(...args) { const result2 = await native.call(this, ...args); cb(this, result2); return result2; }; } _interceptNativeGetter(obj, prop, cb) { const descriptor = Object.getOwnPropertyDescriptor(obj, prop); Object.defineProperty(obj, prop, { ...descriptor, get: function() { const result2 = descriptor.get.call(this); cb(this, result2); return result2; } }); } _interceptNativeSetter(obj, prop, cb) { const descriptor = Object.getOwnPropertyDescriptor(obj, prop); Object.defineProperty(obj, prop, { ...descriptor, set: function(value2) { const result2 = descriptor.set.call(this, value2); cb(this, value2); return result2; } }); } _handleMutations(list) { for (const mutation of list) ensureCachedData(mutation.target).attributesCached = void 0; } _ensureObservingCurrentDocument() { if (this._observedDocument === document) return; this._observedDocument = document; this._observer.disconnect(); this._observer.observe(document, kObserverConfig); this._refreshListenersWhenNeeded(); } _invalidateStyleSheet(sheet) { if (this._readingStyleSheet) return; this._staleStyleSheets.add(sheet); if (sheet.href !== null) this._modifiedStyleSheets.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; } resetHistory() { this._staleStyleSheets.clear(); const visitNode = (node) => { resetCachedData(node); if (node.nodeType === Node.ELEMENT_NODE) { const element2 = node; if (element2.shadowRoot) visitNode(element2.shadowRoot); } for (let child = node.firstChild; child; child = child.nextSibling) visitNode(child); }; visitNode(document.documentElement); visitNode(this._fakeBase); } __sanitizeMetaAttribute(name, value2, httpEquiv) { if (name === "charset") return "utf-8"; if (httpEquiv.toLowerCase() !== "content-type" || name !== "content") return value2; const [type3, ...params2] = value2.split(";"); if (type3 !== "text/html" || params2.length <= 0) return value2; const charsetParamIdx = params2.findIndex((param) => param.trim().startsWith("charset=")); if (charsetParamIdx > -1) params2[charsetParamIdx] = "charset=utf-8"; return `${type3}; ${params2.join("; ")}`; } _sanitizeUrl(url2) { if (url2.startsWith("javascript:") || url2.startsWith("vbscript:")) return ""; return url2; } _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, url2) { if (url2 === "") return ""; try { return new URL(url2, base).href; } catch (e) { return url2; } } _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 { if (sheet.disabled) return ""; const rules = []; for (const rule of sheet.cssRules) rules.push(rule.cssText); return rules.join("\n"); } finally { this._readingStyleSheet = false; } } captureSnapshot(reset) { const timestamp = performance.now(); const snapshotNumber = ++this._lastSnapshotNumber; if (reset === "history") this.resetHistory(); if (reset) ++this._targetGeneration; let nodeCounter = 0; let shadowDomNesting = 0; let headNesting = 0; this._ensureObservingCurrentDocument(); 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") { const httpEquiv = node.httpEquiv.toLowerCase(); if (httpEquiv === "content-security-policy" || httpEquiv === "refresh" || httpEquiv === "set-cookie") return; } if ((nodeName === "IFRAME" || nodeName === "FRAME") && headNesting) return; const data = ensureCachedData(node); const values = []; let equals = !!data.cached; let extraNodes = 0; const expectValue = (value2) => { equals = equals && data.cached[values.length] === value2; values.push(value2); }; 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 value2 = node.nodeValue || ""; expectValue(value2); return checkAndReturn(value2); } 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 result3 = [nodeName, attrs]; const visitChild = (child) => { const snapshot3 = visitNode(child); if (snapshot3) { result3.push(snapshot3.n); expectValue(child); equals = equals && snapshot3.equals; } }; const visitChildStyleSheet = (child) => { const snapshot3 = visitStyleSheet(child); if (snapshot3) { result3.push(snapshot3.n); expectValue(child); equals = equals && snapshot3.equals; } }; if (nodeType === Node.DOCUMENT_FRAGMENT_NODE) attrs[kShadowAttribute] = "open"; if (nodeType === Node.ELEMENT_NODE) { const element2 = node; if (element2.localName.includes("-") && window.customElements?.get(element2.localName)) definedCustomElements.add(element2.localName); if (nodeName === "INPUT" || nodeName === "TEXTAREA") { const value2 = element2.value; expectValue(kValueAttribute); expectValue(value2); attrs[kValueAttribute] = value2; } if (nodeName === "INPUT" && ["checkbox", "radio"].includes(element2.type)) { const value2 = element2.checked ? "true" : "false"; expectValue(kCheckedAttribute); expectValue(value2); attrs[kCheckedAttribute] = value2; } if (nodeName === "OPTION") { const value2 = element2.selected ? "true" : "false"; expectValue(kSelectedAttribute); expectValue(value2); attrs[kSelectedAttribute] = value2; } if (nodeName === "CANVAS" || nodeName === "IFRAME" || nodeName === "FRAME") { const boundingRect = element2.getBoundingClientRect(); const value2 = JSON.stringify({ left: boundingRect.left, top: boundingRect.top, right: boundingRect.right, bottom: boundingRect.bottom }); expectValue(kBoundingRectAttribute); expectValue(value2); attrs[kBoundingRectAttribute] = value2; } if (element2.popover && element2.matches && element2.matches(":popover-open")) { const value2 = "true"; expectValue(kPopoverOpenAttribute); expectValue(value2); attrs[kPopoverOpenAttribute] = value2; } if (nodeName === "DIALOG" && element2.open) { const value2 = element2.matches(":modal") ? "modal" : "true"; expectValue(kDialogOpenAttribute); expectValue(value2); attrs[kDialogOpenAttribute] = value2; } if (element2.scrollTop) { expectValue(kScrollTopAttribute); expectValue(element2.scrollTop); attrs[kScrollTopAttribute] = "" + element2.scrollTop; } if (element2.scrollLeft) { expectValue(kScrollLeftAttribute); expectValue(element2.scrollLeft); attrs[kScrollLeftAttribute] = "" + element2.scrollLeft; } if (element2.shadowRoot) { ++shadowDomNesting; visitChild(element2.shadowRoot); --shadowDomNesting; } if (element2.__playwright_target__ === this._targetGeneration) { expectValue(kTargetAttribute); attrs[kTargetAttribute] = ""; } } 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 element2 = node; const frameId = element2[kSnapshotFrameId]; const name = "src"; const value2 = frameId ? `/snapshot/${frameId}` : ""; expectValue(name); expectValue(value2); attrs[name] = value2; } if (nodeName === "BODY" && definedCustomElements.size) { const value2 = [...definedCustomElements].join(","); expectValue(kCustomElementsAttribute); expectValue(value2); attrs[kCustomElementsAttribute] = value2; } if (nodeName === "IMG" || nodeName === "PICTURE") { const value2 = nodeName === "PICTURE" ? "" : this._sanitizeUrl(node.currentSrc); expectValue(kCurrentSrcAttribute); expectValue(value2); attrs[kCurrentSrcAttribute] = value2; } if (equals && data.attributesCached && !shadowDomNesting) return checkAndReturn(result3); if (nodeType === Node.ELEMENT_NODE) { const element2 = node; for (let i = 0; i < element2.attributes.length; i++) { const name = element2.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 value2 = element2.attributes[i].value; if (nodeName === "META") value2 = this.__sanitizeMetaAttribute(name, value2, node.httpEquiv); else if (name === "src" && nodeName === "IMG") value2 = this._sanitizeUrl(value2); else if (name === "srcset" && nodeName === "IMG") value2 = this._sanitizeSrcSet(value2); else if (name === "srcset" && nodeName === "SOURCE") value2 = this._sanitizeSrcSet(value2); else if (name === "href" && nodeName === "LINK") value2 = this._sanitizeUrl(value2); else if (name.startsWith("on")) value2 = ""; expectValue(name); expectValue(value2); attrs[name] = value2; } expectValue(kEndOfList); } if (result3.length === 2 && !Object.keys(attrs).length) result3.pop(); return checkAndReturn(result3); }; 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 result2 = { 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._modifiedStyleSheets) { if (sheet.href === null) continue; const content = this._updateLinkStyleSheetTextIfNeeded(sheet, snapshotNumber); if (content === void 0) { continue; } const base = this._getSheetBase(sheet); const url2 = removeHash2(this._resolveUrl(base, sheet.href)); result2.resourceOverrides.push({ url: url2, content, contentType: "text/css" }); } result2.collectionTime = performance.now() - timestamp; return result2; } } window[snapshotStreamer] = new Streamer(); } var init_snapshotterInjected = __esm({ "packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts"() { "use strict"; } }); // packages/playwright-core/src/server/trace/recorder/snapshotter.ts var mime3, Snapshotter, kNeedsResetSymbol; var init_snapshotter = __esm({ "packages/playwright-core/src/server/trace/recorder/snapshotter.ts"() { "use strict"; init_time(); init_crypto(); init_debugLogger(); init_eventsHelper(); init_snapshotterInjected(); init_browserContext(); init_progress(); mime3 = require("./utilsBundle").mime; Snapshotter = class { constructor(context2, delegate) { this._eventListeners = []; this._started = false; this._context = context2; this._delegate = delegate; const guid = createGuid(); this._snapshotStreamer = "__playwright_snapshot_streamer_" + guid; } started() { return this._started; } async start(progress2) { this._started = true; if (!this._initScript) await this._initialize(progress2); await progress2.race(this.reset()); } async reset() { if (this._started) await this._context.safeNonStallingEvaluateInAllFrames(`window["${this._snapshotStreamer}"].resetHistory()`, "main"); } stop() { this._started = false; } async resetForReuse() { if (this._initScript) { eventsHelper.removeEventListeners(this._eventListeners); await this._initScript.dispose(); this._initScript = void 0; } } async _initialize(progress2) { for (const page of this._context.pages()) this._onPage(page); this._eventListeners = [ eventsHelper.addEventListener(this._context, BrowserContext.Events.Page, this._onPage.bind(this)), eventsHelper.addEventListener(this._context, BrowserContext.Events.FrameAttached, (frame) => this._annotateFrameHierarchy(frame)) ]; const { javaScriptEnabled } = this._context._options; const initScriptSource = `(${frameSnapshotStreamer})("${this._snapshotStreamer}", ${javaScriptEnabled || javaScriptEnabled === void 0})`; this._initScript = await this._context.addInitScript(progress2, initScriptSource); await progress2.race(this._context.safeNonStallingEvaluateInAllFrames(initScriptSource, "main")); } dispose() { eventsHelper.removeEventListeners(this._eventListeners); } async _captureFrameSnapshot(frame, resetTargets) { const needsHistoryReset = !!frame[kNeedsResetSymbol]; frame[kNeedsResetSymbol] = false; const reset = needsHistoryReset ? "history" : resetTargets ? "targets" : void 0; const expression2 = `window["${this._snapshotStreamer}"].captureSnapshot(${JSON.stringify(reset)})`; try { return await frame.nonStallingRawEvaluateInExistingMainContext(expression2); } catch (e) { frame[kNeedsResetSymbol] = true; debugLogger.log("error", e); } } async captureSnapshot(page, callId, snapshotName, resetTargets) { const snapshots = page.frames().map(async (frame) => { const data = await this._captureFrameSnapshot(frame, resetTargets); if (!data || !this._started) return; const snapshot3 = { callId, snapshotName, pageId: page.guid, frameId: frame.guid, frameUrl: data.url, doctype: data.doctype, html: data.html, viewport: data.viewport, timestamp: monotonicTime(), wallTime: data.wallTime, collectionTime: data.collectionTime, resourceOverrides: [], isMainFrame: page.mainFrame() === frame }; for (const { url: url2, content, contentType } of data.resourceOverrides) { if (typeof content === "string") { const buffer = Buffer.from(content); const sha1 = calculateSha1(buffer) + "." + (mime3.getExtension(contentType) || "dat"); this._delegate.onSnapshotterBlob({ sha1, buffer }); snapshot3.resourceOverrides.push({ url: url2, sha1 }); } else { snapshot3.resourceOverrides.push({ url: url2, ref: content }); } } this._delegate.onFrameSnapshot(snapshot3); }); await Promise.all(snapshots); } _onPage(page) { for (const frame of page.frames()) this._annotateFrameHierarchy(frame); } _annotateFrameHierarchy(frame) { (async () => { const frameElement = await frame.frameElement(nullProgress); const parent = frame.parentFrame(); if (!parent) return; const context2 = await parent.mainContext(); await context2?.evaluate(({ snapshotStreamer, frameElement: frameElement2, frameId }) => { window[snapshotStreamer].markIframe(frameElement2, frameId); }, { snapshotStreamer: this._snapshotStreamer, frameElement, frameId: frame.guid }); frameElement.dispose(); })().catch(() => { }); } }; kNeedsResetSymbol = Symbol("kNeedsReset"); } }); // packages/playwright-core/src/server/artifact.ts var import_fs12, Artifact; var init_artifact = __esm({ "packages/playwright-core/src/server/artifact.ts"() { "use strict"; import_fs12 = __toESM(require("fs")); init_manualPromise(); init_assert(); init_errors(); init_instrumentation(); Artifact = class extends SdkObject { constructor(parent, localPath, unaccessibleErrorMessage, cancelCallback) { super(parent, "artifact"); this._finishedPromise = new ManualPromise(); this._saveCallbacks = []; this._finished = false; this._deleted = false; this._localPath = localPath; this._unaccessibleErrorMessage = unaccessibleErrorMessage; this._cancelCallback = cancelCallback; } async localPathAfterFinished(progress2) { return await progress2.race(this._localPathAfterFinished()); } async failureError(progress2) { return await progress2.race(this._failureError()); } async cancel(progress2) { return await progress2.race(this._cancel()); } async delete(progress2) { return await progress2.race(this._delete()); } localPath() { return this._localPath; } async _localPathAfterFinished() { if (this._unaccessibleErrorMessage) throw new Error(this._unaccessibleErrorMessage); await this._finishedPromise; if (this._failureErrorValue) throw this._failureErrorValue; return this._localPath; } saveAs(progress2, saveCallback) { if (this._unaccessibleErrorMessage) throw new Error(this._unaccessibleErrorMessage); if (this._deleted) throw new Error(`File already deleted. Save before deleting.`); if (this._failureErrorValue) throw this._failureErrorValue; if (this._finished) { saveCallback(this._localPath).catch(() => { }); return; } this._saveCallbacks.push(saveCallback); } async _failureError() { if (this._unaccessibleErrorMessage) return this._unaccessibleErrorMessage; await this._finishedPromise; return this._failureErrorValue?.message || null; } async _cancel() { assert(this._cancelCallback !== void 0); return this._cancelCallback(); } async _delete() { if (this._unaccessibleErrorMessage) return; const fileName = await this._localPathAfterFinished(); if (this._deleted) return; this._deleted = true; if (fileName) await import_fs12.default.promises.unlink(fileName).catch((e) => { }); } async deleteOnContextClose() { if (this._deleted) return; this._deleted = true; if (!this._unaccessibleErrorMessage) await import_fs12.default.promises.unlink(this._localPath).catch((e) => { }); await this.reportFinished(new TargetClosedError(this.closeReason())); } async reportFinished(error) { if (this._finished) return; this._finished = true; this._failureErrorValue = error; if (error) { for (const callback of this._saveCallbacks) await callback("", error); } else { for (const callback of this._saveCallbacks) await callback(this._localPath); } this._saveCallbacks = []; this._finishedPromise.resolve(); } }; } }); // packages/playwright-core/src/protocol/validatorPrimitives.ts function findValidator(type3, method, kind) { const validator = maybeFindValidator(type3, method, kind); if (!validator) throw new ValidationError(`Unknown scheme for ${kind}: ${type3}.${method}`); return validator; } function maybeFindValidator(type3, method, kind) { const schemeName = type3 + (kind === "Initializer" ? "" : method[0].toUpperCase() + method.substring(1)) + kind; return scheme[schemeName]; } function createMetadataValidator() { return tOptional(scheme["Metadata"]); } function createWaitInfoValidator() { return scheme["WaitInfo"]; } var ValidationError, scheme, tFloat, tInt, tBoolean, tString, tBinary, tAny, tOptional, tArray, tObject, tEnum, tChannel, tType; var init_validatorPrimitives = __esm({ "packages/playwright-core/src/protocol/validatorPrimitives.ts"() { "use strict"; ValidationError = class extends Error { }; scheme = {}; tFloat = (arg, path59, context2) => { if (arg instanceof Number) return arg.valueOf(); if (typeof arg === "number") return arg; throw new ValidationError(`${path59}: expected float, got ${typeof arg}`); }; tInt = (arg, path59, context2) => { let value2; if (arg instanceof Number) value2 = arg.valueOf(); else if (typeof arg === "number") value2 = arg; else throw new ValidationError(`${path59}: expected integer, got ${typeof arg}`); if (!Number.isInteger(value2)) throw new ValidationError(`${path59}: expected integer, got float ${value2}`); return value2; }; tBoolean = (arg, path59, context2) => { if (arg instanceof Boolean) return arg.valueOf(); if (typeof arg === "boolean") return arg; throw new ValidationError(`${path59}: expected boolean, got ${typeof arg}`); }; tString = (arg, path59, context2) => { if (arg instanceof String) return arg.valueOf(); if (typeof arg === "string") return arg; throw new ValidationError(`${path59}: expected string, got ${typeof arg}`); }; tBinary = (arg, path59, context2) => { if (context2.binary === "fromBase64") { if (arg instanceof String) return Buffer.from(arg.valueOf(), "base64"); if (typeof arg === "string") return Buffer.from(arg, "base64"); throw new ValidationError(`${path59}: expected base64-encoded buffer, got ${typeof arg}`); } if (context2.binary === "toBase64") { if (!(arg instanceof Buffer)) throw new ValidationError(`${path59}: expected Buffer, got ${typeof arg}`); return arg.toString("base64"); } if (context2.binary === "buffer") { if (!(arg instanceof Buffer) && !(arg instanceof Object)) throw new ValidationError(`${path59}: expected Buffer, got ${typeof arg}`); return arg; } throw new ValidationError(`Unsupported binary behavior "${context2.binary}"`); }; tAny = (arg, path59, context2) => { return arg; }; tOptional = (v) => { return (arg, path59, context2) => { if (Object.is(arg, void 0)) return arg; return v(arg, path59, context2); }; }; tArray = (v) => { return (arg, path59, context2) => { if (!Array.isArray(arg)) throw new ValidationError(`${path59}: expected array, got ${typeof arg}`); return arg.map((x, index) => v(x, path59 + "[" + index + "]", context2)); }; }; tObject = (s) => { return (arg, path59, context2) => { if (Object.is(arg, null)) throw new ValidationError(`${path59}: expected object, got null`); if (typeof arg !== "object") throw new ValidationError(`${path59}: expected object, got ${typeof arg}`); const result2 = {}; for (const [key, v] of Object.entries(s)) { const value2 = v(arg[key], path59 ? path59 + "." + key : key, context2); if (!Object.is(value2, void 0)) result2[key] = value2; } if (context2.isUnderTest()) { for (const [key, value2] of Object.entries(arg)) { if (key.startsWith("__testHook")) result2[key] = value2; } } return result2; }; }; tEnum = (e) => { return (arg, path59, context2) => { if (!e.includes(arg)) throw new ValidationError(`${path59}: expected one of (${e.join("|")})`); return arg; }; }; tChannel = (names) => { return (arg, path59, context2) => { return context2.tChannelImpl(names, arg, path59, context2); }; }; tType = (name) => { return (arg, path59, context2) => { const v = scheme[name]; if (!v) throw new ValidationError(path59 + ': unknown type "' + name + '"'); return v(arg, path59, context2); }; }; } }); // packages/playwright-core/src/protocol/validator.ts var init_validator = __esm({ "packages/playwright-core/src/protocol/validator.ts"() { "use strict"; init_validatorPrimitives(); init_validatorPrimitives(); scheme.AndroidInitializer = tOptional(tObject({})); scheme.AndroidDevicesParams = tObject({ host: tOptional(tString), port: tOptional(tInt), omitDriverInstall: tOptional(tBoolean) }); scheme.AndroidDevicesResult = tObject({ devices: tArray(tChannel(["AndroidDevice"])) }); scheme.AndroidSocketInitializer = tOptional(tObject({})); scheme.AndroidSocketDataEvent = tObject({ data: tBinary }); scheme.AndroidSocketCloseEvent = tOptional(tObject({})); scheme.AndroidSocketWriteParams = tObject({ data: tBinary }); scheme.AndroidSocketWriteResult = tOptional(tObject({})); scheme.AndroidSocketCloseParams = tOptional(tObject({})); scheme.AndroidSocketCloseResult = tOptional(tObject({})); scheme.AndroidDeviceInitializer = tObject({ model: tString, serial: tString }); scheme.AndroidDeviceCloseEvent = tOptional(tObject({})); scheme.AndroidDeviceWebViewAddedEvent = tObject({ webView: tType("AndroidWebView") }); scheme.AndroidDeviceWebViewRemovedEvent = tObject({ socketName: tString }); scheme.AndroidDeviceWaitParams = tObject({ androidSelector: tType("AndroidSelector"), state: tOptional(tEnum(["gone"])), timeout: tFloat }); scheme.AndroidDeviceWaitResult = tOptional(tObject({})); scheme.AndroidDeviceFillParams = tObject({ androidSelector: tType("AndroidSelector"), text: tString, timeout: tFloat }); scheme.AndroidDeviceFillResult = tOptional(tObject({})); scheme.AndroidDeviceTapParams = tObject({ androidSelector: tType("AndroidSelector"), duration: tOptional(tFloat), timeout: tFloat }); scheme.AndroidDeviceTapResult = tOptional(tObject({})); scheme.AndroidDeviceDragParams = tObject({ androidSelector: tType("AndroidSelector"), dest: tType("Point"), speed: tOptional(tFloat), timeout: tFloat }); scheme.AndroidDeviceDragResult = tOptional(tObject({})); scheme.AndroidDeviceFlingParams = tObject({ androidSelector: tType("AndroidSelector"), direction: tEnum(["up", "down", "left", "right"]), speed: tOptional(tFloat), timeout: tFloat }); scheme.AndroidDeviceFlingResult = tOptional(tObject({})); scheme.AndroidDeviceLongTapParams = tObject({ androidSelector: tType("AndroidSelector"), timeout: tFloat }); scheme.AndroidDeviceLongTapResult = tOptional(tObject({})); scheme.AndroidDevicePinchCloseParams = tObject({ androidSelector: tType("AndroidSelector"), percent: tFloat, speed: tOptional(tFloat), timeout: tFloat }); scheme.AndroidDevicePinchCloseResult = tOptional(tObject({})); scheme.AndroidDevicePinchOpenParams = tObject({ androidSelector: tType("AndroidSelector"), percent: tFloat, speed: tOptional(tFloat), timeout: tFloat }); scheme.AndroidDevicePinchOpenResult = tOptional(tObject({})); scheme.AndroidDeviceScrollParams = tObject({ androidSelector: tType("AndroidSelector"), direction: tEnum(["up", "down", "left", "right"]), percent: tFloat, speed: tOptional(tFloat), timeout: tFloat }); scheme.AndroidDeviceScrollResult = tOptional(tObject({})); scheme.AndroidDeviceSwipeParams = tObject({ androidSelector: tType("AndroidSelector"), direction: tEnum(["up", "down", "left", "right"]), percent: tFloat, speed: tOptional(tFloat), timeout: tFloat }); scheme.AndroidDeviceSwipeResult = tOptional(tObject({})); scheme.AndroidDeviceInfoParams = tObject({ androidSelector: tType("AndroidSelector") }); scheme.AndroidDeviceInfoResult = tObject({ info: tType("AndroidElementInfo") }); scheme.AndroidDeviceScreenshotParams = tOptional(tObject({})); scheme.AndroidDeviceScreenshotResult = tObject({ binary: tBinary }); scheme.AndroidDeviceInputTypeParams = tObject({ text: tString }); scheme.AndroidDeviceInputTypeResult = tOptional(tObject({})); scheme.AndroidDeviceInputPressParams = tObject({ key: tString }); scheme.AndroidDeviceInputPressResult = tOptional(tObject({})); scheme.AndroidDeviceInputTapParams = tObject({ point: tType("Point") }); scheme.AndroidDeviceInputTapResult = tOptional(tObject({})); scheme.AndroidDeviceInputSwipeParams = tObject({ segments: tArray(tType("Point")), steps: tInt }); scheme.AndroidDeviceInputSwipeResult = tOptional(tObject({})); scheme.AndroidDeviceInputDragParams = tObject({ from: tType("Point"), to: tType("Point"), steps: tInt }); scheme.AndroidDeviceInputDragResult = tOptional(tObject({})); scheme.AndroidDeviceLaunchBrowserParams = tObject({ noDefaultViewport: tOptional(tBoolean), viewport: tOptional(tObject({ width: tInt, height: tInt })), screen: tOptional(tObject({ width: tInt, height: tInt })), ignoreHTTPSErrors: tOptional(tBoolean), clientCertificates: tOptional(tArray(tObject({ origin: tString, cert: tOptional(tBinary), key: tOptional(tBinary), passphrase: tOptional(tString), pfx: tOptional(tBinary) }))), javaScriptEnabled: tOptional(tBoolean), bypassCSP: tOptional(tBoolean), userAgent: tOptional(tString), locale: tOptional(tString), timezoneId: tOptional(tString), geolocation: tOptional(tObject({ longitude: tFloat, latitude: tFloat, accuracy: tOptional(tFloat) })), permissions: tOptional(tArray(tString)), extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), offline: tOptional(tBoolean), httpCredentials: tOptional(tObject({ username: tString, password: tString, origin: tOptional(tString), send: tOptional(tEnum(["always", "unauthorized"])) })), deviceScaleFactor: tOptional(tFloat), isMobile: tOptional(tBoolean), hasTouch: tOptional(tBoolean), colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), forcedColors: tOptional(tEnum(["active", "none", "no-override"])), acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), contrast: tOptional(tEnum(["no-preference", "more", "no-override"])), baseURL: tOptional(tString), recordVideo: tOptional(tObject({ dir: tOptional(tString), size: tOptional(tObject({ width: tInt, height: tInt })), showActions: tOptional(tObject({ duration: tOptional(tFloat), position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), fontSize: tOptional(tInt), cursor: tOptional(tEnum(["none", "pointer"])) })) })), strictSelectors: tOptional(tBoolean), serviceWorkers: tOptional(tEnum(["allow", "block"])), selectorEngines: tOptional(tArray(tType("SelectorEngine"))), testIdAttributeName: tOptional(tString), pkg: tOptional(tString), args: tOptional(tArray(tString)), proxy: tOptional(tObject({ server: tString, bypass: tOptional(tString), username: tOptional(tString), password: tOptional(tString) })) }); scheme.AndroidDeviceLaunchBrowserResult = tObject({ context: tChannel(["BrowserContext"]) }); scheme.AndroidDeviceOpenParams = tObject({ command: tString }); scheme.AndroidDeviceOpenResult = tObject({ socket: tChannel(["AndroidSocket"]) }); scheme.AndroidDeviceShellParams = tObject({ command: tString }); scheme.AndroidDeviceShellResult = tObject({ result: tBinary }); scheme.AndroidDeviceInstallApkParams = tObject({ file: tBinary, args: tOptional(tArray(tString)) }); scheme.AndroidDeviceInstallApkResult = tOptional(tObject({})); scheme.AndroidDevicePushParams = tObject({ file: tBinary, path: tString, mode: tOptional(tInt) }); scheme.AndroidDevicePushResult = tOptional(tObject({})); scheme.AndroidDeviceConnectToWebViewParams = tObject({ socketName: tString }); scheme.AndroidDeviceConnectToWebViewResult = tObject({ context: tChannel(["BrowserContext"]) }); scheme.AndroidDeviceCloseParams = tOptional(tObject({})); scheme.AndroidDeviceCloseResult = tOptional(tObject({})); scheme.AndroidWebView = tObject({ pid: tInt, pkg: tString, socketName: tString }); scheme.AndroidSelector = tObject({ checkable: tOptional(tBoolean), checked: tOptional(tBoolean), clazz: tOptional(tString), clickable: tOptional(tBoolean), depth: tOptional(tInt), desc: tOptional(tString), enabled: tOptional(tBoolean), focusable: tOptional(tBoolean), focused: tOptional(tBoolean), hasChild: tOptional(tObject({ androidSelector: tType("AndroidSelector") })), hasDescendant: tOptional(tObject({ androidSelector: tType("AndroidSelector"), maxDepth: tOptional(tInt) })), longClickable: tOptional(tBoolean), pkg: tOptional(tString), res: tOptional(tString), scrollable: tOptional(tBoolean), selected: tOptional(tBoolean), text: tOptional(tString) }); scheme.AndroidElementInfo = tObject({ children: tOptional(tArray(tType("AndroidElementInfo"))), clazz: tString, desc: tString, res: tString, pkg: tString, text: tString, bounds: tType("Rect"), checkable: tBoolean, checked: tBoolean, clickable: tBoolean, enabled: tBoolean, focusable: tBoolean, focused: tBoolean, longClickable: tBoolean, scrollable: tBoolean, selected: tBoolean }); scheme.APIRequestContextInitializer = tObject({ tracing: tChannel(["Tracing"]) }); scheme.APIRequestContextFetchParams = tObject({ url: tString, encodedParams: tOptional(tString), params: tOptional(tArray(tType("NameValue"))), method: tOptional(tString), headers: tOptional(tArray(tType("NameValue"))), postData: tOptional(tBinary), jsonData: tOptional(tString), formData: tOptional(tArray(tType("NameValue"))), multipartData: tOptional(tArray(tType("FormField"))), timeout: tFloat, failOnStatusCode: tOptional(tBoolean), ignoreHTTPSErrors: tOptional(tBoolean), maxRedirects: tOptional(tInt), maxRetries: tOptional(tInt) }); scheme.APIRequestContextFetchResult = tObject({ response: tType("APIResponse") }); scheme.APIRequestContextFetchResponseBodyParams = tObject({ fetchUid: tString }); scheme.APIRequestContextFetchResponseBodyResult = tObject({ binary: tOptional(tBinary) }); scheme.APIRequestContextFetchLogParams = tObject({ fetchUid: tString }); scheme.APIRequestContextFetchLogResult = tObject({ log: tArray(tString) }); scheme.APIRequestContextStorageStateParams = tObject({ indexedDB: tOptional(tBoolean) }); scheme.APIRequestContextStorageStateResult = tObject({ cookies: tArray(tType("NetworkCookie")), origins: tArray(tType("OriginStorage")) }); scheme.APIRequestContextDisposeAPIResponseParams = tObject({ fetchUid: tString }); scheme.APIRequestContextDisposeAPIResponseResult = tOptional(tObject({})); scheme.APIRequestContextDisposeParams = tObject({ reason: tOptional(tString) }); scheme.APIRequestContextDisposeResult = tOptional(tObject({})); scheme.APIResponse = tObject({ fetchUid: tString, url: tString, status: tInt, statusText: tString, headers: tArray(tType("NameValue")), securityDetails: tOptional(tType("SecurityDetails")), serverAddr: tOptional(tType("RemoteAddr")) }); scheme.ArtifactInitializer = tObject({ absolutePath: tString }); scheme.ArtifactPathAfterFinishedParams = tOptional(tObject({})); scheme.ArtifactPathAfterFinishedResult = tObject({ value: tString }); scheme.ArtifactSaveAsParams = tObject({ path: tString }); scheme.ArtifactSaveAsResult = tOptional(tObject({})); scheme.ArtifactSaveAsStreamParams = tOptional(tObject({})); scheme.ArtifactSaveAsStreamResult = tObject({ stream: tChannel(["Stream"]) }); scheme.ArtifactFailureParams = tOptional(tObject({})); scheme.ArtifactFailureResult = tObject({ error: tOptional(tString) }); scheme.ArtifactStreamParams = tOptional(tObject({})); scheme.ArtifactStreamResult = tObject({ stream: tChannel(["Stream"]) }); scheme.ArtifactCancelParams = tOptional(tObject({})); scheme.ArtifactCancelResult = tOptional(tObject({})); scheme.ArtifactDeleteParams = tOptional(tObject({})); scheme.ArtifactDeleteResult = tOptional(tObject({})); scheme.StreamInitializer = tOptional(tObject({})); scheme.StreamReadParams = tObject({ size: tOptional(tInt) }); scheme.StreamReadResult = tObject({ binary: tBinary }); scheme.StreamCloseParams = tOptional(tObject({})); scheme.StreamCloseResult = tOptional(tObject({})); scheme.WritableStreamInitializer = tOptional(tObject({})); scheme.WritableStreamWriteParams = tObject({ binary: tBinary }); scheme.WritableStreamWriteResult = tOptional(tObject({})); scheme.WritableStreamCloseParams = tOptional(tObject({})); scheme.WritableStreamCloseResult = tOptional(tObject({})); scheme.BrowserInitializer = tObject({ version: tString, name: tString, browserName: tEnum(["chromium", "firefox", "webkit"]) }); scheme.BrowserContextEvent = tObject({ context: tChannel(["BrowserContext"]) }); scheme.BrowserCloseEvent = tOptional(tObject({})); scheme.BrowserStartServerParams = tObject({ title: tString, workspaceDir: tOptional(tString), metadata: tOptional(tAny), host: tOptional(tString), port: tOptional(tInt) }); scheme.BrowserStartServerResult = tObject({ endpoint: tString }); scheme.BrowserStopServerParams = tOptional(tObject({})); scheme.BrowserStopServerResult = tOptional(tObject({})); scheme.BrowserCloseParams = tObject({ reason: tOptional(tString) }); scheme.BrowserCloseResult = tOptional(tObject({})); scheme.BrowserKillForTestsParams = tOptional(tObject({})); scheme.BrowserKillForTestsResult = tOptional(tObject({})); scheme.BrowserDefaultUserAgentForTestParams = tOptional(tObject({})); scheme.BrowserDefaultUserAgentForTestResult = tObject({ userAgent: tString }); scheme.BrowserNewContextParams = tObject({ noDefaultViewport: tOptional(tBoolean), viewport: tOptional(tObject({ width: tInt, height: tInt })), screen: tOptional(tObject({ width: tInt, height: tInt })), ignoreHTTPSErrors: tOptional(tBoolean), clientCertificates: tOptional(tArray(tObject({ origin: tString, cert: tOptional(tBinary), key: tOptional(tBinary), passphrase: tOptional(tString), pfx: tOptional(tBinary) }))), javaScriptEnabled: tOptional(tBoolean), bypassCSP: tOptional(tBoolean), userAgent: tOptional(tString), locale: tOptional(tString), timezoneId: tOptional(tString), geolocation: tOptional(tObject({ longitude: tFloat, latitude: tFloat, accuracy: tOptional(tFloat) })), permissions: tOptional(tArray(tString)), extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), offline: tOptional(tBoolean), httpCredentials: tOptional(tObject({ username: tString, password: tString, origin: tOptional(tString), send: tOptional(tEnum(["always", "unauthorized"])) })), deviceScaleFactor: tOptional(tFloat), isMobile: tOptional(tBoolean), hasTouch: tOptional(tBoolean), colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), forcedColors: tOptional(tEnum(["active", "none", "no-override"])), acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), contrast: tOptional(tEnum(["no-preference", "more", "no-override"])), baseURL: tOptional(tString), recordVideo: tOptional(tObject({ dir: tOptional(tString), size: tOptional(tObject({ width: tInt, height: tInt })), showActions: tOptional(tObject({ duration: tOptional(tFloat), position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), fontSize: tOptional(tInt), cursor: tOptional(tEnum(["none", "pointer"])) })) })), strictSelectors: tOptional(tBoolean), serviceWorkers: tOptional(tEnum(["allow", "block"])), selectorEngines: tOptional(tArray(tType("SelectorEngine"))), testIdAttributeName: tOptional(tString), proxy: tOptional(tObject({ server: tString, bypass: tOptional(tString), username: tOptional(tString), password: tOptional(tString) })), storageState: tOptional(tObject({ cookies: tOptional(tArray(tType("SetNetworkCookie"))), origins: tOptional(tArray(tType("SetOriginStorage"))) })) }); scheme.BrowserNewContextResult = tObject({ context: tChannel(["BrowserContext"]) }); scheme.BrowserNewContextForReuseParams = tObject({ noDefaultViewport: tOptional(tBoolean), viewport: tOptional(tObject({ width: tInt, height: tInt })), screen: tOptional(tObject({ width: tInt, height: tInt })), ignoreHTTPSErrors: tOptional(tBoolean), clientCertificates: tOptional(tArray(tObject({ origin: tString, cert: tOptional(tBinary), key: tOptional(tBinary), passphrase: tOptional(tString), pfx: tOptional(tBinary) }))), javaScriptEnabled: tOptional(tBoolean), bypassCSP: tOptional(tBoolean), userAgent: tOptional(tString), locale: tOptional(tString), timezoneId: tOptional(tString), geolocation: tOptional(tObject({ longitude: tFloat, latitude: tFloat, accuracy: tOptional(tFloat) })), permissions: tOptional(tArray(tString)), extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), offline: tOptional(tBoolean), httpCredentials: tOptional(tObject({ username: tString, password: tString, origin: tOptional(tString), send: tOptional(tEnum(["always", "unauthorized"])) })), deviceScaleFactor: tOptional(tFloat), isMobile: tOptional(tBoolean), hasTouch: tOptional(tBoolean), colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), forcedColors: tOptional(tEnum(["active", "none", "no-override"])), acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), contrast: tOptional(tEnum(["no-preference", "more", "no-override"])), baseURL: tOptional(tString), recordVideo: tOptional(tObject({ dir: tOptional(tString), size: tOptional(tObject({ width: tInt, height: tInt })), showActions: tOptional(tObject({ duration: tOptional(tFloat), position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), fontSize: tOptional(tInt), cursor: tOptional(tEnum(["none", "pointer"])) })) })), strictSelectors: tOptional(tBoolean), serviceWorkers: tOptional(tEnum(["allow", "block"])), selectorEngines: tOptional(tArray(tType("SelectorEngine"))), testIdAttributeName: tOptional(tString), proxy: tOptional(tObject({ server: tString, bypass: tOptional(tString), username: tOptional(tString), password: tOptional(tString) })), storageState: tOptional(tObject({ cookies: tOptional(tArray(tType("SetNetworkCookie"))), origins: tOptional(tArray(tType("SetOriginStorage"))) })) }); scheme.BrowserNewContextForReuseResult = tObject({ context: tChannel(["BrowserContext"]) }); scheme.BrowserDisconnectFromReusedContextParams = tObject({ reason: tString }); scheme.BrowserDisconnectFromReusedContextResult = tOptional(tObject({})); scheme.BrowserNewBrowserCDPSessionParams = tOptional(tObject({})); scheme.BrowserNewBrowserCDPSessionResult = tObject({ session: tChannel(["CDPSession"]) }); scheme.BrowserStartTracingParams = tObject({ page: tOptional(tChannel(["Page"])), screenshots: tOptional(tBoolean), categories: tOptional(tArray(tString)) }); scheme.BrowserStartTracingResult = tOptional(tObject({})); scheme.BrowserStopTracingParams = tOptional(tObject({})); scheme.BrowserStopTracingResult = tObject({ artifact: tChannel(["Artifact"]) }); scheme.BrowserContextInitializer = tObject({ debugger: tChannel(["Debugger"]), requestContext: tChannel(["APIRequestContext"]), tracing: tChannel(["Tracing"]), options: tObject({ noDefaultViewport: tOptional(tBoolean), viewport: tOptional(tObject({ width: tInt, height: tInt })), screen: tOptional(tObject({ width: tInt, height: tInt })), ignoreHTTPSErrors: tOptional(tBoolean), clientCertificates: tOptional(tArray(tObject({ origin: tString, cert: tOptional(tBinary), key: tOptional(tBinary), passphrase: tOptional(tString), pfx: tOptional(tBinary) }))), javaScriptEnabled: tOptional(tBoolean), bypassCSP: tOptional(tBoolean), userAgent: tOptional(tString), locale: tOptional(tString), timezoneId: tOptional(tString), geolocation: tOptional(tObject({ longitude: tFloat, latitude: tFloat, accuracy: tOptional(tFloat) })), permissions: tOptional(tArray(tString)), extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), offline: tOptional(tBoolean), httpCredentials: tOptional(tObject({ username: tString, password: tString, origin: tOptional(tString), send: tOptional(tEnum(["always", "unauthorized"])) })), deviceScaleFactor: tOptional(tFloat), isMobile: tOptional(tBoolean), hasTouch: tOptional(tBoolean), colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), forcedColors: tOptional(tEnum(["active", "none", "no-override"])), acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), contrast: tOptional(tEnum(["no-preference", "more", "no-override"])), baseURL: tOptional(tString), recordVideo: tOptional(tObject({ dir: tOptional(tString), size: tOptional(tObject({ width: tInt, height: tInt })), showActions: tOptional(tObject({ duration: tOptional(tFloat), position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), fontSize: tOptional(tInt), cursor: tOptional(tEnum(["none", "pointer"])) })) })), strictSelectors: tOptional(tBoolean), serviceWorkers: tOptional(tEnum(["allow", "block"])), selectorEngines: tOptional(tArray(tType("SelectorEngine"))), testIdAttributeName: tOptional(tString) }) }); scheme.BrowserContextBindingCallEvent = tObject({ binding: tChannel(["BindingCall"]) }); scheme.BrowserContextConsoleEvent = tObject({ type: tString, text: tString, args: tArray(tChannel(["ElementHandle", "JSHandle"])), location: tObject({ url: tString, lineNumber: tInt, columnNumber: tInt }), timestamp: tFloat, page: tOptional(tChannel(["Page"])), worker: tOptional(tChannel(["Worker"])) }); scheme.BrowserContextCloseEvent = tOptional(tObject({})); scheme.BrowserContextDialogEvent = tObject({ dialog: tChannel(["Dialog"]) }); scheme.BrowserContextPageEvent = tObject({ page: tChannel(["Page"]) }); scheme.BrowserContextPageErrorEvent = tObject({ error: tType("SerializedError"), page: tChannel(["Page"]), location: tObject({ url: tString, line: tInt, column: tInt }) }); scheme.BrowserContextRouteEvent = tObject({ route: tChannel(["Route"]) }); scheme.BrowserContextWebSocketRouteEvent = tObject({ webSocketRoute: tChannel(["WebSocketRoute"]) }); scheme.BrowserContextServiceWorkerEvent = tObject({ worker: tChannel(["Worker"]) }); scheme.BrowserContextRequestEvent = tObject({ request: tChannel(["Request"]), page: tOptional(tChannel(["Page"])) }); scheme.BrowserContextRequestFailedEvent = tObject({ request: tChannel(["Request"]), failureText: tOptional(tString), responseEndTiming: tFloat, page: tOptional(tChannel(["Page"])) }); scheme.BrowserContextRequestFinishedEvent = tObject({ request: tChannel(["Request"]), response: tOptional(tChannel(["Response"])), responseEndTiming: tFloat, page: tOptional(tChannel(["Page"])) }); scheme.BrowserContextResponseEvent = tObject({ response: tChannel(["Response"]), page: tOptional(tChannel(["Page"])) }); scheme.BrowserContextRecorderEventEvent = tObject({ event: tEnum(["actionAdded", "actionUpdated", "signalAdded"]), data: tAny, page: tChannel(["Page"]), code: tString }); scheme.BrowserContextAddCookiesParams = tObject({ cookies: tArray(tType("SetNetworkCookie")) }); scheme.BrowserContextAddCookiesResult = tOptional(tObject({})); scheme.BrowserContextAddInitScriptParams = tObject({ source: tString }); scheme.BrowserContextAddInitScriptResult = tObject({ disposable: tChannel(["Disposable"]) }); scheme.BrowserContextClearCookiesParams = tObject({ name: tOptional(tString), nameRegexSource: tOptional(tString), nameRegexFlags: tOptional(tString), domain: tOptional(tString), domainRegexSource: tOptional(tString), domainRegexFlags: tOptional(tString), path: tOptional(tString), pathRegexSource: tOptional(tString), pathRegexFlags: tOptional(tString) }); scheme.BrowserContextClearCookiesResult = tOptional(tObject({})); scheme.BrowserContextClearPermissionsParams = tOptional(tObject({})); scheme.BrowserContextClearPermissionsResult = tOptional(tObject({})); scheme.BrowserContextCloseParams = tObject({ reason: tOptional(tString) }); scheme.BrowserContextCloseResult = tOptional(tObject({})); scheme.BrowserContextCookiesParams = tObject({ urls: tArray(tString) }); scheme.BrowserContextCookiesResult = tObject({ cookies: tArray(tType("NetworkCookie")) }); scheme.BrowserContextExposeBindingParams = tObject({ name: tString }); scheme.BrowserContextExposeBindingResult = tObject({ disposable: tChannel(["Disposable"]) }); scheme.BrowserContextGrantPermissionsParams = tObject({ permissions: tArray(tString), origin: tOptional(tString) }); scheme.BrowserContextGrantPermissionsResult = tOptional(tObject({})); scheme.BrowserContextNewPageParams = tOptional(tObject({})); scheme.BrowserContextNewPageResult = tObject({ page: tChannel(["Page"]) }); scheme.BrowserContextRegisterSelectorEngineParams = tObject({ selectorEngine: tType("SelectorEngine") }); scheme.BrowserContextRegisterSelectorEngineResult = tOptional(tObject({})); scheme.BrowserContextSetTestIdAttributeNameParams = tObject({ testIdAttributeName: tString }); scheme.BrowserContextSetTestIdAttributeNameResult = tOptional(tObject({})); scheme.BrowserContextSetExtraHTTPHeadersParams = tObject({ headers: tArray(tType("NameValue")) }); scheme.BrowserContextSetExtraHTTPHeadersResult = tOptional(tObject({})); scheme.BrowserContextSetGeolocationParams = tObject({ geolocation: tOptional(tObject({ longitude: tFloat, latitude: tFloat, accuracy: tOptional(tFloat) })) }); scheme.BrowserContextSetGeolocationResult = tOptional(tObject({})); scheme.BrowserContextSetHTTPCredentialsParams = tObject({ httpCredentials: tOptional(tObject({ username: tString, password: tString, origin: tOptional(tString) })) }); scheme.BrowserContextSetHTTPCredentialsResult = tOptional(tObject({})); scheme.BrowserContextSetNetworkInterceptionPatternsParams = tObject({ patterns: tArray(tObject({ glob: tOptional(tString), regexSource: tOptional(tString), regexFlags: tOptional(tString), urlPattern: tOptional(tType("URLPattern")) })) }); scheme.BrowserContextSetNetworkInterceptionPatternsResult = tOptional(tObject({})); scheme.BrowserContextSetWebSocketInterceptionPatternsParams = tObject({ patterns: tArray(tObject({ glob: tOptional(tString), regexSource: tOptional(tString), regexFlags: tOptional(tString), urlPattern: tOptional(tType("URLPattern")) })) }); scheme.BrowserContextSetWebSocketInterceptionPatternsResult = tOptional(tObject({})); scheme.BrowserContextSetOfflineParams = tObject({ offline: tBoolean }); scheme.BrowserContextSetOfflineResult = tOptional(tObject({})); scheme.BrowserContextStorageStateParams = tObject({ indexedDB: tOptional(tBoolean) }); scheme.BrowserContextStorageStateResult = tObject({ cookies: tArray(tType("NetworkCookie")), origins: tArray(tType("OriginStorage")) }); scheme.BrowserContextSetStorageStateParams = tObject({ storageState: tOptional(tObject({ cookies: tOptional(tArray(tType("SetNetworkCookie"))), origins: tOptional(tArray(tType("SetOriginStorage"))) })) }); scheme.BrowserContextSetStorageStateResult = tOptional(tObject({})); scheme.BrowserContextPauseParams = tOptional(tObject({})); scheme.BrowserContextPauseResult = tOptional(tObject({})); scheme.BrowserContextEnableRecorderParams = tObject({ language: tOptional(tString), mode: tOptional(tEnum(["inspecting", "recording"])), recorderMode: tOptional(tEnum(["default", "api"])), pauseOnNextStatement: tOptional(tBoolean), testIdAttributeName: tOptional(tString), launchOptions: tOptional(tAny), contextOptions: tOptional(tAny), device: tOptional(tString), saveStorage: tOptional(tString), outputFile: tOptional(tString), handleSIGINT: tOptional(tBoolean), omitCallTracking: tOptional(tBoolean) }); scheme.BrowserContextEnableRecorderResult = tOptional(tObject({})); scheme.BrowserContextDisableRecorderParams = tOptional(tObject({})); scheme.BrowserContextDisableRecorderResult = tOptional(tObject({})); scheme.BrowserContextExposeConsoleApiParams = tOptional(tObject({})); scheme.BrowserContextExposeConsoleApiResult = tOptional(tObject({})); scheme.BrowserContextNewCDPSessionParams = tObject({ page: tOptional(tChannel(["Page"])), frame: tOptional(tChannel(["Frame"])) }); scheme.BrowserContextNewCDPSessionResult = tObject({ session: tChannel(["CDPSession"]) }); scheme.BrowserContextCreateTempFilesParams = tObject({ rootDirName: tOptional(tString), items: tArray(tObject({ name: tString, lastModifiedMs: tOptional(tFloat) })) }); scheme.BrowserContextCreateTempFilesResult = tObject({ rootDir: tOptional(tChannel(["WritableStream"])), writableStreams: tArray(tChannel(["WritableStream"])) }); scheme.BrowserContextUpdateSubscriptionParams = tObject({ event: tEnum(["console", "dialog", "request", "response", "requestFinished", "requestFailed"]), enabled: tBoolean }); scheme.BrowserContextUpdateSubscriptionResult = tOptional(tObject({})); scheme.BrowserContextClockFastForwardParams = tObject({ ticksNumber: tOptional(tFloat), ticksString: tOptional(tString) }); scheme.BrowserContextClockFastForwardResult = tOptional(tObject({})); scheme.BrowserContextClockInstallParams = tObject({ timeNumber: tOptional(tFloat), timeString: tOptional(tString) }); scheme.BrowserContextClockInstallResult = tOptional(tObject({})); scheme.BrowserContextClockPauseAtParams = tObject({ timeNumber: tOptional(tFloat), timeString: tOptional(tString) }); scheme.BrowserContextClockPauseAtResult = tOptional(tObject({})); scheme.BrowserContextClockResumeParams = tOptional(tObject({})); scheme.BrowserContextClockResumeResult = tOptional(tObject({})); scheme.BrowserContextClockRunForParams = tObject({ ticksNumber: tOptional(tFloat), ticksString: tOptional(tString) }); scheme.BrowserContextClockRunForResult = tOptional(tObject({})); scheme.BrowserContextClockSetFixedTimeParams = tObject({ timeNumber: tOptional(tFloat), timeString: tOptional(tString) }); scheme.BrowserContextClockSetFixedTimeResult = tOptional(tObject({})); scheme.BrowserContextClockSetSystemTimeParams = tObject({ timeNumber: tOptional(tFloat), timeString: tOptional(tString) }); scheme.BrowserContextClockSetSystemTimeResult = tOptional(tObject({})); scheme.BrowserContextCredentialsInstallParams = tOptional(tObject({})); scheme.BrowserContextCredentialsInstallResult = tOptional(tObject({})); scheme.BrowserContextCredentialsCreateParams = tObject({ rpId: tString, id: tOptional(tString), userHandle: tOptional(tString), privateKey: tOptional(tString), publicKey: tOptional(tString) }); scheme.BrowserContextCredentialsCreateResult = tObject({ credential: tType("VirtualCredential") }); scheme.BrowserContextCredentialsGetParams = tObject({ rpId: tOptional(tString), id: tOptional(tString) }); scheme.BrowserContextCredentialsGetResult = tObject({ credentials: tArray(tType("VirtualCredential")) }); scheme.BrowserContextCredentialsDeleteParams = tObject({ id: tString }); scheme.BrowserContextCredentialsDeleteResult = tOptional(tObject({})); scheme.BrowserTypeInitializer = tObject({ executablePath: tString, name: tString }); scheme.BrowserTypeLaunchParams = tObject({ channel: tOptional(tString), executablePath: tOptional(tString), args: tOptional(tArray(tString)), ignoreAllDefaultArgs: tOptional(tBoolean), ignoreDefaultArgs: tOptional(tArray(tString)), handleSIGINT: tOptional(tBoolean), handleSIGTERM: tOptional(tBoolean), handleSIGHUP: tOptional(tBoolean), timeout: tFloat, env: tOptional(tArray(tType("NameValue"))), headless: tOptional(tBoolean), proxy: tOptional(tObject({ server: tString, bypass: tOptional(tString), username: tOptional(tString), password: tOptional(tString) })), downloadsPath: tOptional(tString), tracesDir: tOptional(tString), artifactsDir: tOptional(tString), chromiumSandbox: tOptional(tBoolean), firefoxUserPrefs: tOptional(tAny), cdpPort: tOptional(tInt), slowMo: tOptional(tFloat) }); scheme.BrowserTypeLaunchResult = tObject({ browser: tChannel(["Browser"]) }); scheme.BrowserTypeLaunchPersistentContextParams = tObject({ channel: tOptional(tString), executablePath: tOptional(tString), args: tOptional(tArray(tString)), ignoreAllDefaultArgs: tOptional(tBoolean), ignoreDefaultArgs: tOptional(tArray(tString)), handleSIGINT: tOptional(tBoolean), handleSIGTERM: tOptional(tBoolean), handleSIGHUP: tOptional(tBoolean), timeout: tFloat, env: tOptional(tArray(tType("NameValue"))), headless: tOptional(tBoolean), proxy: tOptional(tObject({ server: tString, bypass: tOptional(tString), username: tOptional(tString), password: tOptional(tString) })), downloadsPath: tOptional(tString), tracesDir: tOptional(tString), artifactsDir: tOptional(tString), chromiumSandbox: tOptional(tBoolean), firefoxUserPrefs: tOptional(tAny), cdpPort: tOptional(tInt), noDefaultViewport: tOptional(tBoolean), viewport: tOptional(tObject({ width: tInt, height: tInt })), screen: tOptional(tObject({ width: tInt, height: tInt })), ignoreHTTPSErrors: tOptional(tBoolean), clientCertificates: tOptional(tArray(tObject({ origin: tString, cert: tOptional(tBinary), key: tOptional(tBinary), passphrase: tOptional(tString), pfx: tOptional(tBinary) }))), javaScriptEnabled: tOptional(tBoolean), bypassCSP: tOptional(tBoolean), userAgent: tOptional(tString), locale: tOptional(tString), timezoneId: tOptional(tString), geolocation: tOptional(tObject({ longitude: tFloat, latitude: tFloat, accuracy: tOptional(tFloat) })), permissions: tOptional(tArray(tString)), extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), offline: tOptional(tBoolean), httpCredentials: tOptional(tObject({ username: tString, password: tString, origin: tOptional(tString), send: tOptional(tEnum(["always", "unauthorized"])) })), deviceScaleFactor: tOptional(tFloat), isMobile: tOptional(tBoolean), hasTouch: tOptional(tBoolean), colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), forcedColors: tOptional(tEnum(["active", "none", "no-override"])), acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), contrast: tOptional(tEnum(["no-preference", "more", "no-override"])), baseURL: tOptional(tString), recordVideo: tOptional(tObject({ dir: tOptional(tString), size: tOptional(tObject({ width: tInt, height: tInt })), showActions: tOptional(tObject({ duration: tOptional(tFloat), position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), fontSize: tOptional(tInt), cursor: tOptional(tEnum(["none", "pointer"])) })) })), strictSelectors: tOptional(tBoolean), serviceWorkers: tOptional(tEnum(["allow", "block"])), selectorEngines: tOptional(tArray(tType("SelectorEngine"))), testIdAttributeName: tOptional(tString), userDataDir: tString, slowMo: tOptional(tFloat) }); scheme.BrowserTypeLaunchPersistentContextResult = tObject({ browser: tChannel(["Browser"]), context: tChannel(["BrowserContext"]) }); scheme.BrowserTypeConnectOverCDPParams = tObject({ endpointURL: tOptional(tString), headers: tOptional(tArray(tType("NameValue"))), slowMo: tOptional(tFloat), timeout: tFloat, isLocal: tOptional(tBoolean), noDefaults: tOptional(tBoolean), artifactsDir: tOptional(tString), transport: tOptional(tBinary) }); scheme.BrowserTypeConnectOverCDPResult = tObject({ browser: tChannel(["Browser"]), defaultContext: tOptional(tChannel(["BrowserContext"])) }); scheme.BrowserTypeConnectToWorkerParams = tObject({ endpoint: tString, timeout: tFloat }); scheme.BrowserTypeConnectToWorkerResult = tObject({ worker: tChannel(["Worker"]) }); scheme.Metadata = tObject({ location: tOptional(tObject({ file: tString, line: tOptional(tInt), column: tOptional(tInt) })), title: tOptional(tString), internal: tOptional(tBoolean), stepId: tOptional(tString) }); scheme.ClientSideCallMetadata = tObject({ id: tInt, stack: tOptional(tArray(tType("StackFrame"))) }); scheme.SDKLanguage = tEnum(["javascript", "python", "java", "csharp"]); scheme.DisposableInitializer = tOptional(tObject({})); scheme.DisposableDisposeParams = tOptional(tObject({})); scheme.DisposableDisposeResult = tOptional(tObject({})); scheme.WaitInfo = tObject({ waitId: tString, phase: tEnum(["before", "after", "log"]), event: tOptional(tString), message: tOptional(tString), error: tOptional(tString) }); scheme.ElectronInitializer = tOptional(tObject({})); scheme.ElectronLaunchParams = tObject({ executablePath: tOptional(tString), args: tOptional(tArray(tString)), chromiumSandbox: tOptional(tBoolean), cwd: tOptional(tString), env: tOptional(tArray(tType("NameValue"))), timeout: tFloat, acceptDownloads: tOptional(tEnum(["accept", "deny", "internal-browser-default"])), bypassCSP: tOptional(tBoolean), colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), geolocation: tOptional(tObject({ longitude: tFloat, latitude: tFloat, accuracy: tOptional(tFloat) })), httpCredentials: tOptional(tObject({ username: tString, password: tString, origin: tOptional(tString) })), ignoreHTTPSErrors: tOptional(tBoolean), locale: tOptional(tString), offline: tOptional(tBoolean), recordVideo: tOptional(tObject({ dir: tOptional(tString), size: tOptional(tObject({ width: tInt, height: tInt })), showActions: tOptional(tObject({ duration: tOptional(tFloat), position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), fontSize: tOptional(tInt), cursor: tOptional(tEnum(["none", "pointer"])) })) })), strictSelectors: tOptional(tBoolean), timezoneId: tOptional(tString), tracesDir: tOptional(tString), artifactsDir: tOptional(tString), selectorEngines: tOptional(tArray(tType("SelectorEngine"))), testIdAttributeName: tOptional(tString) }); scheme.ElectronLaunchResult = tObject({ electronApplication: tChannel(["ElectronApplication"]) }); scheme.ElectronApplicationInitializer = tObject({ context: tChannel(["BrowserContext"]) }); scheme.ElectronApplicationCloseEvent = tOptional(tObject({})); scheme.ElectronApplicationConsoleEvent = tObject({ type: tString, text: tString, args: tArray(tChannel(["ElementHandle", "JSHandle"])), location: tObject({ url: tString, lineNumber: tInt, columnNumber: tInt }), timestamp: tFloat }); scheme.ElectronApplicationBrowserWindowParams = tObject({ page: tChannel(["Page"]) }); scheme.ElectronApplicationBrowserWindowResult = tObject({ handle: tChannel(["ElementHandle", "JSHandle"]) }); scheme.ElectronApplicationEvaluateExpressionParams = tObject({ expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.ElectronApplicationEvaluateExpressionResult = tObject({ value: tType("SerializedValue") }); scheme.ElectronApplicationEvaluateExpressionHandleParams = tObject({ expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.ElectronApplicationEvaluateExpressionHandleResult = tObject({ handle: tChannel(["ElementHandle", "JSHandle"]) }); scheme.ElectronApplicationUpdateSubscriptionParams = tObject({ event: tEnum(["console"]), enabled: tBoolean }); scheme.ElectronApplicationUpdateSubscriptionResult = tOptional(tObject({})); scheme.FrameInitializer = tObject({ url: tString, name: tString, parentFrame: tOptional(tChannel(["Frame"])), loadStates: tArray(tType("LifecycleEvent")) }); scheme.FrameLoadstateEvent = tObject({ add: tOptional(tType("LifecycleEvent")), remove: tOptional(tType("LifecycleEvent")) }); scheme.FrameNavigatedEvent = tObject({ url: tString, name: tString, newDocument: tOptional(tObject({ request: tOptional(tChannel(["Request"])) })), error: tOptional(tString) }); scheme.FrameEvalOnSelectorParams = tObject({ selector: tString, strict: tOptional(tBoolean), expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.FrameEvalOnSelectorResult = tObject({ value: tType("SerializedValue") }); scheme.FrameEvalOnSelectorAllParams = tObject({ selector: tString, expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.FrameEvalOnSelectorAllResult = tObject({ value: tType("SerializedValue") }); scheme.FrameAddScriptTagParams = tObject({ url: tOptional(tString), content: tOptional(tString), type: tOptional(tString) }); scheme.FrameAddScriptTagResult = tObject({ element: tChannel(["ElementHandle"]) }); scheme.FrameAddStyleTagParams = tObject({ url: tOptional(tString), content: tOptional(tString) }); scheme.FrameAddStyleTagResult = tObject({ element: tChannel(["ElementHandle"]) }); scheme.FrameAriaSnapshotParams = tObject({ mode: tOptional(tEnum(["ai", "default"])), track: tOptional(tString), selector: tOptional(tString), depth: tOptional(tInt), boxes: tOptional(tBoolean), timeout: tFloat }); scheme.FrameAriaSnapshotResult = tObject({ snapshot: tString }); scheme.FrameBlurParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat }); scheme.FrameBlurResult = tOptional(tObject({})); scheme.FrameCheckParams = tObject({ selector: tString, strict: tOptional(tBoolean), force: tOptional(tBoolean), position: tOptional(tType("Point")), timeout: tFloat, trial: tOptional(tBoolean) }); scheme.FrameCheckResult = tOptional(tObject({})); scheme.FrameClickParams = tObject({ selector: tString, strict: tOptional(tBoolean), force: tOptional(tBoolean), noWaitAfter: tOptional(tBoolean), modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), position: tOptional(tType("Point")), delay: tOptional(tFloat), button: tOptional(tEnum(["left", "right", "middle"])), clickCount: tOptional(tInt), timeout: tFloat, trial: tOptional(tBoolean), steps: tOptional(tInt) }); scheme.FrameClickResult = tOptional(tObject({})); scheme.FrameContentParams = tOptional(tObject({})); scheme.FrameContentResult = tObject({ value: tString }); scheme.FrameDragAndDropParams = tObject({ source: tString, target: tString, force: tOptional(tBoolean), timeout: tFloat, trial: tOptional(tBoolean), sourcePosition: tOptional(tType("Point")), targetPosition: tOptional(tType("Point")), strict: tOptional(tBoolean), steps: tOptional(tInt) }); scheme.FrameDragAndDropResult = tOptional(tObject({})); scheme.FrameDropParams = tObject({ selector: tString, strict: tOptional(tBoolean), position: tOptional(tType("Point")), payloads: tOptional(tArray(tObject({ name: tString, mimeType: tOptional(tString), buffer: tBinary }))), localPaths: tOptional(tArray(tString)), streams: tOptional(tArray(tChannel(["WritableStream"]))), data: tOptional(tArray(tObject({ mimeType: tString, value: tString }))), timeout: tFloat }); scheme.FrameDropResult = tOptional(tObject({})); scheme.FrameDblclickParams = tObject({ selector: tString, strict: tOptional(tBoolean), force: tOptional(tBoolean), modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), position: tOptional(tType("Point")), delay: tOptional(tFloat), button: tOptional(tEnum(["left", "right", "middle"])), timeout: tFloat, trial: tOptional(tBoolean), steps: tOptional(tInt) }); scheme.FrameDblclickResult = tOptional(tObject({})); scheme.FrameDispatchEventParams = tObject({ selector: tString, strict: tOptional(tBoolean), type: tString, eventInit: tType("SerializedArgument"), timeout: tFloat }); scheme.FrameDispatchEventResult = tOptional(tObject({})); scheme.FrameEvaluateExpressionParams = tObject({ expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.FrameEvaluateExpressionResult = tObject({ value: tType("SerializedValue") }); scheme.FrameEvaluateExpressionHandleParams = tObject({ expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.FrameEvaluateExpressionHandleResult = tObject({ handle: tChannel(["ElementHandle", "JSHandle"]) }); scheme.FrameFillParams = tObject({ selector: tString, strict: tOptional(tBoolean), value: tString, force: tOptional(tBoolean), timeout: tFloat }); scheme.FrameFillResult = tOptional(tObject({})); scheme.FrameFocusParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat }); scheme.FrameFocusResult = tOptional(tObject({})); scheme.FrameFrameElementParams = tOptional(tObject({})); scheme.FrameFrameElementResult = tObject({ element: tChannel(["ElementHandle"]) }); scheme.FrameResolveSelectorParams = tObject({ selector: tString }); scheme.FrameResolveSelectorResult = tObject({ resolvedSelector: tString }); scheme.FrameHighlightParams = tObject({ selector: tString, style: tOptional(tString) }); scheme.FrameHighlightResult = tOptional(tObject({})); scheme.FrameHideHighlightParams = tObject({ selector: tString }); scheme.FrameHideHighlightResult = tOptional(tObject({})); scheme.FrameGetAttributeParams = tObject({ selector: tString, strict: tOptional(tBoolean), name: tString, timeout: tFloat }); scheme.FrameGetAttributeResult = tObject({ value: tOptional(tString) }); scheme.FrameGotoParams = tObject({ url: tString, timeout: tFloat, waitUntil: tOptional(tType("LifecycleEvent")), referer: tOptional(tString) }); scheme.FrameGotoResult = tObject({ response: tOptional(tChannel(["Response"])) }); scheme.FrameHoverParams = tObject({ selector: tString, strict: tOptional(tBoolean), force: tOptional(tBoolean), modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), position: tOptional(tType("Point")), timeout: tFloat, trial: tOptional(tBoolean) }); scheme.FrameHoverResult = tOptional(tObject({})); scheme.FrameInnerHTMLParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat }); scheme.FrameInnerHTMLResult = tObject({ value: tString }); scheme.FrameInnerTextParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat }); scheme.FrameInnerTextResult = tObject({ value: tString }); scheme.FrameInputValueParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat }); scheme.FrameInputValueResult = tObject({ value: tString }); scheme.FrameIsCheckedParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat }); scheme.FrameIsCheckedResult = tObject({ value: tBoolean }); scheme.FrameIsDisabledParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat }); scheme.FrameIsDisabledResult = tObject({ value: tBoolean }); scheme.FrameIsEnabledParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat }); scheme.FrameIsEnabledResult = tObject({ value: tBoolean }); scheme.FrameIsHiddenParams = tObject({ selector: tString, strict: tOptional(tBoolean) }); scheme.FrameIsHiddenResult = tObject({ value: tBoolean }); scheme.FrameIsVisibleParams = tObject({ selector: tString, strict: tOptional(tBoolean) }); scheme.FrameIsVisibleResult = tObject({ value: tBoolean }); scheme.FrameIsEditableParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat }); scheme.FrameIsEditableResult = tObject({ value: tBoolean }); scheme.FramePressParams = tObject({ selector: tString, strict: tOptional(tBoolean), key: tString, delay: tOptional(tFloat), noWaitAfter: tOptional(tBoolean), timeout: tFloat }); scheme.FramePressResult = tOptional(tObject({})); scheme.FrameQuerySelectorParams = tObject({ selector: tString, strict: tOptional(tBoolean) }); scheme.FrameQuerySelectorResult = tObject({ element: tOptional(tChannel(["ElementHandle"])) }); scheme.FrameQuerySelectorAllParams = tObject({ selector: tString }); scheme.FrameQuerySelectorAllResult = tObject({ elements: tArray(tChannel(["ElementHandle"])) }); scheme.FrameQueryCountParams = tObject({ selector: tString }); scheme.FrameQueryCountResult = tObject({ value: tInt }); scheme.FrameSelectOptionParams = tObject({ selector: tString, strict: tOptional(tBoolean), elements: tOptional(tArray(tChannel(["ElementHandle"]))), options: tOptional(tArray(tObject({ valueOrLabel: tOptional(tString), value: tOptional(tString), label: tOptional(tString), index: tOptional(tInt) }))), force: tOptional(tBoolean), timeout: tFloat }); scheme.FrameSelectOptionResult = tObject({ values: tArray(tString) }); scheme.FrameSetContentParams = tObject({ html: tString, timeout: tFloat, waitUntil: tOptional(tType("LifecycleEvent")) }); scheme.FrameSetContentResult = tOptional(tObject({})); scheme.FrameSetInputFilesParams = tObject({ selector: tString, strict: tOptional(tBoolean), payloads: tOptional(tArray(tObject({ name: tString, mimeType: tOptional(tString), buffer: tBinary }))), localDirectory: tOptional(tString), directoryStream: tOptional(tChannel(["WritableStream"])), localPaths: tOptional(tArray(tString)), streams: tOptional(tArray(tChannel(["WritableStream"]))), timeout: tFloat }); scheme.FrameSetInputFilesResult = tOptional(tObject({})); scheme.FrameTapParams = tObject({ selector: tString, strict: tOptional(tBoolean), force: tOptional(tBoolean), modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), position: tOptional(tType("Point")), timeout: tFloat, trial: tOptional(tBoolean) }); scheme.FrameTapResult = tOptional(tObject({})); scheme.FrameTextContentParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat }); scheme.FrameTextContentResult = tObject({ value: tOptional(tString) }); scheme.FrameTitleParams = tOptional(tObject({})); scheme.FrameTitleResult = tObject({ value: tString }); scheme.FrameTypeParams = tObject({ selector: tString, strict: tOptional(tBoolean), text: tString, delay: tOptional(tFloat), timeout: tFloat }); scheme.FrameTypeResult = tOptional(tObject({})); scheme.FrameUncheckParams = tObject({ selector: tString, strict: tOptional(tBoolean), force: tOptional(tBoolean), position: tOptional(tType("Point")), timeout: tFloat, trial: tOptional(tBoolean) }); scheme.FrameUncheckResult = tOptional(tObject({})); scheme.FrameWaitForTimeoutParams = tObject({ waitTimeout: tFloat }); scheme.FrameWaitForTimeoutResult = tOptional(tObject({})); scheme.FrameWaitForFunctionParams = tObject({ expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument"), timeout: tFloat, pollingInterval: tOptional(tFloat) }); scheme.FrameWaitForFunctionResult = tObject({ handle: tChannel(["ElementHandle", "JSHandle"]) }); scheme.FrameWaitForSelectorParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat, state: tOptional(tEnum(["attached", "detached", "visible", "hidden"])), omitReturnValue: tOptional(tBoolean) }); scheme.FrameWaitForSelectorResult = tObject({ element: tOptional(tChannel(["ElementHandle"])) }); scheme.FrameExpectParams = tObject({ selector: tOptional(tString), expression: tString, expressionArg: tOptional(tAny), pseudo: tOptional(tEnum(["before", "after"])), expectedText: tOptional(tArray(tType("ExpectedTextValue"))), expectedNumber: tOptional(tFloat), expectedValue: tOptional(tType("SerializedArgument")), useInnerText: tOptional(tBoolean), isNot: tBoolean, timeout: tFloat }); scheme.FrameExpectResult = tOptional(tObject({})); scheme.FrameExpectErrorDetails = tObject({ received: tOptional(tObject({ value: tOptional(tType("SerializedValue")), ariaSnapshot: tOptional(tString) })), timedOut: tOptional(tBoolean), customErrorMessage: tOptional(tString) }); scheme.JSHandleInitializer = tObject({ preview: tString }); scheme.JSHandlePreviewUpdatedEvent = tObject({ preview: tString }); scheme.ElementHandlePreviewUpdatedEvent = tType("JSHandlePreviewUpdatedEvent"); scheme.JSHandleDisposeParams = tOptional(tObject({})); scheme.ElementHandleDisposeParams = tType("JSHandleDisposeParams"); scheme.JSHandleDisposeResult = tOptional(tObject({})); scheme.ElementHandleDisposeResult = tType("JSHandleDisposeResult"); scheme.JSHandleEvaluateExpressionParams = tObject({ expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.ElementHandleEvaluateExpressionParams = tType("JSHandleEvaluateExpressionParams"); scheme.JSHandleEvaluateExpressionResult = tObject({ value: tType("SerializedValue") }); scheme.ElementHandleEvaluateExpressionResult = tType("JSHandleEvaluateExpressionResult"); scheme.JSHandleEvaluateExpressionHandleParams = tObject({ expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.ElementHandleEvaluateExpressionHandleParams = tType("JSHandleEvaluateExpressionHandleParams"); scheme.JSHandleEvaluateExpressionHandleResult = tObject({ handle: tChannel(["ElementHandle", "JSHandle"]) }); scheme.ElementHandleEvaluateExpressionHandleResult = tType("JSHandleEvaluateExpressionHandleResult"); scheme.JSHandleGetPropertyListParams = tOptional(tObject({})); scheme.ElementHandleGetPropertyListParams = tType("JSHandleGetPropertyListParams"); scheme.JSHandleGetPropertyListResult = tObject({ properties: tArray(tObject({ name: tString, value: tChannel(["ElementHandle", "JSHandle"]) })) }); scheme.ElementHandleGetPropertyListResult = tType("JSHandleGetPropertyListResult"); scheme.JSHandleGetPropertyParams = tObject({ name: tString }); scheme.ElementHandleGetPropertyParams = tType("JSHandleGetPropertyParams"); scheme.JSHandleGetPropertyResult = tObject({ handle: tChannel(["ElementHandle", "JSHandle"]) }); scheme.ElementHandleGetPropertyResult = tType("JSHandleGetPropertyResult"); scheme.JSHandleJsonValueParams = tOptional(tObject({})); scheme.ElementHandleJsonValueParams = tType("JSHandleJsonValueParams"); scheme.JSHandleJsonValueResult = tObject({ value: tType("SerializedValue") }); scheme.ElementHandleJsonValueResult = tType("JSHandleJsonValueResult"); scheme.ElementHandleInitializer = tObject({ preview: tString }); scheme.ElementHandleEvalOnSelectorParams = tObject({ selector: tString, strict: tOptional(tBoolean), expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.ElementHandleEvalOnSelectorResult = tObject({ value: tType("SerializedValue") }); scheme.ElementHandleEvalOnSelectorAllParams = tObject({ selector: tString, expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.ElementHandleEvalOnSelectorAllResult = tObject({ value: tType("SerializedValue") }); scheme.ElementHandleBoundingBoxParams = tOptional(tObject({})); scheme.ElementHandleBoundingBoxResult = tObject({ value: tOptional(tType("Rect")) }); scheme.ElementHandleCheckParams = tObject({ force: tOptional(tBoolean), position: tOptional(tType("Point")), timeout: tFloat, trial: tOptional(tBoolean) }); scheme.ElementHandleCheckResult = tOptional(tObject({})); scheme.ElementHandleClickParams = tObject({ force: tOptional(tBoolean), noWaitAfter: tOptional(tBoolean), modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), position: tOptional(tType("Point")), delay: tOptional(tFloat), button: tOptional(tEnum(["left", "right", "middle"])), clickCount: tOptional(tInt), timeout: tFloat, trial: tOptional(tBoolean), steps: tOptional(tInt) }); scheme.ElementHandleClickResult = tOptional(tObject({})); scheme.ElementHandleContentFrameParams = tOptional(tObject({})); scheme.ElementHandleContentFrameResult = tObject({ frame: tOptional(tChannel(["Frame"])) }); scheme.ElementHandleDblclickParams = tObject({ force: tOptional(tBoolean), modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), position: tOptional(tType("Point")), delay: tOptional(tFloat), button: tOptional(tEnum(["left", "right", "middle"])), timeout: tFloat, trial: tOptional(tBoolean), steps: tOptional(tInt) }); scheme.ElementHandleDblclickResult = tOptional(tObject({})); scheme.ElementHandleDispatchEventParams = tObject({ type: tString, eventInit: tType("SerializedArgument") }); scheme.ElementHandleDispatchEventResult = tOptional(tObject({})); scheme.ElementHandleFillParams = tObject({ value: tString, force: tOptional(tBoolean), timeout: tFloat }); scheme.ElementHandleFillResult = tOptional(tObject({})); scheme.ElementHandleFocusParams = tOptional(tObject({})); scheme.ElementHandleFocusResult = tOptional(tObject({})); scheme.ElementHandleGetAttributeParams = tObject({ name: tString }); scheme.ElementHandleGetAttributeResult = tObject({ value: tOptional(tString) }); scheme.ElementHandleHoverParams = tObject({ force: tOptional(tBoolean), modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), position: tOptional(tType("Point")), timeout: tFloat, trial: tOptional(tBoolean) }); scheme.ElementHandleHoverResult = tOptional(tObject({})); scheme.ElementHandleInnerHTMLParams = tOptional(tObject({})); scheme.ElementHandleInnerHTMLResult = tObject({ value: tString }); scheme.ElementHandleInnerTextParams = tOptional(tObject({})); scheme.ElementHandleInnerTextResult = tObject({ value: tString }); scheme.ElementHandleInputValueParams = tOptional(tObject({})); scheme.ElementHandleInputValueResult = tObject({ value: tString }); scheme.ElementHandleIsCheckedParams = tOptional(tObject({})); scheme.ElementHandleIsCheckedResult = tObject({ value: tBoolean }); scheme.ElementHandleIsDisabledParams = tOptional(tObject({})); scheme.ElementHandleIsDisabledResult = tObject({ value: tBoolean }); scheme.ElementHandleIsEditableParams = tOptional(tObject({})); scheme.ElementHandleIsEditableResult = tObject({ value: tBoolean }); scheme.ElementHandleIsEnabledParams = tOptional(tObject({})); scheme.ElementHandleIsEnabledResult = tObject({ value: tBoolean }); scheme.ElementHandleIsHiddenParams = tOptional(tObject({})); scheme.ElementHandleIsHiddenResult = tObject({ value: tBoolean }); scheme.ElementHandleIsVisibleParams = tOptional(tObject({})); scheme.ElementHandleIsVisibleResult = tObject({ value: tBoolean }); scheme.ElementHandleOwnerFrameParams = tOptional(tObject({})); scheme.ElementHandleOwnerFrameResult = tObject({ frame: tOptional(tChannel(["Frame"])) }); scheme.ElementHandlePressParams = tObject({ key: tString, delay: tOptional(tFloat), timeout: tFloat, noWaitAfter: tOptional(tBoolean) }); scheme.ElementHandlePressResult = tOptional(tObject({})); scheme.ElementHandleQuerySelectorParams = tObject({ selector: tString, strict: tOptional(tBoolean) }); scheme.ElementHandleQuerySelectorResult = tObject({ element: tOptional(tChannel(["ElementHandle"])) }); scheme.ElementHandleQuerySelectorAllParams = tObject({ selector: tString }); scheme.ElementHandleQuerySelectorAllResult = tObject({ elements: tArray(tChannel(["ElementHandle"])) }); scheme.ElementHandleScreenshotParams = tObject({ timeout: tFloat, type: tOptional(tEnum(["png", "jpeg"])), quality: tOptional(tInt), omitBackground: tOptional(tBoolean), caret: tOptional(tEnum(["hide", "initial"])), animations: tOptional(tEnum(["disabled", "allow"])), scale: tOptional(tEnum(["css", "device"])), mask: tOptional(tArray(tObject({ frame: tChannel(["Frame"]), selector: tString }))), maskColor: tOptional(tString), style: tOptional(tString) }); scheme.ElementHandleScreenshotResult = tObject({ binary: tBinary }); scheme.ElementHandleScrollIntoViewIfNeededParams = tObject({ timeout: tFloat }); scheme.ElementHandleScrollIntoViewIfNeededResult = tOptional(tObject({})); scheme.ElementHandleSelectOptionParams = tObject({ elements: tOptional(tArray(tChannel(["ElementHandle"]))), options: tOptional(tArray(tObject({ valueOrLabel: tOptional(tString), value: tOptional(tString), label: tOptional(tString), index: tOptional(tInt) }))), force: tOptional(tBoolean), timeout: tFloat }); scheme.ElementHandleSelectOptionResult = tObject({ values: tArray(tString) }); scheme.ElementHandleSelectTextParams = tObject({ force: tOptional(tBoolean), timeout: tFloat }); scheme.ElementHandleSelectTextResult = tOptional(tObject({})); scheme.ElementHandleSetInputFilesParams = tObject({ payloads: tOptional(tArray(tObject({ name: tString, mimeType: tOptional(tString), buffer: tBinary }))), localDirectory: tOptional(tString), directoryStream: tOptional(tChannel(["WritableStream"])), localPaths: tOptional(tArray(tString)), streams: tOptional(tArray(tChannel(["WritableStream"]))), timeout: tFloat }); scheme.ElementHandleSetInputFilesResult = tOptional(tObject({})); scheme.ElementHandleTapParams = tObject({ force: tOptional(tBoolean), modifiers: tOptional(tArray(tEnum(["Alt", "Control", "ControlOrMeta", "Meta", "Shift"]))), position: tOptional(tType("Point")), timeout: tFloat, trial: tOptional(tBoolean) }); scheme.ElementHandleTapResult = tOptional(tObject({})); scheme.ElementHandleTextContentParams = tOptional(tObject({})); scheme.ElementHandleTextContentResult = tObject({ value: tOptional(tString) }); scheme.ElementHandleTypeParams = tObject({ text: tString, delay: tOptional(tFloat), timeout: tFloat }); scheme.ElementHandleTypeResult = tOptional(tObject({})); scheme.ElementHandleUncheckParams = tObject({ force: tOptional(tBoolean), position: tOptional(tType("Point")), timeout: tFloat, trial: tOptional(tBoolean) }); scheme.ElementHandleUncheckResult = tOptional(tObject({})); scheme.ElementHandleWaitForElementStateParams = tObject({ state: tEnum(["visible", "hidden", "stable", "enabled", "disabled", "editable"]), timeout: tFloat }); scheme.ElementHandleWaitForElementStateResult = tOptional(tObject({})); scheme.ElementHandleWaitForSelectorParams = tObject({ selector: tString, strict: tOptional(tBoolean), timeout: tFloat, state: tOptional(tEnum(["attached", "detached", "visible", "hidden"])) }); scheme.ElementHandleWaitForSelectorResult = tObject({ element: tOptional(tChannel(["ElementHandle"])) }); scheme.LocalUtilsInitializer = tObject({ deviceDescriptors: tArray(tObject({ name: tString, descriptor: tObject({ userAgent: tString, viewport: tObject({ width: tInt, height: tInt }), screen: tOptional(tObject({ width: tInt, height: tInt })), deviceScaleFactor: tFloat, isMobile: tBoolean, hasTouch: tBoolean, defaultBrowserType: tEnum(["chromium", "firefox", "webkit"]) }) })) }); scheme.LocalUtilsZipParams = tObject({ zipFile: tString, entries: tArray(tType("NameValue")), stacksId: tOptional(tString), mode: tEnum(["write", "append"]), includeSources: tBoolean, additionalSources: tOptional(tArray(tString)) }); scheme.LocalUtilsZipResult = tOptional(tObject({})); scheme.LocalUtilsHarOpenParams = tObject({ file: tString }); scheme.LocalUtilsHarOpenResult = tObject({ harId: tOptional(tString), error: tOptional(tString) }); scheme.LocalUtilsHarLookupParams = tObject({ harId: tString, url: tString, method: tString, headers: tArray(tType("NameValue")), postData: tOptional(tBinary), isNavigationRequest: tBoolean }); scheme.LocalUtilsHarLookupResult = tObject({ action: tEnum(["error", "redirect", "fulfill", "noentry"]), message: tOptional(tString), redirectURL: tOptional(tString), status: tOptional(tInt), headers: tOptional(tArray(tType("NameValue"))), body: tOptional(tBinary) }); scheme.LocalUtilsHarCloseParams = tObject({ harId: tString }); scheme.LocalUtilsHarCloseResult = tOptional(tObject({})); scheme.LocalUtilsHarUnzipParams = tObject({ zipFile: tString, harFile: tString, resourcesDir: tOptional(tString) }); scheme.LocalUtilsHarUnzipResult = tOptional(tObject({})); scheme.LocalUtilsConnectParams = tObject({ endpoint: tString, headers: tOptional(tAny), exposeNetwork: tOptional(tString), slowMo: tOptional(tFloat), timeout: tFloat, socksProxyRedirectPortForTest: tOptional(tInt) }); scheme.LocalUtilsConnectResult = tObject({ pipe: tChannel(["JsonPipe"]), headers: tArray(tType("NameValue")) }); scheme.LocalUtilsTracingStartedParams = tObject({ tracesDir: tOptional(tString), traceName: tString, live: tOptional(tBoolean) }); scheme.LocalUtilsTracingStartedResult = tObject({ stacksId: tString }); scheme.LocalUtilsAddStackToTracingNoReplyParams = tObject({ callData: tType("ClientSideCallMetadata") }); scheme.LocalUtilsAddStackToTracingNoReplyResult = tOptional(tObject({})); scheme.LocalUtilsTraceDiscardedParams = tObject({ stacksId: tString }); scheme.LocalUtilsTraceDiscardedResult = tOptional(tObject({})); scheme.LocalUtilsGlobToRegexParams = tObject({ glob: tString, baseURL: tOptional(tString), webSocketUrl: tOptional(tBoolean) }); scheme.LocalUtilsGlobToRegexResult = tObject({ regex: tString }); scheme.SetNetworkCookie = tObject({ name: tString, value: tString, url: tOptional(tString), domain: tOptional(tString), path: tOptional(tString), expires: tOptional(tFloat), httpOnly: tOptional(tBoolean), secure: tOptional(tBoolean), sameSite: tOptional(tEnum(["Strict", "Lax", "None"])), partitionKey: tOptional(tString), _crHasCrossSiteAncestor: tOptional(tBoolean) }); scheme.NetworkCookie = tObject({ name: tString, value: tString, domain: tString, path: tString, expires: tFloat, httpOnly: tBoolean, secure: tBoolean, sameSite: tEnum(["Strict", "Lax", "None"]), partitionKey: tOptional(tString), _crHasCrossSiteAncestor: tOptional(tBoolean) }); scheme.RequestInitializer = tObject({ frame: tOptional(tChannel(["Frame"])), serviceWorker: tOptional(tChannel(["Worker"])), url: tString, resourceType: tString, method: tString, postData: tOptional(tBinary), headers: tArray(tType("NameValue")), isNavigationRequest: tBoolean, redirectedFrom: tOptional(tChannel(["Request"])) }); scheme.RequestResponseParams = tOptional(tObject({})); scheme.RequestResponseResult = tObject({ response: tOptional(tChannel(["Response"])) }); scheme.RequestRawRequestHeadersParams = tOptional(tObject({})); scheme.RequestRawRequestHeadersResult = tObject({ headers: tArray(tType("NameValue")) }); scheme.RouteInitializer = tObject({ request: tChannel(["Request"]) }); scheme.RouteRedirectNavigationRequestParams = tObject({ url: tString }); scheme.RouteRedirectNavigationRequestResult = tOptional(tObject({})); scheme.RouteAbortParams = tObject({ errorCode: tOptional(tString) }); scheme.RouteAbortResult = tOptional(tObject({})); scheme.RouteContinueParams = tObject({ url: tOptional(tString), method: tOptional(tString), headers: tOptional(tArray(tType("NameValue"))), postData: tOptional(tBinary), isFallback: tBoolean }); scheme.RouteContinueResult = tOptional(tObject({})); scheme.RouteFulfillParams = tObject({ status: tOptional(tInt), headers: tOptional(tArray(tType("NameValue"))), body: tOptional(tString), isBase64: tOptional(tBoolean), fetchResponseUid: tOptional(tString) }); scheme.RouteFulfillResult = tOptional(tObject({})); scheme.WebSocketRouteInitializer = tObject({ url: tString, protocols: tArray(tString) }); scheme.WebSocketRouteMessageFromPageEvent = tObject({ message: tString, isBase64: tBoolean }); scheme.WebSocketRouteMessageFromServerEvent = tObject({ message: tString, isBase64: tBoolean }); scheme.WebSocketRouteClosePageEvent = tObject({ code: tOptional(tInt), reason: tOptional(tString), wasClean: tBoolean }); scheme.WebSocketRouteCloseServerEvent = tObject({ code: tOptional(tInt), reason: tOptional(tString), wasClean: tBoolean }); scheme.WebSocketRouteConnectParams = tOptional(tObject({})); scheme.WebSocketRouteConnectResult = tOptional(tObject({})); scheme.WebSocketRouteEnsureOpenedParams = tOptional(tObject({})); scheme.WebSocketRouteEnsureOpenedResult = tOptional(tObject({})); scheme.WebSocketRouteSendToPageParams = tObject({ message: tString, isBase64: tBoolean }); scheme.WebSocketRouteSendToPageResult = tOptional(tObject({})); scheme.WebSocketRouteSendToServerParams = tObject({ message: tString, isBase64: tBoolean }); scheme.WebSocketRouteSendToServerResult = tOptional(tObject({})); scheme.WebSocketRouteClosePageParams = tObject({ code: tOptional(tInt), reason: tOptional(tString), wasClean: tBoolean }); scheme.WebSocketRouteClosePageResult = tOptional(tObject({})); scheme.WebSocketRouteCloseServerParams = tObject({ code: tOptional(tInt), reason: tOptional(tString), wasClean: tBoolean }); scheme.WebSocketRouteCloseServerResult = tOptional(tObject({})); scheme.ResourceTiming = tObject({ startTime: tFloat, domainLookupStart: tFloat, domainLookupEnd: tFloat, connectStart: tFloat, secureConnectionStart: tFloat, connectEnd: tFloat, requestStart: tFloat, responseStart: tFloat }); scheme.ResponseInitializer = tObject({ request: tChannel(["Request"]), url: tString, status: tInt, statusText: tString, headers: tArray(tType("NameValue")), timing: tType("ResourceTiming"), fromServiceWorker: tBoolean }); scheme.ResponseBodyParams = tOptional(tObject({})); scheme.ResponseBodyResult = tObject({ binary: tBinary }); scheme.ResponseSecurityDetailsParams = tOptional(tObject({})); scheme.ResponseSecurityDetailsResult = tObject({ value: tOptional(tType("SecurityDetails")) }); scheme.ResponseServerAddrParams = tOptional(tObject({})); scheme.ResponseServerAddrResult = tObject({ value: tOptional(tType("RemoteAddr")) }); scheme.ResponseRawResponseHeadersParams = tOptional(tObject({})); scheme.ResponseRawResponseHeadersResult = tObject({ headers: tArray(tType("NameValue")) }); scheme.ResponseHttpVersionParams = tOptional(tObject({})); scheme.ResponseHttpVersionResult = tObject({ value: tString }); scheme.ResponseSizesParams = tOptional(tObject({})); scheme.ResponseSizesResult = tObject({ sizes: tType("RequestSizes") }); scheme.SecurityDetails = tObject({ issuer: tOptional(tString), protocol: tOptional(tString), subjectName: tOptional(tString), validFrom: tOptional(tFloat), validTo: tOptional(tFloat) }); scheme.RequestSizes = tObject({ requestBodySize: tInt, requestHeadersSize: tInt, responseBodySize: tInt, responseHeadersSize: tInt }); scheme.RemoteAddr = tObject({ ipAddress: tString, port: tInt }); scheme.WebSocketInitializer = tObject({ url: tString }); scheme.WebSocketOpenEvent = tOptional(tObject({})); scheme.WebSocketFrameSentEvent = tObject({ opcode: tInt, data: tString }); scheme.WebSocketFrameReceivedEvent = tObject({ opcode: tInt, data: tString }); scheme.WebSocketSocketErrorEvent = tObject({ error: tString }); scheme.WebSocketCloseEvent = tOptional(tObject({})); scheme.PageInitializer = tObject({ mainFrame: tChannel(["Frame"]), viewportSize: tOptional(tObject({ width: tInt, height: tInt })), isClosed: tBoolean, opener: tOptional(tChannel(["Page"])), video: tOptional(tChannel(["Artifact"])) }); scheme.PageBindingCallEvent = tObject({ binding: tChannel(["BindingCall"]) }); scheme.PageCloseEvent = tOptional(tObject({})); scheme.PageCrashEvent = tOptional(tObject({})); scheme.PageDownloadEvent = tObject({ url: tString, suggestedFilename: tString, artifact: tChannel(["Artifact"]) }); scheme.PageViewportSizeChangedEvent = tObject({ viewportSize: tOptional(tObject({ width: tInt, height: tInt })) }); scheme.PageFileChooserEvent = tObject({ element: tChannel(["ElementHandle"]), isMultiple: tBoolean }); scheme.PageFrameAttachedEvent = tObject({ frame: tChannel(["Frame"]) }); scheme.PageFrameDetachedEvent = tObject({ frame: tChannel(["Frame"]) }); scheme.PageLocatorHandlerTriggeredEvent = tObject({ uid: tInt }); scheme.PageRouteEvent = tObject({ route: tChannel(["Route"]) }); scheme.PageScreencastFrameEvent = tObject({ data: tBinary, timestamp: tFloat, viewportWidth: tInt, viewportHeight: tInt }); scheme.PageWebSocketRouteEvent = tObject({ webSocketRoute: tChannel(["WebSocketRoute"]) }); scheme.PageWebSocketEvent = tObject({ webSocket: tChannel(["WebSocket"]) }); scheme.PageWorkerEvent = tObject({ worker: tChannel(["Worker"]) }); scheme.PageAddInitScriptParams = tObject({ source: tString }); scheme.PageAddInitScriptResult = tObject({ disposable: tChannel(["Disposable"]) }); scheme.PageCloseParams = tObject({ reason: tOptional(tString) }); scheme.PageCloseResult = tOptional(tObject({})); scheme.PageRunBeforeUnloadParams = tOptional(tObject({})); scheme.PageRunBeforeUnloadResult = tOptional(tObject({})); scheme.PageClearConsoleMessagesParams = tOptional(tObject({})); scheme.PageClearConsoleMessagesResult = tOptional(tObject({})); scheme.PageConsoleMessagesParams = tObject({ filter: tOptional(tType("ConsoleMessagesFilter")) }); scheme.PageConsoleMessagesResult = tObject({ messages: tArray(tObject({ type: tString, text: tString, args: tArray(tChannel(["ElementHandle", "JSHandle"])), location: tObject({ url: tString, lineNumber: tInt, columnNumber: tInt }), timestamp: tFloat })) }); scheme.PageEmulateMediaParams = tObject({ media: tOptional(tEnum(["screen", "print", "no-override"])), colorScheme: tOptional(tEnum(["dark", "light", "no-preference", "no-override"])), reducedMotion: tOptional(tEnum(["reduce", "no-preference", "no-override"])), forcedColors: tOptional(tEnum(["active", "none", "no-override"])), contrast: tOptional(tEnum(["no-preference", "more", "no-override"])) }); scheme.PageEmulateMediaResult = tOptional(tObject({})); scheme.PageExposeBindingParams = tObject({ name: tString }); scheme.PageExposeBindingResult = tObject({ disposable: tChannel(["Disposable"]) }); scheme.PageGoBackParams = tObject({ timeout: tFloat, waitUntil: tOptional(tType("LifecycleEvent")) }); scheme.PageGoBackResult = tObject({ response: tOptional(tChannel(["Response"])) }); scheme.PageGoForwardParams = tObject({ timeout: tFloat, waitUntil: tOptional(tType("LifecycleEvent")) }); scheme.PageGoForwardResult = tObject({ response: tOptional(tChannel(["Response"])) }); scheme.PageRequestGCParams = tOptional(tObject({})); scheme.PageRequestGCResult = tOptional(tObject({})); scheme.PageRegisterLocatorHandlerParams = tObject({ selector: tString, noWaitAfter: tOptional(tBoolean) }); scheme.PageRegisterLocatorHandlerResult = tObject({ uid: tInt }); scheme.PageResolveLocatorHandlerNoReplyParams = tObject({ uid: tInt, remove: tOptional(tBoolean) }); scheme.PageResolveLocatorHandlerNoReplyResult = tOptional(tObject({})); scheme.PageUnregisterLocatorHandlerParams = tObject({ uid: tInt }); scheme.PageUnregisterLocatorHandlerResult = tOptional(tObject({})); scheme.PageReloadParams = tObject({ timeout: tFloat, waitUntil: tOptional(tType("LifecycleEvent")) }); scheme.PageReloadResult = tObject({ response: tOptional(tChannel(["Response"])) }); scheme.PageExpectScreenshotParams = tObject({ expected: tOptional(tBinary), timeout: tFloat, isNot: tBoolean, locator: tOptional(tObject({ frame: tChannel(["Frame"]), selector: tString })), comparator: tOptional(tString), maxDiffPixels: tOptional(tInt), maxDiffPixelRatio: tOptional(tFloat), threshold: tOptional(tFloat), fullPage: tOptional(tBoolean), clip: tOptional(tType("Rect")), omitBackground: tOptional(tBoolean), caret: tOptional(tEnum(["hide", "initial"])), animations: tOptional(tEnum(["disabled", "allow"])), scale: tOptional(tEnum(["css", "device"])), mask: tOptional(tArray(tObject({ frame: tChannel(["Frame"]), selector: tString }))), maskColor: tOptional(tString), style: tOptional(tString) }); scheme.PageExpectScreenshotResult = tObject({ actual: tOptional(tBinary) }); scheme.PageExpectScreenshotErrorDetails = tObject({ diff: tOptional(tBinary), customErrorMessage: tOptional(tString), actual: tOptional(tBinary), previous: tOptional(tBinary), timedOut: tOptional(tBoolean), log: tOptional(tArray(tString)) }); scheme.PageScreenshotParams = tObject({ timeout: tFloat, type: tOptional(tEnum(["png", "jpeg"])), quality: tOptional(tInt), fullPage: tOptional(tBoolean), clip: tOptional(tType("Rect")), omitBackground: tOptional(tBoolean), caret: tOptional(tEnum(["hide", "initial"])), animations: tOptional(tEnum(["disabled", "allow"])), scale: tOptional(tEnum(["css", "device"])), mask: tOptional(tArray(tObject({ frame: tChannel(["Frame"]), selector: tString }))), maskColor: tOptional(tString), style: tOptional(tString) }); scheme.PageScreenshotResult = tObject({ binary: tBinary }); scheme.PageSetExtraHTTPHeadersParams = tObject({ headers: tArray(tType("NameValue")) }); scheme.PageSetExtraHTTPHeadersResult = tOptional(tObject({})); scheme.PageSetNetworkInterceptionPatternsParams = tObject({ patterns: tArray(tObject({ glob: tOptional(tString), regexSource: tOptional(tString), regexFlags: tOptional(tString), urlPattern: tOptional(tType("URLPattern")) })) }); scheme.PageSetNetworkInterceptionPatternsResult = tOptional(tObject({})); scheme.PageSetWebSocketInterceptionPatternsParams = tObject({ patterns: tArray(tObject({ glob: tOptional(tString), regexSource: tOptional(tString), regexFlags: tOptional(tString), urlPattern: tOptional(tType("URLPattern")) })) }); scheme.PageSetWebSocketInterceptionPatternsResult = tOptional(tObject({})); scheme.PageSetViewportSizeParams = tObject({ viewportSize: tObject({ width: tInt, height: tInt }) }); scheme.PageSetViewportSizeResult = tOptional(tObject({})); scheme.PageKeyboardDownParams = tObject({ key: tString }); scheme.PageKeyboardDownResult = tOptional(tObject({})); scheme.PageKeyboardUpParams = tObject({ key: tString }); scheme.PageKeyboardUpResult = tOptional(tObject({})); scheme.PageKeyboardInsertTextParams = tObject({ text: tString }); scheme.PageKeyboardInsertTextResult = tOptional(tObject({})); scheme.PageKeyboardTypeParams = tObject({ text: tString, delay: tOptional(tFloat) }); scheme.PageKeyboardTypeResult = tOptional(tObject({})); scheme.PageKeyboardPressParams = tObject({ key: tString, delay: tOptional(tFloat) }); scheme.PageKeyboardPressResult = tOptional(tObject({})); scheme.PageMouseMoveParams = tObject({ x: tFloat, y: tFloat, steps: tOptional(tInt) }); scheme.PageMouseMoveResult = tOptional(tObject({})); scheme.PageMouseDownParams = tObject({ button: tOptional(tEnum(["left", "right", "middle"])), clickCount: tOptional(tInt) }); scheme.PageMouseDownResult = tOptional(tObject({})); scheme.PageMouseUpParams = tObject({ button: tOptional(tEnum(["left", "right", "middle"])), clickCount: tOptional(tInt) }); scheme.PageMouseUpResult = tOptional(tObject({})); scheme.PageMouseClickParams = tObject({ x: tFloat, y: tFloat, delay: tOptional(tFloat), button: tOptional(tEnum(["left", "right", "middle"])), clickCount: tOptional(tInt) }); scheme.PageMouseClickResult = tOptional(tObject({})); scheme.PageMouseWheelParams = tObject({ deltaX: tFloat, deltaY: tFloat }); scheme.PageMouseWheelResult = tOptional(tObject({})); scheme.PageTouchscreenTapParams = tObject({ x: tFloat, y: tFloat }); scheme.PageTouchscreenTapResult = tOptional(tObject({})); scheme.PageClearPageErrorsParams = tOptional(tObject({})); scheme.PageClearPageErrorsResult = tOptional(tObject({})); scheme.PagePageErrorsParams = tObject({ filter: tOptional(tType("ConsoleMessagesFilter")) }); scheme.PagePageErrorsResult = tObject({ errors: tArray(tType("SerializedError")) }); scheme.PagePdfParams = tObject({ scale: tOptional(tFloat), displayHeaderFooter: tOptional(tBoolean), headerTemplate: tOptional(tString), footerTemplate: tOptional(tString), printBackground: tOptional(tBoolean), landscape: tOptional(tBoolean), pageRanges: tOptional(tString), format: tOptional(tString), width: tOptional(tString), height: tOptional(tString), preferCSSPageSize: tOptional(tBoolean), margin: tOptional(tObject({ top: tOptional(tString), bottom: tOptional(tString), left: tOptional(tString), right: tOptional(tString) })), tagged: tOptional(tBoolean), outline: tOptional(tBoolean) }); scheme.PagePdfResult = tObject({ pdf: tBinary }); scheme.PageRequestsParams = tOptional(tObject({})); scheme.PageRequestsResult = tObject({ requests: tArray(tChannel(["Request"])) }); scheme.PageStartJSCoverageParams = tObject({ resetOnNavigation: tOptional(tBoolean), reportAnonymousScripts: tOptional(tBoolean) }); scheme.PageStartJSCoverageResult = tOptional(tObject({})); scheme.PageStopJSCoverageParams = tOptional(tObject({})); scheme.PageStopJSCoverageResult = tObject({ entries: tArray(tObject({ url: tString, scriptId: tString, source: tOptional(tString), functions: tArray(tObject({ functionName: tString, isBlockCoverage: tBoolean, ranges: tArray(tObject({ startOffset: tInt, endOffset: tInt, count: tInt })) })) })) }); scheme.PageStartCSSCoverageParams = tObject({ resetOnNavigation: tOptional(tBoolean) }); scheme.PageStartCSSCoverageResult = tOptional(tObject({})); scheme.PageStopCSSCoverageParams = tOptional(tObject({})); scheme.PageStopCSSCoverageResult = tObject({ entries: tArray(tObject({ url: tString, text: tOptional(tString), ranges: tArray(tObject({ start: tInt, end: tInt })) })) }); scheme.PageBringToFrontParams = tOptional(tObject({})); scheme.PageBringToFrontResult = tOptional(tObject({})); scheme.PagePickLocatorParams = tOptional(tObject({})); scheme.PagePickLocatorResult = tObject({ selector: tString }); scheme.PageCancelPickLocatorParams = tOptional(tObject({})); scheme.PageCancelPickLocatorResult = tOptional(tObject({})); scheme.PageHideHighlightParams = tOptional(tObject({})); scheme.PageHideHighlightResult = tOptional(tObject({})); scheme.PageScreencastShowOverlayParams = tObject({ html: tString, duration: tOptional(tFloat) }); scheme.PageScreencastShowOverlayResult = tObject({ id: tString }); scheme.PageScreencastRemoveOverlayParams = tObject({ id: tString }); scheme.PageScreencastRemoveOverlayResult = tOptional(tObject({})); scheme.PageScreencastChapterParams = tObject({ title: tString, description: tOptional(tString), duration: tOptional(tFloat) }); scheme.PageScreencastChapterResult = tOptional(tObject({})); scheme.PageScreencastSetOverlayVisibleParams = tObject({ visible: tBoolean }); scheme.PageScreencastSetOverlayVisibleResult = tOptional(tObject({})); scheme.PageScreencastShowActionsParams = tObject({ duration: tOptional(tFloat), position: tOptional(tEnum(["top-left", "top", "top-right", "bottom-left", "bottom", "bottom-right"])), fontSize: tOptional(tInt), cursor: tOptional(tEnum(["none", "pointer"])) }); scheme.PageScreencastShowActionsResult = tOptional(tObject({})); scheme.PageScreencastHideActionsParams = tOptional(tObject({})); scheme.PageScreencastHideActionsResult = tOptional(tObject({})); scheme.PageScreencastStartParams = tObject({ size: tOptional(tObject({ width: tInt, height: tInt })), quality: tOptional(tInt), sendFrames: tOptional(tBoolean), record: tOptional(tBoolean) }); scheme.PageScreencastStartResult = tObject({ artifact: tOptional(tChannel(["Artifact"])) }); scheme.PageScreencastStopParams = tOptional(tObject({})); scheme.PageScreencastStopResult = tOptional(tObject({})); scheme.PageUpdateSubscriptionParams = tObject({ event: tEnum(["console", "dialog", "fileChooser", "request", "response", "requestFinished", "requestFailed"]), enabled: tBoolean }); scheme.PageUpdateSubscriptionResult = tOptional(tObject({})); scheme.PageSetDockTileParams = tObject({ image: tBinary }); scheme.PageSetDockTileResult = tOptional(tObject({})); scheme.PageWebStorageItemsParams = tObject({ kind: tEnum(["local", "session"]) }); scheme.PageWebStorageItemsResult = tObject({ items: tArray(tType("NameValue")) }); scheme.PageWebStorageGetItemParams = tObject({ kind: tEnum(["local", "session"]), name: tString }); scheme.PageWebStorageGetItemResult = tObject({ value: tOptional(tString) }); scheme.PageWebStorageSetItemParams = tObject({ kind: tEnum(["local", "session"]), name: tString, value: tString }); scheme.PageWebStorageSetItemResult = tOptional(tObject({})); scheme.PageWebStorageRemoveItemParams = tObject({ kind: tEnum(["local", "session"]), name: tString }); scheme.PageWebStorageRemoveItemResult = tOptional(tObject({})); scheme.PageWebStorageClearParams = tObject({ kind: tEnum(["local", "session"]) }); scheme.PageWebStorageClearResult = tOptional(tObject({})); scheme.RootInitializer = tOptional(tObject({})); scheme.RootInitializeParams = tObject({ sdkLanguage: tType("SDKLanguage") }); scheme.RootInitializeResult = tObject({ playwright: tChannel(["Playwright"]) }); scheme.PlaywrightInitializer = tObject({ chromium: tChannel(["BrowserType"]), firefox: tChannel(["BrowserType"]), webkit: tChannel(["BrowserType"]), android: tChannel(["Android"]), electron: tChannel(["Electron"]), utils: tOptional(tChannel(["LocalUtils"])), preLaunchedBrowser: tOptional(tChannel(["Browser"])), preConnectedAndroidDevice: tOptional(tChannel(["AndroidDevice"])), socksSupport: tOptional(tChannel(["SocksSupport"])) }); scheme.PlaywrightNewRequestParams = tObject({ baseURL: tOptional(tString), userAgent: tOptional(tString), ignoreHTTPSErrors: tOptional(tBoolean), extraHTTPHeaders: tOptional(tArray(tType("NameValue"))), failOnStatusCode: tOptional(tBoolean), clientCertificates: tOptional(tArray(tObject({ origin: tString, cert: tOptional(tBinary), key: tOptional(tBinary), passphrase: tOptional(tString), pfx: tOptional(tBinary) }))), maxRedirects: tOptional(tInt), httpCredentials: tOptional(tObject({ username: tString, password: tString, origin: tOptional(tString), send: tOptional(tEnum(["always", "unauthorized"])) })), proxy: tOptional(tObject({ server: tString, bypass: tOptional(tString), username: tOptional(tString), password: tOptional(tString) })), storageState: tOptional(tObject({ cookies: tOptional(tArray(tType("NetworkCookie"))), origins: tOptional(tArray(tType("SetOriginStorage"))) })), tracesDir: tOptional(tString) }); scheme.PlaywrightNewRequestResult = tObject({ request: tChannel(["APIRequestContext"]) }); scheme.DebugControllerInitializer = tOptional(tObject({})); scheme.DebugControllerInspectRequestedEvent = tObject({ selector: tString, locator: tString, ariaSnapshot: tString }); scheme.DebugControllerSetModeRequestedEvent = tObject({ mode: tString }); scheme.DebugControllerStateChangedEvent = tObject({ pageCount: tInt }); scheme.DebugControllerSourceChangedEvent = tObject({ text: tString, header: tOptional(tString), footer: tOptional(tString), actions: tOptional(tArray(tString)) }); scheme.DebugControllerPausedEvent = tObject({ paused: tBoolean }); scheme.DebugControllerInitializeParams = tObject({ codegenId: tString, sdkLanguage: tType("SDKLanguage") }); scheme.DebugControllerInitializeResult = tOptional(tObject({})); scheme.DebugControllerSetReportStateChangedParams = tObject({ enabled: tBoolean }); scheme.DebugControllerSetReportStateChangedResult = tOptional(tObject({})); scheme.DebugControllerSetRecorderModeParams = tObject({ mode: tEnum(["inspecting", "recording", "none"]), testIdAttributeName: tOptional(tString), generateAutoExpect: tOptional(tBoolean) }); scheme.DebugControllerSetRecorderModeResult = tOptional(tObject({})); scheme.DebugControllerHighlightParams = tObject({ selector: tOptional(tString), ariaTemplate: tOptional(tString) }); scheme.DebugControllerHighlightResult = tOptional(tObject({})); scheme.DebugControllerHideHighlightParams = tOptional(tObject({})); scheme.DebugControllerHideHighlightResult = tOptional(tObject({})); scheme.DebugControllerResumeParams = tOptional(tObject({})); scheme.DebugControllerResumeResult = tOptional(tObject({})); scheme.DebugControllerKillParams = tOptional(tObject({})); scheme.DebugControllerKillResult = tOptional(tObject({})); scheme.SocksSupportInitializer = tOptional(tObject({})); scheme.SocksSupportSocksRequestedEvent = tObject({ uid: tString, host: tString, port: tInt }); scheme.SocksSupportSocksDataEvent = tObject({ uid: tString, data: tBinary }); scheme.SocksSupportSocksClosedEvent = tObject({ uid: tString }); scheme.SocksSupportSocksConnectedParams = tObject({ uid: tString, host: tString, port: tInt }); scheme.SocksSupportSocksConnectedResult = tOptional(tObject({})); scheme.SocksSupportSocksFailedParams = tObject({ uid: tString, errorCode: tString }); scheme.SocksSupportSocksFailedResult = tOptional(tObject({})); scheme.SocksSupportSocksDataParams = tObject({ uid: tString, data: tBinary }); scheme.SocksSupportSocksDataResult = tOptional(tObject({})); scheme.SocksSupportSocksErrorParams = tObject({ uid: tString, error: tString }); scheme.SocksSupportSocksErrorResult = tOptional(tObject({})); scheme.SocksSupportSocksEndParams = tObject({ uid: tString }); scheme.SocksSupportSocksEndResult = tOptional(tObject({})); scheme.JsonPipeInitializer = tOptional(tObject({})); scheme.JsonPipeMessageEvent = tObject({ message: tAny }); scheme.JsonPipeClosedEvent = tObject({ reason: tOptional(tString) }); scheme.JsonPipeSendParams = tObject({ message: tAny }); scheme.JsonPipeSendResult = tOptional(tObject({})); scheme.JsonPipeCloseParams = tOptional(tObject({})); scheme.JsonPipeCloseResult = tOptional(tObject({})); scheme.ExpectedTextValue = tObject({ string: tOptional(tString), regexSource: tOptional(tString), regexFlags: tOptional(tString), matchSubstring: tOptional(tBoolean), ignoreCase: tOptional(tBoolean), normalizeWhiteSpace: tOptional(tBoolean) }); scheme.SelectorEngine = tObject({ name: tString, source: tString, contentScript: tOptional(tBoolean) }); scheme.FormField = tObject({ name: tString, value: tOptional(tString), file: tOptional(tObject({ name: tString, mimeType: tOptional(tString), buffer: tBinary })) }); scheme.LifecycleEvent = tEnum(["load", "domcontentloaded", "networkidle", "commit"]); scheme.ConsoleMessagesFilter = tEnum(["all", "since-navigation"]); scheme.RecorderSource = tObject({ isRecorded: tBoolean, id: tString, label: tString, text: tString, language: tString, highlight: tArray(tObject({ line: tInt, type: tString })), revealLine: tOptional(tInt), group: tOptional(tString) }); scheme.IndexedDBDatabase = tObject({ name: tString, version: tInt, stores: tArray(tObject({ name: tString, autoIncrement: tBoolean, keyPath: tOptional(tString), keyPathArray: tOptional(tArray(tString)), records: tArray(tObject({ key: tOptional(tAny), keyEncoded: tOptional(tAny), value: tOptional(tAny), valueEncoded: tOptional(tAny) })), indexes: tArray(tObject({ name: tString, keyPath: tOptional(tString), keyPathArray: tOptional(tArray(tString)), multiEntry: tBoolean, unique: tBoolean })) })) }); scheme.SetOriginStorage = tObject({ origin: tString, localStorage: tArray(tType("NameValue")), indexedDB: tOptional(tArray(tType("IndexedDBDatabase"))) }); scheme.OriginStorage = tObject({ origin: tString, localStorage: tArray(tType("NameValue")), indexedDB: tOptional(tArray(tType("IndexedDBDatabase"))) }); scheme.RecordHarOptions = tObject({ content: tOptional(tEnum(["embed", "attach", "omit"])), mode: tOptional(tEnum(["full", "minimal"])), urlGlob: tOptional(tString), urlRegexSource: tOptional(tString), urlRegexFlags: tOptional(tString), harPath: tOptional(tString), resourcesDir: tOptional(tString) }); scheme.CDPSessionInitializer = tOptional(tObject({})); scheme.CDPSessionEventEvent = tObject({ method: tString, params: tOptional(tAny) }); scheme.CDPSessionCloseEvent = tOptional(tObject({})); scheme.CDPSessionSendParams = tObject({ method: tString, params: tOptional(tAny) }); scheme.CDPSessionSendResult = tObject({ result: tAny }); scheme.CDPSessionDetachParams = tOptional(tObject({})); scheme.CDPSessionDetachResult = tOptional(tObject({})); scheme.BindingCallInitializer = tObject({ frame: tChannel(["Frame"]), name: tString, args: tArray(tType("SerializedValue")) }); scheme.BindingCallRejectParams = tObject({ error: tType("SerializedError") }); scheme.BindingCallRejectResult = tOptional(tObject({})); scheme.BindingCallResolveParams = tObject({ result: tType("SerializedArgument") }); scheme.BindingCallResolveResult = tOptional(tObject({})); scheme.DebuggerInitializer = tOptional(tObject({})); scheme.DebuggerPausedStateChangedEvent = tObject({ pausedDetails: tOptional(tObject({ location: tObject({ file: tString, line: tOptional(tInt), column: tOptional(tInt) }), title: tString, stack: tOptional(tString) })) }); scheme.DebuggerRequestPauseParams = tOptional(tObject({})); scheme.DebuggerRequestPauseResult = tOptional(tObject({})); scheme.DebuggerResumeParams = tOptional(tObject({})); scheme.DebuggerResumeResult = tOptional(tObject({})); scheme.DebuggerNextParams = tOptional(tObject({})); scheme.DebuggerNextResult = tOptional(tObject({})); scheme.DebuggerRunToParams = tObject({ location: tObject({ file: tString, line: tOptional(tInt), column: tOptional(tInt) }) }); scheme.DebuggerRunToResult = tOptional(tObject({})); scheme.DialogInitializer = tObject({ page: tOptional(tChannel(["Page"])), type: tString, message: tString, defaultValue: tString }); scheme.DialogAcceptParams = tObject({ promptText: tOptional(tString) }); scheme.DialogAcceptResult = tOptional(tObject({})); scheme.DialogDismissParams = tOptional(tObject({})); scheme.DialogDismissResult = tOptional(tObject({})); scheme.SerializedValue = tObject({ n: tOptional(tFloat), b: tOptional(tBoolean), s: tOptional(tString), v: tOptional(tEnum(["null", "undefined", "NaN", "Infinity", "-Infinity", "-0"])), d: tOptional(tString), u: tOptional(tString), bi: tOptional(tString), ta: tOptional(tObject({ b: tBinary, k: tEnum(["i8", "ui8", "ui8c", "i16", "ui16", "i32", "ui32", "f32", "f64", "bi64", "bui64"]) })), e: tOptional(tObject({ m: tString, n: tString, s: tString })), r: tOptional(tObject({ p: tString, f: tString })), a: tOptional(tArray(tType("SerializedValue"))), o: tOptional(tArray(tObject({ k: tString, v: tType("SerializedValue") }))), h: tOptional(tInt), id: tOptional(tInt), ref: tOptional(tInt) }); scheme.SerializedArgument = tObject({ value: tType("SerializedValue"), handles: tArray(tChannel("*")) }); scheme.SerializedError = tObject({ error: tOptional(tObject({ message: tString, name: tString, stack: tOptional(tString) })), value: tOptional(tType("SerializedValue")) }); scheme.StackFrame = tObject({ file: tString, line: tInt, column: tInt, function: tOptional(tString) }); scheme.VirtualCredential = tObject({ id: tString, rpId: tString, userHandle: tString, privateKey: tString, publicKey: tString }); scheme.Point = tObject({ x: tFloat, y: tFloat }); scheme.Rect = tObject({ x: tFloat, y: tFloat, width: tFloat, height: tFloat }); scheme.URLPattern = tObject({ hash: tString, hostname: tString, password: tString, pathname: tString, port: tString, protocol: tString, search: tString, username: tString }); scheme.NameValue = tObject({ name: tString, value: tString }); scheme.TracingInitializer = tOptional(tObject({})); scheme.TracingTracingStartParams = tObject({ name: tOptional(tString), snapshots: tOptional(tBoolean), screenshots: tOptional(tBoolean), live: tOptional(tBoolean) }); scheme.TracingTracingStartResult = tOptional(tObject({})); scheme.TracingTracingStartChunkParams = tObject({ name: tOptional(tString), title: tOptional(tString) }); scheme.TracingTracingStartChunkResult = tObject({ traceName: tString }); scheme.TracingTracingGroupParams = tObject({ name: tString, location: tOptional(tObject({ file: tString, line: tOptional(tInt), column: tOptional(tInt) })) }); scheme.TracingTracingGroupResult = tOptional(tObject({})); scheme.TracingTracingGroupEndParams = tOptional(tObject({})); scheme.TracingTracingGroupEndResult = tOptional(tObject({})); scheme.TracingTracingStopChunkParams = tObject({ mode: tEnum(["archive", "discard", "entries"]) }); scheme.TracingTracingStopChunkResult = tObject({ artifact: tOptional(tChannel(["Artifact"])), entries: tOptional(tArray(tType("NameValue"))) }); scheme.TracingTracingStopParams = tOptional(tObject({})); scheme.TracingTracingStopResult = tOptional(tObject({})); scheme.TracingHarStartParams = tObject({ page: tOptional(tChannel(["Page"])), options: tType("RecordHarOptions") }); scheme.TracingHarStartResult = tObject({ harId: tString }); scheme.TracingHarExportParams = tObject({ harId: tOptional(tString), mode: tEnum(["archive", "entries"]) }); scheme.TracingHarExportResult = tObject({ artifact: tOptional(tChannel(["Artifact"])), entries: tOptional(tArray(tType("NameValue"))) }); scheme.WorkerInitializer = tObject({ url: tString }); scheme.WorkerConsoleEvent = tObject({ type: tString, text: tString, args: tArray(tChannel(["ElementHandle", "JSHandle"])), location: tObject({ url: tString, lineNumber: tInt, columnNumber: tInt }), timestamp: tFloat }); scheme.WorkerCloseEvent = tOptional(tObject({})); scheme.WorkerDisconnectParams = tObject({ reason: tOptional(tString) }); scheme.WorkerDisconnectResult = tOptional(tObject({})); scheme.WorkerEvaluateExpressionParams = tObject({ expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.WorkerEvaluateExpressionResult = tObject({ value: tType("SerializedValue") }); scheme.WorkerEvaluateExpressionHandleParams = tObject({ expression: tString, isFunction: tOptional(tBoolean), arg: tType("SerializedArgument") }); scheme.WorkerEvaluateExpressionHandleResult = tObject({ handle: tChannel(["ElementHandle", "JSHandle"]) }); scheme.WorkerUpdateSubscriptionParams = tObject({ event: tEnum(["console"]), enabled: tBoolean }); scheme.WorkerUpdateSubscriptionResult = tOptional(tObject({})); } }); // packages/playwright-core/src/server/protocolError.ts function isProtocolError(e) { return e instanceof ProtocolError; } function isSessionClosedError(e) { return e instanceof ProtocolError && (e.type === "closed" || e.type === "crashed"); } var ProtocolError; var init_protocolError = __esm({ "packages/playwright-core/src/server/protocolError.ts"() { "use strict"; init_stackTrace(); ProtocolError = class extends Error { constructor(type3, method, logs) { super(); this.type = type3; this.method = method; this.logs = logs; } setMessage(message) { rewriteErrorMessage(this, `Protocol error (${this.method}): ${message}`); } browserLogMessage() { return this.logs ? "\nBrowser logs:\n" + this.logs : ""; } }; } }); // packages/playwright-core/src/server/callLog.ts function compressCallLog(log2) { const lines = []; for (const block of findRepeatedSubsequences(log2)) { for (let i = 0; i < block.sequence.length; i++) { const line = block.sequence[i]; const leadingWhitespace = line.match(/^\s*/); const whitespacePrefix = " " + leadingWhitespace?.[0] || ""; const countPrefix = `${block.count} \xD7 `; if (block.count > 1 && i === 0) lines.push(whitespacePrefix + countPrefix + line.trim()); else if (block.count > 1) lines.push(whitespacePrefix + " ".repeat(countPrefix.length - 2) + "- " + line.trim()); else lines.push(whitespacePrefix + "- " + line.trim()); } } return lines; } function findRepeatedSubsequences(s) { const n = s.length; const result2 = []; let i = 0; const arraysEqual = (a1, a2) => { if (a1.length !== a2.length) return false; for (let j = 0; j < a1.length; j++) { if (a1[j] !== a2[j]) return false; } return true; }; while (i < n) { let maxRepeatCount = 1; let maxRepeatSubstr = [s[i]]; let maxRepeatLength = 1; for (let p = 1; p <= n - i; p++) { const substr = s.slice(i, i + p); let k = 1; while (i + p * k <= n && arraysEqual(s.slice(i + p * (k - 1), i + p * k), substr)) k += 1; k -= 1; if (k > 1 && k * p > maxRepeatCount * maxRepeatLength) { maxRepeatCount = k; maxRepeatSubstr = substr; maxRepeatLength = p; } } result2.push({ sequence: maxRepeatSubstr, count: maxRepeatCount }); i += maxRepeatLength * maxRepeatCount; } return result2; } var findRepeatedSubsequencesForTest; var init_callLog = __esm({ "packages/playwright-core/src/server/callLog.ts"() { "use strict"; findRepeatedSubsequencesForTest = findRepeatedSubsequences; } }); // packages/playwright-core/src/server/dispatchers/dispatcher.ts function setMaxDispatchersForTest(value2) { maxDispatchersOverride = value2; } function maxDispatchersForBucket(gcBucket) { return maxDispatchersOverride ?? { "JSHandle": 1e5, "ElementHandle": 1e5 }[gcBucket] ?? 1e4; } var import_events5, metadataValidator, waitInfoValidator, maxDispatchersOverride, Dispatcher, RootDispatcher, DispatcherConnection; var init_dispatcher = __esm({ "packages/playwright-core/src/server/dispatchers/dispatcher.ts"() { "use strict"; import_events5 = require("events"); init_protocolMetainfo(); init_eventsHelper(); init_debug(); init_assert(); init_time(); init_stackTrace(); init_validator(); init_errors(); init_instrumentation(); init_protocolError(); init_callLog(); init_progress(); metadataValidator = createMetadataValidator(); waitInfoValidator = createWaitInfoValidator(); Dispatcher = class extends import_events5.EventEmitter { constructor(parent, object, type3, initializer, gcBucket) { super(); this._dispatchers = /* @__PURE__ */ new Map(); this._disposed = false; this._eventListeners = []; this._activeProgressControllers = /* @__PURE__ */ new Set(); this.connection = parent instanceof DispatcherConnection ? parent : parent.connection; this._parent = parent instanceof DispatcherConnection ? void 0 : parent; const guid = object.guid; this._guid = guid; this._type = type3; this._object = object; this._gcBucket = gcBucket ?? type3; this.connection.registerDispatcher(this); if (this._parent) { assert(!this._parent._dispatchers.has(guid)); this._parent._dispatchers.set(guid, this); } if (this._parent) this.connection.sendCreate(this._parent, type3, guid, initializer); this.connection.maybeDisposeStaleDispatchers(this._gcBucket); } parentScope() { return this._parent; } addObjectListener(eventName, handler) { this._eventListeners.push(eventsHelper.addEventListener(this._object, eventName, handler)); } adopt(child) { if (child._parent === this) return; const oldParent = child._parent; oldParent._dispatchers.delete(child._guid); this._dispatchers.set(child._guid, child); child._parent = this; this.connection.sendAdopt(this, child); } async _runCommand(callMetadata, method, validParams) { const controller = ProgressController.createForSdkObject(this._object, callMetadata); this._activeProgressControllers.add(controller); try { return await controller.run((progress2) => this[method](validParams, progress2), validParams?.timeout); } finally { this._activeProgressControllers.delete(controller); } } _dispatchEvent(method, params2) { if (this._disposed) { if (isUnderTest()) throw new Error(`${this._guid} is sending "${String(method)}" event after being disposed`); return; } this.connection.sendEvent(this, method, params2); } _dispose(reason) { this._disposeRecursively(new TargetClosedError(this._object.closeReason())); this.connection.sendDispose(this, reason); } _onDispose() { } async stopPendingOperations(error) { const controllers = []; const collect = (dispatcher) => { controllers.push(...dispatcher._activeProgressControllers); for (const child of [...dispatcher._dispatchers.values()]) collect(child); }; collect(this); await Promise.all(controllers.map((controller) => controller.abort(error))); } _disposeRecursively(error) { assert(!this._disposed, `${this._guid} is disposed more than once`); this._onDispose(); this._disposed = true; eventsHelper.removeEventListeners(this._eventListeners); this._parent?._dispatchers.delete(this._guid); const list = this.connection._dispatchersByBucket.get(this._gcBucket); list?.delete(this._guid); this.connection._dispatcherByGuid.delete(this._guid); this.connection._dispatcherByObject.delete(this._object); for (const dispatcher of [...this._dispatchers.values()]) dispatcher._disposeRecursively(error); this._dispatchers.clear(); } _debugScopeState() { return { _guid: this._guid, objects: Array.from(this._dispatchers.values()).map((o) => o._debugScopeState()) }; } }; RootDispatcher = class extends Dispatcher { constructor(connection, createPlaywright2) { super(connection, createRootSdkObject(), "Root", {}); this.createPlaywright = createPlaywright2; this._initialized = false; } async initialize(params2, progress2) { assert(this.createPlaywright); assert(!this._initialized); this._initialized = true; return { playwright: await progress2.race(this.createPlaywright(this, params2)) }; } }; DispatcherConnection = class { constructor(isInProcess) { this._dispatcherByGuid = /* @__PURE__ */ new Map(); this._dispatcherByObject = /* @__PURE__ */ new Map(); this._dispatchersByBucket = /* @__PURE__ */ new Map(); this.onmessage = (message) => { }; this._waitOperations = /* @__PURE__ */ new Map(); this._isInProcess = !!isInProcess; } sendEvent(dispatcher, event, params2) { const validator = findValidator(dispatcher._type, event, "Event"); params2 = validator(params2, "", this._validatorToWireContext()); this.onmessage({ guid: dispatcher._guid, method: event, params: params2 }); } sendCreate(parent, type3, guid, initializer) { const validator = findValidator(type3, "", "Initializer"); initializer = validator(initializer, "", this._validatorToWireContext()); this.onmessage({ guid: parent._guid, method: "__create__", params: { type: type3, initializer, guid } }); } sendAdopt(parent, dispatcher) { this.onmessage({ guid: parent._guid, method: "__adopt__", params: { guid: dispatcher._guid } }); } sendDispose(dispatcher, reason) { this.onmessage({ guid: dispatcher._guid, method: "__dispose__", params: { reason } }); } _validatorToWireContext() { return { tChannelImpl: this._tChannelImplToWire.bind(this), binary: this._isInProcess ? "buffer" : "toBase64", isUnderTest }; } _validatorFromWireContext() { return { tChannelImpl: this._tChannelImplFromWire.bind(this), binary: this._isInProcess ? "buffer" : "fromBase64", isUnderTest }; } _tChannelImplFromWire(names, arg, path59, context2) { if (arg && typeof arg === "object" && typeof arg.guid === "string") { const guid = arg.guid; const dispatcher = this._dispatcherByGuid.get(guid); if (!dispatcher) throw new ValidationError(`${path59}: no object with guid ${guid}`); if (names !== "*" && !names.includes(dispatcher._type)) throw new ValidationError(`${path59}: object with guid ${guid} has type ${dispatcher._type}, expected ${names.toString()}`); return dispatcher; } throw new ValidationError(`${path59}: expected guid for ${names.toString()}`); } _tChannelImplToWire(names, arg, path59, context2) { if (arg instanceof Dispatcher) { if (names !== "*" && !names.includes(arg._type)) throw new ValidationError(`${path59}: dispatcher with guid ${arg._guid} has type ${arg._type}, expected ${names.toString()}`); return { guid: arg._guid }; } throw new ValidationError(`${path59}: expected dispatcher ${names.toString()}`); } existingDispatcher(object) { return this._dispatcherByObject.get(object); } registerDispatcher(dispatcher) { assert(!this._dispatcherByGuid.has(dispatcher._guid)); this._dispatcherByGuid.set(dispatcher._guid, dispatcher); this._dispatcherByObject.set(dispatcher._object, dispatcher); let list = this._dispatchersByBucket.get(dispatcher._gcBucket); if (!list) { list = /* @__PURE__ */ new Set(); this._dispatchersByBucket.set(dispatcher._gcBucket, list); } list.add(dispatcher._guid); } maybeDisposeStaleDispatchers(gcBucket) { const maxDispatchers = maxDispatchersForBucket(gcBucket); const list = this._dispatchersByBucket.get(gcBucket); if (!list || list.size <= maxDispatchers) return; const dispatchersArray = [...list]; const disposeCount = maxDispatchers / 10 | 0; this._dispatchersByBucket.set(gcBucket, new Set(dispatchersArray.slice(disposeCount))); for (let i = 0; i < disposeCount; ++i) { const d = this._dispatcherByGuid.get(dispatchersArray[i]); if (!d) continue; d._dispose("gc"); } } async dispatch(message) { const { id, guid, method, params: params2, metadata } = message; const dispatcher = this._dispatcherByGuid.get(guid); if (method === "__waitInfo__") { if (dispatcher) await this._dispatchWaitInfo(id, dispatcher, params2, metadata); return; } if (!dispatcher) { this.onmessage({ id, error: serializeError(new TargetClosedError(void 0)) }); return; } let validParams; let validMetadata; try { const validator = findValidator(dispatcher._type, method, "Params"); const validatorContext = this._validatorFromWireContext(); validParams = validator(params2, "", validatorContext); validMetadata = metadataValidator(metadata, "", validatorContext); if (typeof dispatcher[method] !== "function") throw new Error(`Mismatching dispatcher: "${dispatcher._type}" does not implement "${method}"`); } catch (e) { this.onmessage({ id, error: serializeError(e) }); return; } const metainfo = getMetainfo({ type: dispatcher._type, method }); if (metainfo?.internal) { validMetadata.internal = true; } const sdkObject = dispatcher._object; const callMetadata = { id: `call@${id}`, location: validMetadata.location, title: validMetadata.title, internal: validMetadata.internal, stepId: validMetadata.stepId, objectId: sdkObject.guid, pageId: sdkObject.attribution?.page?.guid, frameId: sdkObject.attribution?.frame?.guid, startTime: monotonicTime(), endTime: 0, type: dispatcher._type, method, params: params2 || {}, log: [] }; await sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata); const response2 = { id }; try { if (this._dispatcherByGuid.get(guid) !== dispatcher) throw new TargetClosedError(sdkObject.closeReason()); const result2 = await dispatcher._runCommand(callMetadata, method, validParams); const validator = findValidator(dispatcher._type, method, "Result"); response2.result = validator(result2, "", this._validatorToWireContext()); callMetadata.result = result2; } catch (e) { if (isTargetClosedError(e)) { const reason = sdkObject.closeReason(); if (reason) rewriteErrorMessage(e, reason); } else if (isProtocolError(e)) { if (e.type === "closed") e = new TargetClosedError(sdkObject.closeReason(), e.browserLogMessage()); else if (e.type === "crashed") rewriteErrorMessage(e, "Target crashed " + e.browserLogMessage()); } response2.error = serializeError(e); const detailsValidator = maybeFindValidator(dispatcher._type, method, "ErrorDetails"); if (detailsValidator) response2.errorDetails = detailsValidator(e?.details ?? {}, "", this._validatorToWireContext()); callMetadata.error = response2.error; } finally { callMetadata.endTime = monotonicTime(); await sdkObject.instrumentation.onAfterCall(sdkObject, callMetadata); if (metainfo?.slowMo) await this._doSlowMo(sdkObject); } if (response2.error) response2.log = compressCallLog(callMetadata.log); this.onmessage(response2); } async _doSlowMo(sdkObject) { const slowMo = sdkObject.attribution.browser?.options.slowMo; if (slowMo) await new Promise((f) => setTimeout(f, slowMo)); } async _dispatchWaitInfo(id, dispatcher, params2, metadata) { let info; let validMetadata; try { const validatorContext = this._validatorFromWireContext(); info = waitInfoValidator(params2, "", validatorContext); validMetadata = metadataValidator(metadata, "", validatorContext); } catch { return; } const sdkObject = dispatcher._object; if (info.phase === "before") { const callMetadata = { id: `call@${id}`, location: validMetadata.location, title: validMetadata.title, internal: validMetadata.internal, stepId: validMetadata.stepId, objectId: sdkObject.guid, pageId: sdkObject.attribution?.page?.guid, frameId: sdkObject.attribution?.frame?.guid, startTime: monotonicTime(), endTime: 0, type: dispatcher._type, method: "__waitInfo__", params: params2 || {}, log: [] }; this._waitOperations.set(info.waitId, callMetadata); await sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata).catch(() => { }); return; } const originalMetadata = this._waitOperations.get(info.waitId); if (!originalMetadata) return; if (info.phase === "log" && info.message) { originalMetadata.log.push(info.message); sdkObject.instrumentation.onCallLog(sdkObject, originalMetadata, "api", info.message); return; } if (info.phase === "after") { originalMetadata.endTime = monotonicTime(); originalMetadata.error = info.error ? { error: { name: "Error", message: info.error } } : void 0; this._waitOperations.delete(info.waitId); await sdkObject.instrumentation.onAfterCall(sdkObject, originalMetadata).catch(() => { }); } } }; } }); // packages/isomorphic/utilityScriptSerializers.ts function isRegExp5(obj) { try { return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]"; } catch (error) { return false; } } function isDate2(obj) { try { return obj instanceof Date || Object.prototype.toString.call(obj) === "[object Date]"; } catch (error) { return false; } } function isURL2(obj) { try { return obj instanceof URL || Object.prototype.toString.call(obj) === "[object URL]"; } catch (error) { return false; } } function isError3(obj) { try { return obj instanceof Error || obj && Object.getPrototypeOf(obj)?.name === "Error"; } catch (error) { return false; } } function isTypedArray(obj, constructor) { try { return obj instanceof constructor || Object.prototype.toString.call(obj) === `[object ${constructor.name}]`; } catch (error) { return false; } } function isArrayBuffer(obj) { try { return obj instanceof ArrayBuffer || Object.prototype.toString.call(obj) === "[object ArrayBuffer]"; } catch (error) { return false; } } function typedArrayToBase64(array) { if ("toBase64" in array) return array.toBase64(); const binary = Array.from(new Uint8Array(array.buffer, array.byteOffset, array.byteLength)).map((b) => String.fromCharCode(b)).join(""); return btoa(binary); } function base64ToTypedArray(base64, TypedArrayConstructor) { const binary = atob(base64); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i); return new TypedArrayConstructor(bytes.buffer); } function parseEvaluationResultValue(value2, handles = [], refs = /* @__PURE__ */ new Map()) { if (Object.is(value2, void 0)) return void 0; if (typeof value2 === "object" && value2) { if ("ref" in value2) return refs.get(value2.ref); if ("v" in value2) { if (value2.v === "undefined") return void 0; if (value2.v === "null") return null; if (value2.v === "NaN") return NaN; if (value2.v === "Infinity") return Infinity; if (value2.v === "-Infinity") return -Infinity; if (value2.v === "-0") return -0; return void 0; } if ("d" in value2) { return new Date(value2.d); } if ("u" in value2) return new URL(value2.u); if ("bi" in value2) return BigInt(value2.bi); if ("e" in value2) { const error = new Error(value2.e.m); error.name = value2.e.n; error.stack = value2.e.s; return error; } if ("r" in value2) return new RegExp(value2.r.p, value2.r.f); if ("a" in value2) { const result2 = []; refs.set(value2.id, result2); for (const a of value2.a) result2.push(parseEvaluationResultValue(a, handles, refs)); return result2; } if ("o" in value2) { const result2 = {}; refs.set(value2.id, result2); for (const { k, v } of value2.o) { if (k === "__proto__") continue; result2[k] = parseEvaluationResultValue(v, handles, refs); } return result2; } if ("h" in value2) return handles[value2.h]; if ("ta" in value2) return base64ToTypedArray(value2.ta.b, typedArrayConstructors[value2.ta.k]); if ("ab" in value2) return base64ToTypedArray(value2.ab.b, Uint8Array).buffer; } return value2; } function serializeAsCallArgument(value2, handleSerializer) { return serialize(value2, handleSerializer, { visited: /* @__PURE__ */ new Map(), lastId: 0 }); } function serialize(value2, handleSerializer, visitorInfo) { if (value2 && typeof value2 === "object") { if (typeof globalThis.Window === "function" && value2 instanceof globalThis.Window) return "ref: "; if (typeof globalThis.Document === "function" && value2 instanceof globalThis.Document) return "ref: "; if (typeof globalThis.Node === "function" && value2 instanceof globalThis.Node) return "ref: "; } return innerSerialize(value2, handleSerializer, visitorInfo); } function innerSerialize(value2, handleSerializer, visitorInfo) { const result2 = handleSerializer(value2); if ("fallThrough" in result2) value2 = result2.fallThrough; else return result2; if (typeof value2 === "symbol") return { v: "undefined" }; if (Object.is(value2, void 0)) return { v: "undefined" }; if (Object.is(value2, null)) return { v: "null" }; if (Object.is(value2, NaN)) return { v: "NaN" }; if (Object.is(value2, Infinity)) return { v: "Infinity" }; if (Object.is(value2, -Infinity)) return { v: "-Infinity" }; if (Object.is(value2, -0)) return { v: "-0" }; if (typeof value2 === "boolean") return value2; if (typeof value2 === "number") return value2; if (typeof value2 === "string") return value2; if (typeof value2 === "bigint") return { bi: value2.toString() }; if (isError3(value2)) { let stack; if (value2.stack?.startsWith(value2.name + ": " + value2.message)) { stack = value2.stack; } else { stack = `${value2.name}: ${value2.message} ${value2.stack}`; } return { e: { n: value2.name, m: value2.message, s: stack } }; } if (isDate2(value2)) return { d: value2.toJSON() }; if (isURL2(value2)) return { u: value2.toJSON() }; if (isRegExp5(value2)) return { r: { p: value2.source, f: value2.flags } }; for (const [k, ctor] of Object.entries(typedArrayConstructors)) { if (isTypedArray(value2, ctor)) return { ta: { b: typedArrayToBase64(value2), k } }; } if (isArrayBuffer(value2)) return { ab: { b: typedArrayToBase64(new Uint8Array(value2)) } }; const id = visitorInfo.visited.get(value2); if (id) return { ref: id }; if (Array.isArray(value2)) { const a = []; const id2 = ++visitorInfo.lastId; visitorInfo.visited.set(value2, id2); for (let i = 0; i < value2.length; ++i) a.push(serialize(value2[i], handleSerializer, visitorInfo)); return { a, id: id2 }; } if (typeof value2 === "object") { const o = []; const id2 = ++visitorInfo.lastId; visitorInfo.visited.set(value2, id2); for (const name of Object.keys(value2)) { let item; try { item = value2[name]; } catch (e) { continue; } if (name === "toJSON" && typeof item === "function") o.push({ k: name, v: { o: [], id: 0 } }); else o.push({ k: name, v: serialize(item, handleSerializer, visitorInfo) }); } let jsonWrapper; try { if (o.length === 0 && value2.toJSON && typeof value2.toJSON === "function") jsonWrapper = { value: value2.toJSON() }; } catch (e) { } if (jsonWrapper) return innerSerialize(jsonWrapper.value, handleSerializer, visitorInfo); return { o, id: id2 }; } } var typedArrayConstructors; var init_utilityScriptSerializers = __esm({ "packages/isomorphic/utilityScriptSerializers.ts"() { "use strict"; typedArrayConstructors = { i8: Int8Array, ui8: Uint8Array, ui8c: Uint8ClampedArray, i16: Int16Array, ui16: Uint16Array, i32: Int32Array, ui32: Uint32Array, // TODO: add Float16Array once it's in baseline f32: Float32Array, f64: Float64Array, bi64: BigInt64Array, bui64: BigUint64Array }; } }); // packages/playwright-core/src/generated/utilityScriptSource.ts var source3; var init_utilityScriptSource = __esm({ "packages/playwright-core/src/generated/utilityScriptSource.ts"() { "use strict"; source3 = '\nvar __commonJS = obj => {\n let required = false;\n let result;\n return function __require() {\n if (!required) {\n required = true;\n let fn;\n for (const name in obj) { fn = obj[name]; break; }\n const module = { exports: {} };\n fn(module.exports, module);\n result = module.exports;\n }\n return result;\n }\n};\nvar __export = (target, all) => {for (var name in all) target[name] = all[name];};\nvar __toESM = mod => ({ ...mod, \'default\': mod });\nvar __toCommonJS = mod => ({ ...mod, __esModule: true });\n\n\n// packages/injected/src/utilityScript.ts\nvar utilityScript_exports = {};\n__export(utilityScript_exports, {\n UtilityScript: () => UtilityScript\n});\nmodule.exports = __toCommonJS(utilityScript_exports);\n\n// packages/isomorphic/utilityScriptSerializers.ts\nfunction isRegExp(obj) {\n try {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]";\n } catch (error) {\n return false;\n }\n}\nfunction isDate(obj) {\n try {\n return obj instanceof Date || Object.prototype.toString.call(obj) === "[object Date]";\n } catch (error) {\n return false;\n }\n}\nfunction isURL(obj) {\n try {\n return obj instanceof URL || Object.prototype.toString.call(obj) === "[object URL]";\n } catch (error) {\n return false;\n }\n}\nfunction isError(obj) {\n var _a;\n try {\n return obj instanceof Error || obj && ((_a = Object.getPrototypeOf(obj)) == null ? void 0 : _a.name) === "Error";\n } catch (error) {\n return false;\n }\n}\nfunction isTypedArray(obj, constructor) {\n try {\n return obj instanceof constructor || Object.prototype.toString.call(obj) === `[object ${constructor.name}]`;\n } catch (error) {\n return false;\n }\n}\nfunction isArrayBuffer(obj) {\n try {\n return obj instanceof ArrayBuffer || Object.prototype.toString.call(obj) === "[object ArrayBuffer]";\n } catch (error) {\n return false;\n }\n}\nvar typedArrayConstructors = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n // TODO: add Float16Array once it\'s in baseline\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array\n};\nfunction typedArrayToBase64(array) {\n if ("toBase64" in array)\n return array.toBase64();\n const binary = Array.from(new Uint8Array(array.buffer, array.byteOffset, array.byteLength)).map((b) => String.fromCharCode(b)).join("");\n return btoa(binary);\n}\nfunction base64ToTypedArray(base64, TypedArrayConstructor) {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return new TypedArrayConstructor(bytes.buffer);\n}\nfunction parseEvaluationResultValue(value, handles = [], refs = /* @__PURE__ */ new Map()) {\n if (Object.is(value, void 0))\n return void 0;\n if (typeof value === "object" && value) {\n if ("ref" in value)\n return refs.get(value.ref);\n if ("v" in value) {\n if (value.v === "undefined")\n return void 0;\n if (value.v === "null")\n return null;\n if (value.v === "NaN")\n return NaN;\n if (value.v === "Infinity")\n return Infinity;\n if (value.v === "-Infinity")\n return -Infinity;\n if (value.v === "-0")\n return -0;\n return void 0;\n }\n if ("d" in value) {\n return new Date(value.d);\n }\n if ("u" in value)\n return new URL(value.u);\n if ("bi" in value)\n return BigInt(value.bi);\n if ("e" in value) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if ("r" in value)\n return new RegExp(value.r.p, value.r.f);\n if ("a" in value) {\n const result = [];\n refs.set(value.id, result);\n for (const a of value.a)\n result.push(parseEvaluationResultValue(a, handles, refs));\n return result;\n }\n if ("o" in value) {\n const result = {};\n refs.set(value.id, result);\n for (const { k, v } of value.o) {\n if (k === "__proto__")\n continue;\n result[k] = parseEvaluationResultValue(v, handles, refs);\n }\n return result;\n }\n if ("h" in value)\n return handles[value.h];\n if ("ta" in value)\n return base64ToTypedArray(value.ta.b, typedArrayConstructors[value.ta.k]);\n if ("ab" in value)\n return base64ToTypedArray(value.ab.b, Uint8Array).buffer;\n }\n return value;\n}\nfunction serializeAsCallArgument(value, handleSerializer) {\n return serialize(value, handleSerializer, { visited: /* @__PURE__ */ new Map(), lastId: 0 });\n}\nfunction serialize(value, handleSerializer, visitorInfo) {\n if (value && typeof value === "object") {\n if (typeof globalThis.Window === "function" && value instanceof globalThis.Window)\n return "ref: ";\n if (typeof globalThis.Document === "function" && value instanceof globalThis.Document)\n return "ref: ";\n if (typeof globalThis.Node === "function" && value instanceof globalThis.Node)\n return "ref: ";\n }\n return innerSerialize(value, handleSerializer, visitorInfo);\n}\nfunction innerSerialize(value, handleSerializer, visitorInfo) {\n var _a;\n const result = handleSerializer(value);\n if ("fallThrough" in result)\n value = result.fallThrough;\n else\n return result;\n if (typeof value === "symbol")\n return { v: "undefined" };\n if (Object.is(value, void 0))\n return { v: "undefined" };\n if (Object.is(value, null))\n return { v: "null" };\n if (Object.is(value, NaN))\n return { v: "NaN" };\n if (Object.is(value, Infinity))\n return { v: "Infinity" };\n if (Object.is(value, -Infinity))\n return { v: "-Infinity" };\n if (Object.is(value, -0))\n return { v: "-0" };\n if (typeof value === "boolean")\n return value;\n if (typeof value === "number")\n return value;\n if (typeof value === "string")\n return value;\n if (typeof value === "bigint")\n return { bi: value.toString() };\n if (isError(value)) {\n let stack;\n if ((_a = value.stack) == null ? void 0 : _a.startsWith(value.name + ": " + value.message)) {\n stack = value.stack;\n } else {\n stack = `${value.name}: ${value.message}\n${value.stack}`;\n }\n return { e: { n: value.name, m: value.message, s: stack } };\n }\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n for (const [k, ctor] of Object.entries(typedArrayConstructors)) {\n if (isTypedArray(value, ctor))\n return { ta: { b: typedArrayToBase64(value), k } };\n }\n if (isArrayBuffer(value))\n return { ab: { b: typedArrayToBase64(new Uint8Array(value)) } };\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n if (Array.isArray(value)) {\n const a = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (let i = 0; i < value.length; ++i)\n a.push(serialize(value[i], handleSerializer, visitorInfo));\n return { a, id: id2 };\n }\n if (typeof value === "object") {\n const o = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (const name of Object.keys(value)) {\n let item;\n try {\n item = value[name];\n } catch (e) {\n continue;\n }\n if (name === "toJSON" && typeof item === "function")\n o.push({ k: name, v: { o: [], id: 0 } });\n else\n o.push({ k: name, v: serialize(item, handleSerializer, visitorInfo) });\n }\n let jsonWrapper;\n try {\n if (o.length === 0 && value.toJSON && typeof value.toJSON === "function")\n jsonWrapper = { value: value.toJSON() };\n } catch (e) {\n }\n if (jsonWrapper)\n return innerSerialize(jsonWrapper.value, handleSerializer, visitorInfo);\n return { o, id: id2 };\n }\n}\n\n// packages/injected/src/utilityScript.ts\nvar UtilityScript = class {\n constructor(global, isUnderTest) {\n var _a, _b, _c, _d, _e, _f, _g, _h;\n this.global = global;\n this.isUnderTest = isUnderTest;\n if (global.__pwClock) {\n this.builtins = global.__pwClock.builtins;\n } else {\n this.builtins = {\n setTimeout: (_a = global.setTimeout) == null ? void 0 : _a.bind(global),\n clearTimeout: (_b = global.clearTimeout) == null ? void 0 : _b.bind(global),\n setInterval: (_c = global.setInterval) == null ? void 0 : _c.bind(global),\n clearInterval: (_d = global.clearInterval) == null ? void 0 : _d.bind(global),\n requestAnimationFrame: (_e = global.requestAnimationFrame) == null ? void 0 : _e.bind(global),\n cancelAnimationFrame: (_f = global.cancelAnimationFrame) == null ? void 0 : _f.bind(global),\n requestIdleCallback: (_g = global.requestIdleCallback) == null ? void 0 : _g.bind(global),\n cancelIdleCallback: (_h = global.cancelIdleCallback) == null ? void 0 : _h.bind(global),\n performance: global.performance,\n Intl: global.Intl,\n Date: global.Date,\n AbortSignal: global.AbortSignal\n };\n }\n if (this.isUnderTest)\n global.builtins = this.builtins;\n }\n evaluate(isFunction, returnByValue, expression, argCount, ...argsAndHandles) {\n const args = argsAndHandles.slice(0, argCount);\n const handles = argsAndHandles.slice(argCount);\n const parameters = [];\n for (let i = 0; i < args.length; i++)\n parameters[i] = parseEvaluationResultValue(args[i], handles);\n let result = this.global.eval(expression);\n if (isFunction === true) {\n result = result(...parameters);\n } else if (isFunction === false) {\n result = result;\n } else {\n if (typeof result === "function")\n result = result(...parameters);\n }\n return returnByValue ? this._promiseAwareJsonValueNoThrow(result) : result;\n }\n jsonValue(returnByValue, value) {\n if (value === void 0)\n return void 0;\n return serializeAsCallArgument(value, (value2) => ({ fallThrough: value2 }));\n }\n _promiseAwareJsonValueNoThrow(value) {\n const safeJson = (value2) => {\n try {\n return this.jsonValue(true, value2);\n } catch (e) {\n return void 0;\n }\n };\n if (value && typeof value === "object" && typeof value.then === "function") {\n return (async () => {\n const promiseValue = await value;\n return safeJson(promiseValue);\n })();\n }\n return safeJson(value);\n }\n};\n'; } }); // packages/playwright-core/src/server/javascript.ts async function evaluate(context2, returnByValue, pageFunction, ...args) { return evaluateExpression(context2, String(pageFunction), { returnByValue, isFunction: typeof pageFunction === "function" }, ...args); } async function evaluateExpression(context2, expression2, options, ...args) { expression2 = normalizeEvaluationExpression(expression2, options.isFunction); const handles = []; const toDispose = []; const pushHandle = (handle) => { handles.push(handle); return handles.length - 1; }; args = args.map((arg) => serializeAsCallArgument(arg, (handle) => { if (handle instanceof JSHandle) { if (!handle._objectId) return { fallThrough: handle._value }; if (handle._disposed) throw new JavaScriptErrorInEvaluate("JSHandle is disposed!"); const adopted = context2.adoptIfNeeded(handle); if (adopted === null) return { h: pushHandle(Promise.resolve(handle)) }; toDispose.push(adopted); return { h: pushHandle(adopted) }; } return { fallThrough: handle }; })); const utilityScriptObjects = []; for (const handle of await Promise.all(handles)) { if (handle._context !== context2) throw new JavaScriptErrorInEvaluate("JSHandles can be evaluated only in the context they were created!"); utilityScriptObjects.push(handle); } const utilityScriptValues = [options.isFunction, options.returnByValue, expression2, args.length, ...args]; const script = `(utilityScript, ...args) => utilityScript.evaluate(...args)`; try { return await context2._evaluateWithArguments(script, options.returnByValue || false, utilityScriptValues, utilityScriptObjects); } finally { toDispose.map((handlePromise) => handlePromise.then((handle) => handle.dispose())); } } function parseUnserializableValue(unserializableValue) { if (unserializableValue === "NaN") return NaN; if (unserializableValue === "Infinity") return Infinity; if (unserializableValue === "-Infinity") return -Infinity; if (unserializableValue === "-0") return -0; } function normalizeEvaluationExpression(expression2, isFunction2) { expression2 = expression2.trim(); if (isFunction2) { try { new Function("(" + expression2 + ")"); } catch (e1) { if (expression2.startsWith("async ")) expression2 = "async function " + expression2.substring("async ".length); else expression2 = "function " + expression2; try { new Function("(" + expression2 + ")"); } catch (e2) { throw new Error("Passed function is not well-serializable!"); } } } if (/^(async)?\s*function(\s|\()/.test(expression2)) expression2 = "(" + expression2 + ")"; return expression2; } function isJavaScriptErrorInEvaluate(error) { return error instanceof JavaScriptErrorInEvaluate; } function sparseArrayToString(entries) { const arrayEntries = []; for (const { name, value: value2 } of entries) { const index = +name; if (isNaN(index) || index < 0) continue; arrayEntries.push({ index, value: value2 }); } arrayEntries.sort((a, b) => a.index - b.index); let lastIndex = -1; const tokens = []; for (const { index, value: value2 } of arrayEntries) { const emptyItems = index - lastIndex - 1; if (emptyItems === 1) tokens.push(`empty`); else if (emptyItems > 1) tokens.push(`empty x ${emptyItems}`); tokens.push(String(value2)); lastIndex = index; } return "[" + tokens.join(", ") + "]"; } var ExecutionContext, JSHandle, JavaScriptErrorInEvaluate, snapshottedFunctionBuiltins, snapshottedObjectBuiltins, snapshottedTimerBuiltins, saveGlobalsSnapshotSource, mainWorldGlobalsSnapshotSource; var init_javascript = __esm({ "packages/playwright-core/src/server/javascript.ts"() { "use strict"; init_utilityScriptSerializers(); init_manualPromise(); init_debug(); init_instrumentation(); init_utilityScriptSource(); ExecutionContext = class extends SdkObject { constructor(parent, delegate, worldNameForTest, options) { super(parent, "execution-context"); this._contextDestroyedScope = new LongStandingScope(); this.worldNameForTest = worldNameForTest; this._noUtilityWorld = options?.noUtilityWorld; this.delegate = delegate; } contextDestroyed(reason) { this._contextDestroyedScope.close(new Error(reason)); } async raceAgainstContextDestroyed(promise) { return this._contextDestroyedScope.race(promise); } rawEvaluateJSON(expression2) { return this.raceAgainstContextDestroyed(this.delegate.rawEvaluateJSON(expression2)); } rawEvaluateHandle(expression2) { return this.raceAgainstContextDestroyed(this.delegate.rawEvaluateHandle(this, expression2)); } async _evaluateWithArguments(expression2, returnByValue, values, handles) { const utilityScript = await this._utilityScript(); return this.raceAgainstContextDestroyed(this.delegate.evaluateWithArguments(expression2, returnByValue, utilityScript, values, handles)); } getProperties(object) { return this.raceAgainstContextDestroyed(this.delegate.getProperties(object)); } _releaseHandle(handle) { return this.delegate.releaseHandle(handle); } adoptIfNeeded(handle) { return null; } _utilityScript() { if (!this._utilityScriptPromise) { const globalsSnapshot = this._noUtilityWorld ? mainWorldGlobalsSnapshotSource : ""; const source11 = ` (() => { ${globalsSnapshot} const module = {}; ${source3} return new (module.exports.UtilityScript())(globalThis, ${isUnderTest()}); })();`; this._utilityScriptPromise = this.raceAgainstContextDestroyed(this.delegate.rawEvaluateHandle(this, source11)).then((handle) => { handle._setPreview("UtilityScript"); return handle; }); } return this._utilityScriptPromise; } }; JSHandle = class extends SdkObject { constructor(context2, type3, preview, objectId, value2) { super(context2, "handle"); this.__jshandle = true; this._disposed = false; this._context = context2; this._objectId = objectId; this._value = value2; this._objectType = type3; this._preview = this._objectId ? preview || `JSHandle@${this._objectType}` : String(value2); if (this._objectId && globalThis.leakedJSHandles) globalThis.leakedJSHandles.set(this, new Error("Leaked JSHandle")); } async evaluateExpression(progress2, expression2, options, arg) { return await progress2.race(this.internalEvaluateExpression(expression2, options, arg)); } async evaluateExpressionHandle(progress2, expression2, options, arg) { return await progress2.race(this._evaluateExpressionHandle(expression2, options, arg)); } async getProperty(progress2, propertyName) { return await progress2.race(this._getProperty(propertyName)); } async getProperties(progress2) { return await progress2.race(this.internalGetProperties()); } async jsonValue(progress2) { return await progress2.race(this._jsonValue()); } async evaluate(pageFunction, arg) { return evaluate(this._context, true, pageFunction, this, arg); } async evaluateHandle(pageFunction, arg) { return evaluate(this._context, false, pageFunction, this, arg); } async internalEvaluateExpression(expression2, options, arg) { return await evaluateExpression(this._context, expression2, { ...options, returnByValue: true }, this, arg); } async _evaluateExpressionHandle(expression2, options, arg) { return await evaluateExpression(this._context, expression2, { ...options, returnByValue: false }, this, arg); } async _getProperty(propertyName) { const objectHandle = await this.evaluateHandle((object, propertyName2) => { const result3 = { __proto__: null }; result3[propertyName2] = object[propertyName2]; return result3; }, propertyName); const properties = await objectHandle.internalGetProperties(); const result2 = properties.get(propertyName); objectHandle.dispose(); return result2; } async internalGetProperties() { if (!this._objectId) return /* @__PURE__ */ new Map(); return this._context.getProperties(this); } rawValue() { return this._value; } async _jsonValue() { if (!this._objectId) return this._value; const script = `(utilityScript, ...args) => utilityScript.jsonValue(...args)`; return this._context._evaluateWithArguments(script, true, [true], [this]); } asElement() { return null; } dispose() { if (this._disposed) return; this._disposed = true; if (this._objectId) { this._context._releaseHandle(this).catch((e) => { }); if (globalThis.leakedJSHandles) globalThis.leakedJSHandles.delete(this); } } toString() { return this._preview; } _setPreviewCallback(callback) { this._previewCallback = callback; } preview() { return this._preview; } worldNameForTest() { return this._context.worldNameForTest; } _setPreview(preview) { this._preview = preview; if (this._previewCallback) this._previewCallback(preview); } }; JavaScriptErrorInEvaluate = class extends Error { }; snapshottedFunctionBuiltins = [ // DOM "Node", "Element", "NodeFilter", "HTMLElement", "Document", "ShadowRoot", "MutationObserver", "Event", "CustomEvent", "EventTarget", // JS standard "Map", "Set", "WeakMap", "WeakSet", "Promise", "Symbol", "Error", "TypeError", "RegExp", "Array", "Object" ]; snapshottedObjectBuiltins = ["JSON", "Math"]; snapshottedTimerBuiltins = ["setTimeout"]; saveGlobalsSnapshotSource = `window.__pwSnapshotGlobals = { ${[...snapshottedFunctionBuiltins, ...snapshottedObjectBuiltins, ...snapshottedTimerBuiltins].map((n) => ` ${n}: window.${n}`).join(",\n")} };`; mainWorldGlobalsSnapshotSource = ` const __snap = globalThis.__pwSnapshotGlobals || {}; ${snapshottedFunctionBuiltins.map((n) => ` const ${n} = (typeof globalThis.${n} === 'function' ? globalThis.${n} : __snap.${n});`).join("\n")} ${snapshottedObjectBuiltins.map((n) => ` const ${n} = (typeof globalThis.${n} === 'object' && globalThis.${n} ? globalThis.${n} : __snap.${n});`).join("\n")} `; } }); // packages/playwright-core/src/server/fileUploadUtils.ts async function filesExceedUploadLimit(files) { const sizes = await Promise.all(files.map(async (file) => (await import_fs13.default.promises.stat(file)).size)); return sizes.reduce((total, size) => total + size, 0) >= fileUploadSizeLimit; } async function prepareFilesForUpload(frame, params2) { const { payloads, streams, directoryStream } = params2; let { localPaths, localDirectory } = params2; if (localPaths && !frame.attribution.playwright.options.isClientCollocatedWithServer) throw new Error("localPaths are not allowed when the client is not local"); if ([payloads, localPaths, localDirectory, streams, directoryStream].filter(Boolean).length !== 1) throw new Error("Exactly one of payloads, localPaths and streams must be provided"); if (streams) localPaths = streams.map((c) => c.path()); if (directoryStream) localDirectory = directoryStream.path(); if (localPaths) { for (const p of localPaths) assert(import_path12.default.isAbsolute(p) && import_path12.default.resolve(p) === p, "Paths provided to localPaths must be absolute and fully resolved."); } let fileBuffers = payloads; if (!frame._page.browserContext._browser._isBrowserCollocatedWithServer) { if (localPaths) { if (await filesExceedUploadLimit(localPaths)) throw new Error("Cannot transfer files larger than 50Mb to a browser not co-located with the server"); fileBuffers = await Promise.all(localPaths.map(async (item) => { return { name: import_path12.default.basename(item), buffer: await import_fs13.default.promises.readFile(item), lastModifiedMs: (await import_fs13.default.promises.stat(item)).mtimeMs }; })); localPaths = void 0; } } const filePayloads = fileBuffers?.map((payload) => ({ name: payload.name, mimeType: payload.mimeType || mime4.getType(payload.name) || "application/octet-stream", buffer: payload.buffer.toString("base64"), lastModifiedMs: payload.lastModifiedMs })); return { localPaths, localDirectory, filePayloads }; } var import_fs13, import_path12, mime4, fileUploadSizeLimit; var init_fileUploadUtils = __esm({ "packages/playwright-core/src/server/fileUploadUtils.ts"() { "use strict"; import_fs13 = __toESM(require("fs")); import_path12 = __toESM(require("path")); init_assert(); mime4 = require("./utilsBundle").mime; fileUploadSizeLimit = 50 * 1024 * 1024; } }); // packages/playwright-core/src/generated/injectedScriptSource.ts var source4; var init_injectedScriptSource = __esm({ "packages/playwright-core/src/generated/injectedScriptSource.ts"() { "use strict"; source4 = '\nvar __commonJS = obj => {\n let required = false;\n let result;\n return function __require() {\n if (!required) {\n required = true;\n let fn;\n for (const name in obj) { fn = obj[name]; break; }\n const module = { exports: {} };\n fn(module.exports, module);\n result = module.exports;\n }\n return result;\n }\n};\nvar __export = (target, all) => {for (var name in all) target[name] = all[name];};\nvar __toESM = mod => ({ ...mod, \'default\': mod });\nvar __toCommonJS = mod => ({ ...mod, __esModule: true });\n\n\n// packages/injected/src/injectedScript.ts\nvar injectedScript_exports = {};\n__export(injectedScript_exports, {\n InjectedScript: () => InjectedScript\n});\nmodule.exports = __toCommonJS(injectedScript_exports);\n\n// packages/isomorphic/ariaSnapshot.ts\nfunction ariaNodesEqual(a, b) {\n if (a.role !== b.role || a.name !== b.name)\n return false;\n if (!ariaPropsEqual(a, b) || hasPointerCursor(a) !== hasPointerCursor(b))\n return false;\n const aKeys = Object.keys(a.props);\n const bKeys = Object.keys(b.props);\n return aKeys.length === bKeys.length && aKeys.every((k) => a.props[k] === b.props[k]);\n}\nfunction hasPointerCursor(ariaNode) {\n return ariaNode.box.cursor === "pointer";\n}\nfunction ariaPropsEqual(a, b) {\n return a.active === b.active && a.checked === b.checked && a.disabled === b.disabled && a.expanded === b.expanded && a.invalid === b.invalid && a.selected === b.selected && a.level === b.level && a.pressed === b.pressed;\n}\nfunction parseAriaSnapshot(yaml, text, options = {}) {\n var _a;\n const lineCounter = new yaml.LineCounter();\n const parseOptions = {\n keepSourceTokens: true,\n lineCounter,\n ...options\n };\n const yamlDoc = yaml.parseDocument(text, parseOptions);\n const errors = [];\n const convertRange = (range) => {\n return [lineCounter.linePos(range[0]), lineCounter.linePos(range[1])];\n };\n const addError = (error) => {\n errors.push({\n message: error.message,\n range: [lineCounter.linePos(error.pos[0]), lineCounter.linePos(error.pos[1])]\n });\n };\n const convertSeq = (container, seq) => {\n for (const item of seq.items) {\n const itemIsString = item instanceof yaml.Scalar && typeof item.value === "string";\n if (itemIsString) {\n const childNode = KeyParser.parse(item, parseOptions, errors);\n if (childNode) {\n container.children = container.children || [];\n container.children.push(childNode);\n }\n continue;\n }\n const itemIsMap = item instanceof yaml.YAMLMap;\n if (itemIsMap) {\n convertMap(container, item);\n continue;\n }\n errors.push({\n message: "Sequence items should be strings or maps",\n range: convertRange(item.range || seq.range)\n });\n }\n };\n const convertMap = (container, map) => {\n var _a2;\n for (const entry of map.items) {\n container.children = container.children || [];\n const keyIsString = entry.key instanceof yaml.Scalar && typeof entry.key.value === "string";\n if (!keyIsString) {\n errors.push({\n message: "Only string keys are supported",\n range: convertRange(entry.key.range || map.range)\n });\n continue;\n }\n const key = entry.key;\n const value = entry.value;\n if (key.value === "text") {\n const valueIsString = value instanceof yaml.Scalar && typeof value.value === "string";\n if (!valueIsString) {\n errors.push({\n message: "Text value should be a string",\n range: convertRange(entry.value.range || map.range)\n });\n continue;\n }\n container.children.push({\n kind: "text",\n text: textValue(value.value)\n });\n continue;\n }\n if (key.value === "/children") {\n const valueIsString = value instanceof yaml.Scalar && typeof value.value === "string";\n if (!valueIsString || value.value !== "contain" && value.value !== "equal" && value.value !== "deep-equal") {\n errors.push({\n message: \'Strict value should be "contain", "equal" or "deep-equal"\',\n range: convertRange(entry.value.range || map.range)\n });\n continue;\n }\n container.containerMode = value.value;\n continue;\n }\n if (key.value.startsWith("/")) {\n const valueIsString = value instanceof yaml.Scalar && typeof value.value === "string";\n if (!valueIsString) {\n errors.push({\n message: "Property value should be a string",\n range: convertRange(entry.value.range || map.range)\n });\n continue;\n }\n container.props = (_a2 = container.props) != null ? _a2 : {};\n container.props[key.value.slice(1)] = textValue(value.value);\n continue;\n }\n const childNode = KeyParser.parse(key, parseOptions, errors);\n if (!childNode)\n continue;\n const valueIsScalar = value instanceof yaml.Scalar;\n if (valueIsScalar) {\n const type = typeof value.value;\n if (type !== "string" && type !== "number" && type !== "boolean") {\n errors.push({\n message: "Node value should be a string or a sequence",\n range: convertRange(entry.value.range || map.range)\n });\n continue;\n }\n container.children.push({\n ...childNode,\n children: [{\n kind: "text",\n text: textValue(String(value.value))\n }]\n });\n continue;\n }\n const valueIsSequence = value instanceof yaml.YAMLSeq;\n if (valueIsSequence) {\n container.children.push(childNode);\n convertSeq(childNode, value);\n continue;\n }\n errors.push({\n message: "Map values should be strings or sequences",\n range: convertRange(entry.value.range || map.range)\n });\n }\n };\n const fragment = { kind: "role", role: "fragment" };\n yamlDoc.errors.forEach(addError);\n if (errors.length)\n return { errors, fragment };\n if (!(yamlDoc.contents instanceof yaml.YAMLSeq)) {\n errors.push({\n message: \'Aria snapshot must be a YAML sequence, elements starting with " -"\',\n range: yamlDoc.contents ? convertRange(yamlDoc.contents.range) : [{ line: 0, col: 0 }, { line: 0, col: 0 }]\n });\n }\n if (errors.length)\n return { errors, fragment };\n convertSeq(fragment, yamlDoc.contents);\n if (errors.length)\n return { errors, fragment: emptyFragment };\n if (((_a = fragment.children) == null ? void 0 : _a.length) === 1 && (!fragment.containerMode || fragment.containerMode === "contain"))\n return { fragment: fragment.children[0], errors: [] };\n return { fragment, errors: [] };\n}\nvar emptyFragment = { kind: "role", role: "fragment" };\nfunction normalizeWhitespace(text) {\n return text.replace(/[\\u200b\\u00ad]/g, "").replace(/[\\r\\n\\s\\t]+/g, " ").trim();\n}\nfunction textValue(value) {\n return {\n raw: value,\n normalized: normalizeWhitespace(value)\n };\n}\nvar KeyParser = class _KeyParser {\n static parse(text, options, errors) {\n try {\n return new _KeyParser(text.value)._parse();\n } catch (e) {\n if (e instanceof ParserError) {\n const message = options.prettyErrors === false ? e.message : e.message + ":\\n\\n" + text.value + "\\n" + " ".repeat(e.pos) + "^\\n";\n errors.push({\n message,\n range: [options.lineCounter.linePos(text.range[0]), options.lineCounter.linePos(text.range[0] + e.pos)]\n });\n return null;\n }\n throw e;\n }\n }\n constructor(input) {\n this._input = input;\n this._pos = 0;\n this._length = input.length;\n }\n _peek() {\n return this._input[this._pos] || "";\n }\n _next() {\n if (this._pos < this._length)\n return this._input[this._pos++];\n return null;\n }\n _eof() {\n return this._pos >= this._length;\n }\n _isWhitespace() {\n return !this._eof() && /\\s/.test(this._peek());\n }\n _skipWhitespace() {\n while (this._isWhitespace())\n this._pos++;\n }\n _readIdentifier(type) {\n if (this._eof())\n this._throwError(`Unexpected end of input when expecting ${type}`);\n const start = this._pos;\n while (!this._eof() && /[a-zA-Z]/.test(this._peek()))\n this._pos++;\n return this._input.slice(start, this._pos);\n }\n _readString() {\n let result = "";\n let escaped = false;\n while (!this._eof()) {\n const ch = this._next();\n if (escaped) {\n result += ch;\n escaped = false;\n } else if (ch === "\\\\") {\n escaped = true;\n } else if (ch === \'"\') {\n return result;\n } else {\n result += ch;\n }\n }\n this._throwError("Unterminated string");\n }\n _throwError(message, offset = 0) {\n throw new ParserError(message, offset || this._pos);\n }\n _readRegex() {\n let result = "";\n let escaped = false;\n let insideClass = false;\n while (!this._eof()) {\n const ch = this._next();\n if (escaped) {\n result += ch;\n escaped = false;\n } else if (ch === "\\\\") {\n escaped = true;\n result += ch;\n } else if (ch === "/" && !insideClass) {\n return { pattern: result };\n } else if (ch === "[") {\n insideClass = true;\n result += ch;\n } else if (ch === "]" && insideClass) {\n result += ch;\n insideClass = false;\n } else {\n result += ch;\n }\n }\n this._throwError("Unterminated regex");\n }\n _readStringOrRegex() {\n const ch = this._peek();\n if (ch === \'"\') {\n this._next();\n return normalizeWhitespace(this._readString());\n }\n if (ch === "/") {\n this._next();\n return this._readRegex();\n }\n return null;\n }\n _readAttributes(result) {\n let errorPos = this._pos;\n while (true) {\n this._skipWhitespace();\n if (this._peek() === "[") {\n this._next();\n this._skipWhitespace();\n errorPos = this._pos;\n const flagName = this._readIdentifier("attribute");\n this._skipWhitespace();\n let flagValue = "";\n if (this._peek() === "=") {\n this._next();\n this._skipWhitespace();\n errorPos = this._pos;\n while (this._peek() !== "]" && !this._isWhitespace() && !this._eof())\n flagValue += this._next();\n }\n this._skipWhitespace();\n if (this._peek() !== "]")\n this._throwError("Expected ]");\n this._next();\n this._applyAttribute(result, flagName, flagValue || "true", errorPos);\n } else {\n break;\n }\n }\n }\n _parse() {\n this._skipWhitespace();\n const role = this._readIdentifier("role");\n this._skipWhitespace();\n const name = this._readStringOrRegex() || "";\n const result = { kind: "role", role, name };\n this._readAttributes(result);\n this._skipWhitespace();\n if (!this._eof())\n this._throwError("Unexpected input");\n return result;\n }\n _applyAttribute(node, key, value, errorPos) {\n if (key === "checked") {\n this._assert(value === "true" || value === "false" || value === "mixed", \'Value of "checked" attribute must be a boolean or "mixed"\', errorPos);\n node.checked = value === "true" ? true : value === "false" ? false : "mixed";\n return;\n }\n if (key === "disabled") {\n this._assert(value === "true" || value === "false", \'Value of "disabled" attribute must be a boolean\', errorPos);\n node.disabled = value === "true";\n return;\n }\n if (key === "expanded") {\n this._assert(value === "true" || value === "false", \'Value of "expanded" attribute must be a boolean\', errorPos);\n node.expanded = value === "true";\n return;\n }\n if (key === "active") {\n this._assert(value === "true" || value === "false", \'Value of "active" attribute must be a boolean\', errorPos);\n node.active = value === "true";\n return;\n }\n if (key === "invalid") {\n this._assert(value === "true" || value === "false" || value === "grammar" || value === "spelling", \'Value of "invalid" attribute must be a boolean, "grammar" or "spelling"\', errorPos);\n node.invalid = value === "true" ? true : value === "false" ? false : value;\n return;\n }\n if (key === "level") {\n this._assert(!isNaN(Number(value)), \'Value of "level" attribute must be a number\', errorPos);\n node.level = Number(value);\n return;\n }\n if (key === "pressed") {\n this._assert(value === "true" || value === "false" || value === "mixed", \'Value of "pressed" attribute must be a boolean or "mixed"\', errorPos);\n node.pressed = value === "true" ? true : value === "false" ? false : "mixed";\n return;\n }\n if (key === "selected") {\n this._assert(value === "true" || value === "false", \'Value of "selected" attribute must be a boolean\', errorPos);\n node.selected = value === "true";\n return;\n }\n this._assert(false, `Unsupported attribute [${key}]`, errorPos);\n }\n _assert(value, message, valuePos) {\n if (!value)\n this._throwError(message || "Assertion error", valuePos);\n }\n};\nvar ParserError = class extends Error {\n constructor(message, pos) {\n super(message);\n this.pos = pos;\n }\n};\nfunction findNewNode(from, to) {\n var _a, _b;\n function fillMap(root, map, position) {\n let size = 1;\n let childPosition = position + size;\n for (const child of root.children || []) {\n if (typeof child === "string") {\n size++;\n childPosition++;\n } else {\n size += fillMap(child, map, childPosition);\n childPosition += size;\n }\n }\n if (!["none", "presentation", "fragment", "iframe", "generic"].includes(root.role) && root.name) {\n let byRole = map.get(root.role);\n if (!byRole) {\n byRole = /* @__PURE__ */ new Map();\n map.set(root.role, byRole);\n }\n const existing = byRole.get(root.name);\n const sizeAndPosition = size * 100 - position;\n if (!existing || existing.sizeAndPosition < sizeAndPosition)\n byRole.set(root.name, { node: root, sizeAndPosition });\n }\n return size;\n }\n const fromMap = /* @__PURE__ */ new Map();\n if (from)\n fillMap(from, fromMap, 0);\n const toMap = /* @__PURE__ */ new Map();\n fillMap(to, toMap, 0);\n const result = [];\n for (const [role, byRole] of toMap) {\n for (const [name, byName] of byRole) {\n const inFrom = (_a = fromMap.get(role)) == null ? void 0 : _a.get(name);\n if (!inFrom)\n result.push(byName);\n }\n }\n result.sort((a, b) => b.sizeAndPosition - a.sizeAndPosition);\n return (_b = result[0]) == null ? void 0 : _b.node;\n}\n\n// packages/isomorphic/cssTokenizer.ts\nvar between = function(num, first, last) {\n return num >= first && num <= last;\n};\nfunction digit(code) {\n return between(code, 48, 57);\n}\nfunction hexdigit(code) {\n return digit(code) || between(code, 65, 70) || between(code, 97, 102);\n}\nfunction uppercaseletter(code) {\n return between(code, 65, 90);\n}\nfunction lowercaseletter(code) {\n return between(code, 97, 122);\n}\nfunction letter(code) {\n return uppercaseletter(code) || lowercaseletter(code);\n}\nfunction nonascii(code) {\n return code >= 128;\n}\nfunction namestartchar(code) {\n return letter(code) || nonascii(code) || code === 95;\n}\nfunction namechar(code) {\n return namestartchar(code) || digit(code) || code === 45;\n}\nfunction nonprintable(code) {\n return between(code, 0, 8) || code === 11 || between(code, 14, 31) || code === 127;\n}\nfunction newline(code) {\n return code === 10;\n}\nfunction whitespace(code) {\n return newline(code) || code === 9 || code === 32;\n}\nvar maximumallowedcodepoint = 1114111;\nvar InvalidCharacterError = class extends Error {\n constructor(message) {\n super(message);\n this.name = "InvalidCharacterError";\n }\n};\nfunction preprocess(str) {\n const codepoints = [];\n for (let i = 0; i < str.length; i++) {\n let code = str.charCodeAt(i);\n if (code === 13 && str.charCodeAt(i + 1) === 10) {\n code = 10;\n i++;\n }\n if (code === 13 || code === 12)\n code = 10;\n if (code === 0)\n code = 65533;\n if (between(code, 55296, 56319) && between(str.charCodeAt(i + 1), 56320, 57343)) {\n const lead = code - 55296;\n const trail = str.charCodeAt(i + 1) - 56320;\n code = Math.pow(2, 16) + lead * Math.pow(2, 10) + trail;\n i++;\n }\n codepoints.push(code);\n }\n return codepoints;\n}\nfunction stringFromCode(code) {\n if (code <= 65535)\n return String.fromCharCode(code);\n code -= Math.pow(2, 16);\n const lead = Math.floor(code / Math.pow(2, 10)) + 55296;\n const trail = code % Math.pow(2, 10) + 56320;\n return String.fromCharCode(lead) + String.fromCharCode(trail);\n}\nfunction tokenize(str1) {\n const str = preprocess(str1);\n let i = -1;\n const tokens = [];\n let code;\n let line = 0;\n let column = 0;\n let lastLineLength = 0;\n const incrLineno = function() {\n line += 1;\n lastLineLength = column;\n column = 0;\n };\n const locStart = { line, column };\n const codepoint = function(i2) {\n if (i2 >= str.length)\n return -1;\n return str[i2];\n };\n const next = function(num) {\n if (num === void 0)\n num = 1;\n if (num > 3)\n throw "Spec Error: no more than three codepoints of lookahead.";\n return codepoint(i + num);\n };\n const consume = function(num) {\n if (num === void 0)\n num = 1;\n i += num;\n code = codepoint(i);\n if (newline(code))\n incrLineno();\n else\n column += num;\n return true;\n };\n const reconsume = function() {\n i -= 1;\n if (newline(code)) {\n line -= 1;\n column = lastLineLength;\n } else {\n column -= 1;\n }\n locStart.line = line;\n locStart.column = column;\n return true;\n };\n const eof = function(codepoint2) {\n if (codepoint2 === void 0)\n codepoint2 = code;\n return codepoint2 === -1;\n };\n const donothing = function() {\n };\n const parseerror = function() {\n };\n const consumeAToken = function() {\n consumeComments();\n consume();\n if (whitespace(code)) {\n while (whitespace(next()))\n consume();\n return new WhitespaceToken();\n } else if (code === 34) {\n return consumeAStringToken();\n } else if (code === 35) {\n if (namechar(next()) || areAValidEscape(next(1), next(2))) {\n const token = new HashToken("");\n if (wouldStartAnIdentifier(next(1), next(2), next(3)))\n token.type = "id";\n token.value = consumeAName();\n return token;\n } else {\n return new DelimToken(code);\n }\n } else if (code === 36) {\n if (next() === 61) {\n consume();\n return new SuffixMatchToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 39) {\n return consumeAStringToken();\n } else if (code === 40) {\n return new OpenParenToken();\n } else if (code === 41) {\n return new CloseParenToken();\n } else if (code === 42) {\n if (next() === 61) {\n consume();\n return new SubstringMatchToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 43) {\n if (startsWithANumber()) {\n reconsume();\n return consumeANumericToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 44) {\n return new CommaToken();\n } else if (code === 45) {\n if (startsWithANumber()) {\n reconsume();\n return consumeANumericToken();\n } else if (next(1) === 45 && next(2) === 62) {\n consume(2);\n return new CDCToken();\n } else if (startsWithAnIdentifier()) {\n reconsume();\n return consumeAnIdentlikeToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 46) {\n if (startsWithANumber()) {\n reconsume();\n return consumeANumericToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 58) {\n return new ColonToken();\n } else if (code === 59) {\n return new SemicolonToken();\n } else if (code === 60) {\n if (next(1) === 33 && next(2) === 45 && next(3) === 45) {\n consume(3);\n return new CDOToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 64) {\n if (wouldStartAnIdentifier(next(1), next(2), next(3)))\n return new AtKeywordToken(consumeAName());\n else\n return new DelimToken(code);\n } else if (code === 91) {\n return new OpenSquareToken();\n } else if (code === 92) {\n if (startsWithAValidEscape()) {\n reconsume();\n return consumeAnIdentlikeToken();\n } else {\n parseerror();\n return new DelimToken(code);\n }\n } else if (code === 93) {\n return new CloseSquareToken();\n } else if (code === 94) {\n if (next() === 61) {\n consume();\n return new PrefixMatchToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 123) {\n return new OpenCurlyToken();\n } else if (code === 124) {\n if (next() === 61) {\n consume();\n return new DashMatchToken();\n } else if (next() === 124) {\n consume();\n return new ColumnToken();\n } else {\n return new DelimToken(code);\n }\n } else if (code === 125) {\n return new CloseCurlyToken();\n } else if (code === 126) {\n if (next() === 61) {\n consume();\n return new IncludeMatchToken();\n } else {\n return new DelimToken(code);\n }\n } else if (digit(code)) {\n reconsume();\n return consumeANumericToken();\n } else if (namestartchar(code)) {\n reconsume();\n return consumeAnIdentlikeToken();\n } else if (eof()) {\n return new EOFToken();\n } else {\n return new DelimToken(code);\n }\n };\n const consumeComments = function() {\n while (next(1) === 47 && next(2) === 42) {\n consume(2);\n while (true) {\n consume();\n if (code === 42 && next() === 47) {\n consume();\n break;\n } else if (eof()) {\n parseerror();\n return;\n }\n }\n }\n };\n const consumeANumericToken = function() {\n const num = consumeANumber();\n if (wouldStartAnIdentifier(next(1), next(2), next(3))) {\n const token = new DimensionToken();\n token.value = num.value;\n token.repr = num.repr;\n token.type = num.type;\n token.unit = consumeAName();\n return token;\n } else if (next() === 37) {\n consume();\n const token = new PercentageToken();\n token.value = num.value;\n token.repr = num.repr;\n return token;\n } else {\n const token = new NumberToken();\n token.value = num.value;\n token.repr = num.repr;\n token.type = num.type;\n return token;\n }\n };\n const consumeAnIdentlikeToken = function() {\n const str2 = consumeAName();\n if (str2.toLowerCase() === "url" && next() === 40) {\n consume();\n while (whitespace(next(1)) && whitespace(next(2)))\n consume();\n if (next() === 34 || next() === 39)\n return new FunctionToken(str2);\n else if (whitespace(next()) && (next(2) === 34 || next(2) === 39))\n return new FunctionToken(str2);\n else\n return consumeAURLToken();\n } else if (next() === 40) {\n consume();\n return new FunctionToken(str2);\n } else {\n return new IdentToken(str2);\n }\n };\n const consumeAStringToken = function(endingCodePoint) {\n if (endingCodePoint === void 0)\n endingCodePoint = code;\n let string = "";\n while (consume()) {\n if (code === endingCodePoint || eof()) {\n return new StringToken(string);\n } else if (newline(code)) {\n parseerror();\n reconsume();\n return new BadStringToken();\n } else if (code === 92) {\n if (eof(next()))\n donothing();\n else if (newline(next()))\n consume();\n else\n string += stringFromCode(consumeEscape());\n } else {\n string += stringFromCode(code);\n }\n }\n throw new Error("Internal error");\n };\n const consumeAURLToken = function() {\n const token = new URLToken("");\n while (whitespace(next()))\n consume();\n if (eof(next()))\n return token;\n while (consume()) {\n if (code === 41 || eof()) {\n return token;\n } else if (whitespace(code)) {\n while (whitespace(next()))\n consume();\n if (next() === 41 || eof(next())) {\n consume();\n return token;\n } else {\n consumeTheRemnantsOfABadURL();\n return new BadURLToken();\n }\n } else if (code === 34 || code === 39 || code === 40 || nonprintable(code)) {\n parseerror();\n consumeTheRemnantsOfABadURL();\n return new BadURLToken();\n } else if (code === 92) {\n if (startsWithAValidEscape()) {\n token.value += stringFromCode(consumeEscape());\n } else {\n parseerror();\n consumeTheRemnantsOfABadURL();\n return new BadURLToken();\n }\n } else {\n token.value += stringFromCode(code);\n }\n }\n throw new Error("Internal error");\n };\n const consumeEscape = function() {\n consume();\n if (hexdigit(code)) {\n const digits = [code];\n for (let total = 0; total < 5; total++) {\n if (hexdigit(next())) {\n consume();\n digits.push(code);\n } else {\n break;\n }\n }\n if (whitespace(next()))\n consume();\n let value = parseInt(digits.map(function(x) {\n return String.fromCharCode(x);\n }).join(""), 16);\n if (value > maximumallowedcodepoint)\n value = 65533;\n return value;\n } else if (eof()) {\n return 65533;\n } else {\n return code;\n }\n };\n const areAValidEscape = function(c1, c2) {\n if (c1 !== 92)\n return false;\n if (newline(c2))\n return false;\n return true;\n };\n const startsWithAValidEscape = function() {\n return areAValidEscape(code, next());\n };\n const wouldStartAnIdentifier = function(c1, c2, c3) {\n if (c1 === 45)\n return namestartchar(c2) || c2 === 45 || areAValidEscape(c2, c3);\n else if (namestartchar(c1))\n return true;\n else if (c1 === 92)\n return areAValidEscape(c1, c2);\n else\n return false;\n };\n const startsWithAnIdentifier = function() {\n return wouldStartAnIdentifier(code, next(1), next(2));\n };\n const wouldStartANumber = function(c1, c2, c3) {\n if (c1 === 43 || c1 === 45) {\n if (digit(c2))\n return true;\n if (c2 === 46 && digit(c3))\n return true;\n return false;\n } else if (c1 === 46) {\n if (digit(c2))\n return true;\n return false;\n } else if (digit(c1)) {\n return true;\n } else {\n return false;\n }\n };\n const startsWithANumber = function() {\n return wouldStartANumber(code, next(1), next(2));\n };\n const consumeAName = function() {\n let result = "";\n while (consume()) {\n if (namechar(code)) {\n result += stringFromCode(code);\n } else if (startsWithAValidEscape()) {\n result += stringFromCode(consumeEscape());\n } else {\n reconsume();\n return result;\n }\n }\n throw new Error("Internal parse error");\n };\n const consumeANumber = function() {\n let repr = "";\n let type = "integer";\n if (next() === 43 || next() === 45) {\n consume();\n repr += stringFromCode(code);\n }\n while (digit(next())) {\n consume();\n repr += stringFromCode(code);\n }\n if (next(1) === 46 && digit(next(2))) {\n consume();\n repr += stringFromCode(code);\n consume();\n repr += stringFromCode(code);\n type = "number";\n while (digit(next())) {\n consume();\n repr += stringFromCode(code);\n }\n }\n const c1 = next(1);\n const c2 = next(2);\n const c3 = next(3);\n if ((c1 === 69 || c1 === 101) && digit(c2)) {\n consume();\n repr += stringFromCode(code);\n consume();\n repr += stringFromCode(code);\n type = "number";\n while (digit(next())) {\n consume();\n repr += stringFromCode(code);\n }\n } else if ((c1 === 69 || c1 === 101) && (c2 === 43 || c2 === 45) && digit(c3)) {\n consume();\n repr += stringFromCode(code);\n consume();\n repr += stringFromCode(code);\n consume();\n repr += stringFromCode(code);\n type = "number";\n while (digit(next())) {\n consume();\n repr += stringFromCode(code);\n }\n }\n const value = convertAStringToANumber(repr);\n return { type, value, repr };\n };\n const convertAStringToANumber = function(string) {\n return +string;\n };\n const consumeTheRemnantsOfABadURL = function() {\n while (consume()) {\n if (code === 41 || eof()) {\n return;\n } else if (startsWithAValidEscape()) {\n consumeEscape();\n donothing();\n } else {\n donothing();\n }\n }\n };\n let iterationCount = 0;\n while (!eof(next())) {\n tokens.push(consumeAToken());\n iterationCount++;\n if (iterationCount > str.length * 2)\n throw new Error("I\'m infinite-looping!");\n }\n return tokens;\n}\nvar CSSParserToken = class {\n constructor() {\n this.tokenType = "";\n }\n toJSON() {\n return { token: this.tokenType };\n }\n toString() {\n return this.tokenType;\n }\n toSource() {\n return "" + this;\n }\n};\nvar BadStringToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "BADSTRING";\n }\n};\nvar BadURLToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "BADURL";\n }\n};\nvar WhitespaceToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "WHITESPACE";\n }\n toString() {\n return "WS";\n }\n toSource() {\n return " ";\n }\n};\nvar CDOToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "CDO";\n }\n toSource() {\n return "";\n }\n};\nvar ColonToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = ":";\n }\n};\nvar SemicolonToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = ";";\n }\n};\nvar CommaToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = ",";\n }\n};\nvar GroupingToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.value = "";\n this.mirror = "";\n }\n};\nvar OpenCurlyToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = "{";\n this.value = "{";\n this.mirror = "}";\n }\n};\nvar CloseCurlyToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = "}";\n this.value = "}";\n this.mirror = "{";\n }\n};\nvar OpenSquareToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = "[";\n this.value = "[";\n this.mirror = "]";\n }\n};\nvar CloseSquareToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = "]";\n this.value = "]";\n this.mirror = "[";\n }\n};\nvar OpenParenToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = "(";\n this.value = "(";\n this.mirror = ")";\n }\n};\nvar CloseParenToken = class extends GroupingToken {\n constructor() {\n super();\n this.tokenType = ")";\n this.value = ")";\n this.mirror = "(";\n }\n};\nvar IncludeMatchToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "~=";\n }\n};\nvar DashMatchToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "|=";\n }\n};\nvar PrefixMatchToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "^=";\n }\n};\nvar SuffixMatchToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "$=";\n }\n};\nvar SubstringMatchToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "*=";\n }\n};\nvar ColumnToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "||";\n }\n};\nvar EOFToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.tokenType = "EOF";\n }\n toSource() {\n return "";\n }\n};\nvar DelimToken = class extends CSSParserToken {\n constructor(code) {\n super();\n this.tokenType = "DELIM";\n this.value = "";\n this.value = stringFromCode(code);\n }\n toString() {\n return "DELIM(" + this.value + ")";\n }\n toJSON() {\n const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);\n json.value = this.value;\n return json;\n }\n toSource() {\n if (this.value === "\\\\")\n return "\\\\\\n";\n else\n return this.value;\n }\n};\nvar StringValuedToken = class extends CSSParserToken {\n constructor() {\n super(...arguments);\n this.value = "";\n }\n ASCIIMatch(str) {\n return this.value.toLowerCase() === str.toLowerCase();\n }\n toJSON() {\n const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);\n json.value = this.value;\n return json;\n }\n};\nvar IdentToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "IDENT";\n this.value = val;\n }\n toString() {\n return "IDENT(" + this.value + ")";\n }\n toSource() {\n return escapeIdent(this.value);\n }\n};\nvar FunctionToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "FUNCTION";\n this.value = val;\n this.mirror = ")";\n }\n toString() {\n return "FUNCTION(" + this.value + ")";\n }\n toSource() {\n return escapeIdent(this.value) + "(";\n }\n};\nvar AtKeywordToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "AT-KEYWORD";\n this.value = val;\n }\n toString() {\n return "AT(" + this.value + ")";\n }\n toSource() {\n return "@" + escapeIdent(this.value);\n }\n};\nvar HashToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "HASH";\n this.value = val;\n this.type = "unrestricted";\n }\n toString() {\n return "HASH(" + this.value + ")";\n }\n toJSON() {\n const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);\n json.value = this.value;\n json.type = this.type;\n return json;\n }\n toSource() {\n if (this.type === "id")\n return "#" + escapeIdent(this.value);\n else\n return "#" + escapeHash(this.value);\n }\n};\nvar StringToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "STRING";\n this.value = val;\n }\n toString() {\n return \'"\' + escapeString(this.value) + \'"\';\n }\n};\nvar URLToken = class extends StringValuedToken {\n constructor(val) {\n super();\n this.tokenType = "URL";\n this.value = val;\n }\n toString() {\n return "URL(" + this.value + ")";\n }\n toSource() {\n return \'url("\' + escapeString(this.value) + \'")\';\n }\n};\nvar NumberToken = class extends CSSParserToken {\n constructor() {\n super();\n this.tokenType = "NUMBER";\n this.type = "integer";\n this.repr = "";\n }\n toString() {\n if (this.type === "integer")\n return "INT(" + this.value + ")";\n return "NUMBER(" + this.value + ")";\n }\n toJSON() {\n const json = super.toJSON();\n json.value = this.value;\n json.type = this.type;\n json.repr = this.repr;\n return json;\n }\n toSource() {\n return this.repr;\n }\n};\nvar PercentageToken = class extends CSSParserToken {\n constructor() {\n super();\n this.tokenType = "PERCENTAGE";\n this.repr = "";\n }\n toString() {\n return "PERCENTAGE(" + this.value + ")";\n }\n toJSON() {\n const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);\n json.value = this.value;\n json.repr = this.repr;\n return json;\n }\n toSource() {\n return this.repr + "%";\n }\n};\nvar DimensionToken = class extends CSSParserToken {\n constructor() {\n super();\n this.tokenType = "DIMENSION";\n this.type = "integer";\n this.repr = "";\n this.unit = "";\n }\n toString() {\n return "DIM(" + this.value + "," + this.unit + ")";\n }\n toJSON() {\n const json = this.constructor.prototype.constructor.prototype.toJSON.call(this);\n json.value = this.value;\n json.type = this.type;\n json.repr = this.repr;\n json.unit = this.unit;\n return json;\n }\n toSource() {\n const source = this.repr;\n let unit = escapeIdent(this.unit);\n if (unit[0].toLowerCase() === "e" && (unit[1] === "-" || between(unit.charCodeAt(1), 48, 57))) {\n unit = "\\\\65 " + unit.slice(1, unit.length);\n }\n return source + unit;\n }\n};\nfunction escapeIdent(string) {\n string = "" + string;\n let result = "";\n const firstcode = string.charCodeAt(0);\n for (let i = 0; i < string.length; i++) {\n const code = string.charCodeAt(i);\n if (code === 0)\n throw new InvalidCharacterError("Invalid character: the input contains U+0000.");\n if (between(code, 1, 31) || code === 127 || i === 0 && between(code, 48, 57) || i === 1 && between(code, 48, 57) && firstcode === 45)\n result += "\\\\" + code.toString(16) + " ";\n else if (code >= 128 || code === 45 || code === 95 || between(code, 48, 57) || between(code, 65, 90) || between(code, 97, 122))\n result += string[i];\n else\n result += "\\\\" + string[i];\n }\n return result;\n}\nfunction escapeHash(string) {\n string = "" + string;\n let result = "";\n for (let i = 0; i < string.length; i++) {\n const code = string.charCodeAt(i);\n if (code === 0)\n throw new InvalidCharacterError("Invalid character: the input contains U+0000.");\n if (code >= 128 || code === 45 || code === 95 || between(code, 48, 57) || between(code, 65, 90) || between(code, 97, 122))\n result += string[i];\n else\n result += "\\\\" + code.toString(16) + " ";\n }\n return result;\n}\nfunction escapeString(string) {\n string = "" + string;\n let result = "";\n for (let i = 0; i < string.length; i++) {\n const code = string.charCodeAt(i);\n if (code === 0)\n throw new InvalidCharacterError("Invalid character: the input contains U+0000.");\n if (between(code, 1, 31) || code === 127)\n result += "\\\\" + code.toString(16) + " ";\n else if (code === 34 || code === 92)\n result += "\\\\" + string[i];\n else\n result += string[i];\n }\n return result;\n}\n\n// packages/isomorphic/cssParser.ts\nvar InvalidSelectorError = class extends Error {\n};\nfunction parseCSS(selector, customNames) {\n let tokens;\n try {\n tokens = tokenize(selector);\n if (!(tokens[tokens.length - 1] instanceof EOFToken))\n tokens.push(new EOFToken());\n } catch (e) {\n const newMessage = e.message + ` while parsing css selector "${selector}". Did you mean to CSS.escape it?`;\n const index = (e.stack || "").indexOf(e.message);\n if (index !== -1)\n e.stack = e.stack.substring(0, index) + newMessage + e.stack.substring(index + e.message.length);\n e.message = newMessage;\n throw e;\n }\n const unsupportedToken = tokens.find((token) => {\n return token instanceof AtKeywordToken || token instanceof BadStringToken || token instanceof BadURLToken || token instanceof ColumnToken || token instanceof CDOToken || token instanceof CDCToken || token instanceof SemicolonToken || // TODO: Consider using these for something, e.g. to escape complex strings.\n // For example :xpath{ (//div/bar[@attr="foo"])[2]/baz }\n // Or this way :xpath( {complex-xpath-goes-here("hello")} )\n token instanceof OpenCurlyToken || token instanceof CloseCurlyToken || // TODO: Consider treating these as strings?\n token instanceof URLToken || token instanceof PercentageToken;\n });\n if (unsupportedToken)\n throw new InvalidSelectorError(`Unsupported token "${unsupportedToken.toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`);\n let pos = 0;\n const names = /* @__PURE__ */ new Set();\n function unexpected() {\n return new InvalidSelectorError(`Unexpected token "${tokens[pos].toSource()}" while parsing css selector "${selector}". Did you mean to CSS.escape it?`);\n }\n function skipWhitespace() {\n while (tokens[pos] instanceof WhitespaceToken)\n pos++;\n }\n function isIdent(p = pos) {\n return tokens[p] instanceof IdentToken;\n }\n function isString(p = pos) {\n return tokens[p] instanceof StringToken;\n }\n function isNumber(p = pos) {\n return tokens[p] instanceof NumberToken;\n }\n function isComma(p = pos) {\n return tokens[p] instanceof CommaToken;\n }\n function isOpenParen(p = pos) {\n return tokens[p] instanceof OpenParenToken;\n }\n function isCloseParen(p = pos) {\n return tokens[p] instanceof CloseParenToken;\n }\n function isFunction(p = pos) {\n return tokens[p] instanceof FunctionToken;\n }\n function isStar(p = pos) {\n return tokens[p] instanceof DelimToken && tokens[p].value === "*";\n }\n function isEOF(p = pos) {\n return tokens[p] instanceof EOFToken;\n }\n function isClauseCombinator(p = pos) {\n return tokens[p] instanceof DelimToken && [">", "+", "~"].includes(tokens[p].value);\n }\n function isSelectorClauseEnd(p = pos) {\n return isComma(p) || isCloseParen(p) || isEOF(p) || isClauseCombinator(p) || tokens[p] instanceof WhitespaceToken;\n }\n function consumeFunctionArguments() {\n const result2 = [consumeArgument()];\n while (true) {\n skipWhitespace();\n if (!isComma())\n break;\n pos++;\n result2.push(consumeArgument());\n }\n return result2;\n }\n function consumeArgument() {\n skipWhitespace();\n if (isNumber())\n return tokens[pos++].value;\n if (isString())\n return tokens[pos++].value;\n return consumeComplexSelector();\n }\n function consumeComplexSelector() {\n const result2 = { simples: [] };\n skipWhitespace();\n if (isClauseCombinator()) {\n result2.simples.push({ selector: { functions: [{ name: "scope", args: [] }] }, combinator: "" });\n } else {\n result2.simples.push({ selector: consumeSimpleSelector(), combinator: "" });\n }\n while (true) {\n skipWhitespace();\n if (isClauseCombinator()) {\n result2.simples[result2.simples.length - 1].combinator = tokens[pos++].value;\n skipWhitespace();\n } else if (isSelectorClauseEnd()) {\n break;\n }\n result2.simples.push({ combinator: "", selector: consumeSimpleSelector() });\n }\n return result2;\n }\n function consumeSimpleSelector() {\n let rawCSSString = "";\n const functions = [];\n while (!isSelectorClauseEnd()) {\n if (isIdent() || isStar()) {\n rawCSSString += tokens[pos++].toSource();\n } else if (tokens[pos] instanceof HashToken) {\n rawCSSString += tokens[pos++].toSource();\n } else if (tokens[pos] instanceof DelimToken && tokens[pos].value === ".") {\n pos++;\n if (isIdent())\n rawCSSString += "." + tokens[pos++].toSource();\n else\n throw unexpected();\n } else if (tokens[pos] instanceof ColonToken) {\n pos++;\n if (isIdent()) {\n if (!customNames.has(tokens[pos].value.toLowerCase())) {\n rawCSSString += ":" + tokens[pos++].toSource();\n } else {\n const name = tokens[pos++].value.toLowerCase();\n functions.push({ name, args: [] });\n names.add(name);\n }\n } else if (isFunction()) {\n const name = tokens[pos++].value.toLowerCase();\n if (!customNames.has(name)) {\n rawCSSString += `:${name}(${consumeBuiltinFunctionArguments()})`;\n } else {\n functions.push({ name, args: consumeFunctionArguments() });\n names.add(name);\n }\n skipWhitespace();\n if (!isCloseParen())\n throw unexpected();\n pos++;\n } else {\n throw unexpected();\n }\n } else if (tokens[pos] instanceof OpenSquareToken) {\n rawCSSString += "[";\n pos++;\n while (!(tokens[pos] instanceof CloseSquareToken) && !isEOF())\n rawCSSString += tokens[pos++].toSource();\n if (!(tokens[pos] instanceof CloseSquareToken))\n throw unexpected();\n rawCSSString += "]";\n pos++;\n } else {\n throw unexpected();\n }\n }\n if (!rawCSSString && !functions.length)\n throw unexpected();\n return { css: rawCSSString || void 0, functions };\n }\n function consumeBuiltinFunctionArguments() {\n let s = "";\n let balance = 1;\n while (!isEOF()) {\n if (isOpenParen() || isFunction())\n balance++;\n if (isCloseParen())\n balance--;\n if (!balance)\n break;\n s += tokens[pos++].toSource();\n }\n return s;\n }\n const result = consumeFunctionArguments();\n if (!isEOF())\n throw unexpected();\n if (result.some((arg) => typeof arg !== "object" || !("simples" in arg)))\n throw new InvalidSelectorError(`Error while parsing css selector "${selector}". Did you mean to CSS.escape it?`);\n return { selector: result, names: Array.from(names) };\n}\n\n// packages/isomorphic/selectorParser.ts\nvar kNestedSelectorNames = /* @__PURE__ */ new Set(["internal:has", "internal:has-not", "internal:and", "internal:or", "internal:chain", "left-of", "right-of", "above", "below", "near"]);\nvar kNestedSelectorNamesWithDistance = /* @__PURE__ */ new Set(["left-of", "right-of", "above", "below", "near"]);\nvar customCSSNames = /* @__PURE__ */ new Set(["not", "is", "where", "has", "scope", "light", "visible", "text", "text-matches", "text-is", "has-text", "above", "below", "right-of", "left-of", "near", "nth-match"]);\nfunction parseSelector(selector) {\n const parsedStrings = parseSelectorString(selector);\n const parts = [];\n for (const part of parsedStrings.parts) {\n if (part.name === "css" || part.name === "css:light") {\n if (part.name === "css:light")\n part.body = ":light(" + part.body + ")";\n const parsedCSS = parseCSS(part.body, customCSSNames);\n parts.push({\n name: "css",\n body: parsedCSS.selector,\n source: part.body\n });\n continue;\n }\n if (kNestedSelectorNames.has(part.name)) {\n let innerSelector;\n let distance;\n try {\n const unescaped = JSON.parse("[" + part.body + "]");\n if (!Array.isArray(unescaped) || unescaped.length < 1 || unescaped.length > 2 || typeof unescaped[0] !== "string")\n throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body);\n innerSelector = unescaped[0];\n if (unescaped.length === 2) {\n if (typeof unescaped[1] !== "number" || !kNestedSelectorNamesWithDistance.has(part.name))\n throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body);\n distance = unescaped[1];\n }\n } catch (e) {\n throw new InvalidSelectorError(`Malformed selector: ${part.name}=` + part.body);\n }\n const nested = { name: part.name, source: part.body, body: { parsed: parseSelector(innerSelector), distance } };\n const lastFrame = [...nested.body.parsed.parts].reverse().find((part2) => part2.name === "internal:control" && part2.body === "enter-frame");\n const lastFrameIndex = lastFrame ? nested.body.parsed.parts.indexOf(lastFrame) : -1;\n if (lastFrameIndex !== -1 && selectorPartsEqual(nested.body.parsed.parts.slice(0, lastFrameIndex + 1), parts.slice(0, lastFrameIndex + 1)))\n nested.body.parsed.parts.splice(0, lastFrameIndex + 1);\n parts.push(nested);\n continue;\n }\n parts.push({ ...part, source: part.body });\n }\n if (kNestedSelectorNames.has(parts[0].name))\n throw new InvalidSelectorError(`"${parts[0].name}" selector cannot be first`);\n return {\n capture: parsedStrings.capture,\n parts\n };\n}\nfunction selectorPartsEqual(list1, list2) {\n return stringifySelector({ parts: list1 }) === stringifySelector({ parts: list2 });\n}\nfunction stringifySelector(selector, forceEngineName) {\n if (typeof selector === "string")\n return selector;\n return selector.parts.map((p, i) => {\n let includeEngine = true;\n if (!forceEngineName && i !== selector.capture) {\n if (p.name === "css")\n includeEngine = false;\n else if (p.name === "xpath" && p.source.startsWith("//") || p.source.startsWith(".."))\n includeEngine = false;\n }\n const prefix = includeEngine ? p.name + "=" : "";\n return `${i === selector.capture ? "*" : ""}${prefix}${p.source}`;\n }).join(" >> ");\n}\nfunction visitAllSelectorParts(selector, visitor) {\n const visit = (selector2, nested) => {\n for (const part of selector2.parts) {\n visitor(part, nested);\n if (kNestedSelectorNames.has(part.name))\n visit(part.body.parsed, true);\n }\n };\n visit(selector, false);\n}\nfunction parseSelectorString(selector) {\n let index = 0;\n let quote;\n let start = 0;\n const result = { parts: [] };\n const append = () => {\n const part = selector.substring(start, index).trim();\n const eqIndex = part.indexOf("=");\n let name;\n let body;\n if (eqIndex !== -1 && part.substring(0, eqIndex).trim().match(/^[a-zA-Z_0-9-+:*]+$/)) {\n name = part.substring(0, eqIndex).trim();\n body = part.substring(eqIndex + 1);\n } else if (part.length > 1 && part[0] === \'"\' && part[part.length - 1] === \'"\') {\n name = "text";\n body = part;\n } else if (part.length > 1 && part[0] === "\'" && part[part.length - 1] === "\'") {\n name = "text";\n body = part;\n } else if (/^\\(*\\/\\//.test(part) || part.startsWith("..")) {\n name = "xpath";\n body = part;\n } else {\n name = "css";\n body = part;\n }\n let capture = false;\n if (name[0] === "*") {\n capture = true;\n name = name.substring(1);\n }\n result.parts.push({ name, body });\n if (capture) {\n if (result.capture !== void 0)\n throw new InvalidSelectorError(`Only one of the selectors can capture using * modifier`);\n result.capture = result.parts.length - 1;\n }\n };\n if (!selector.includes(">>")) {\n index = selector.length;\n append();\n return result;\n }\n const shouldIgnoreTextSelectorQuote = () => {\n const prefix = selector.substring(start, index);\n const match = prefix.match(/^\\s*text\\s*=(.*)$/);\n return !!match && !!match[1];\n };\n while (index < selector.length) {\n const c = selector[index];\n if (c === "\\\\" && index + 1 < selector.length) {\n index += 2;\n } else if (c === quote) {\n quote = void 0;\n index++;\n } else if (!quote && (c === \'"\' || c === "\'" || c === "`") && !shouldIgnoreTextSelectorQuote()) {\n quote = c;\n index++;\n } else if (!quote && c === ">" && selector[index + 1] === ">") {\n append();\n index += 2;\n start = index;\n } else {\n index++;\n }\n }\n append();\n return result;\n}\nfunction parseAttributeSelector(selector, allowUnquotedStrings) {\n let wp = 0;\n let EOL = selector.length === 0;\n const next = () => selector[wp] || "";\n const eat1 = () => {\n const result2 = next();\n ++wp;\n EOL = wp >= selector.length;\n return result2;\n };\n const syntaxError = (stage) => {\n if (EOL)\n throw new InvalidSelectorError(`Unexpected end of selector while parsing selector \\`${selector}\\``);\n throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - unexpected symbol "${next()}" at position ${wp}` + (stage ? " during " + stage : ""));\n };\n function skipSpaces() {\n while (!EOL && /\\s/.test(next()))\n eat1();\n }\n function isCSSNameChar(char) {\n return char >= "\\x80" || char >= "0" && char <= "9" || char >= "A" && char <= "Z" || char >= "a" && char <= "z" || char >= "0" && char <= "9" || char === "_" || char === "-";\n }\n function readIdentifier() {\n let result2 = "";\n skipSpaces();\n while (!EOL && isCSSNameChar(next()))\n result2 += eat1();\n return result2;\n }\n function readQuotedString(quote) {\n let result2 = eat1();\n if (result2 !== quote)\n syntaxError("parsing quoted string");\n while (!EOL && next() !== quote) {\n if (next() === "\\\\")\n eat1();\n result2 += eat1();\n }\n if (next() !== quote)\n syntaxError("parsing quoted string");\n result2 += eat1();\n return result2;\n }\n function readRegularExpression() {\n if (eat1() !== "/")\n syntaxError("parsing regular expression");\n let source = "";\n let inClass = false;\n while (!EOL) {\n if (next() === "\\\\") {\n source += eat1();\n if (EOL)\n syntaxError("parsing regular expression");\n } else if (inClass && next() === "]") {\n inClass = false;\n } else if (!inClass && next() === "[") {\n inClass = true;\n } else if (!inClass && next() === "/") {\n break;\n }\n source += eat1();\n }\n if (eat1() !== "/")\n syntaxError("parsing regular expression");\n let flags = "";\n while (!EOL && next().match(/[dgimsuy]/))\n flags += eat1();\n try {\n return new RegExp(source, flags);\n } catch (e) {\n throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\`: ${e.message}`);\n }\n }\n function readAttributeToken() {\n let token = "";\n skipSpaces();\n if (next() === `\'` || next() === `"`)\n token = readQuotedString(next()).slice(1, -1);\n else\n token = readIdentifier();\n if (!token)\n syntaxError("parsing property path");\n return token;\n }\n function readOperator() {\n skipSpaces();\n let op = "";\n if (!EOL)\n op += eat1();\n if (!EOL && op !== "=")\n op += eat1();\n if (!["=", "*=", "^=", "$=", "|=", "~="].includes(op))\n syntaxError("parsing operator");\n return op;\n }\n function readAttribute() {\n eat1();\n const jsonPath = [];\n jsonPath.push(readAttributeToken());\n skipSpaces();\n while (next() === ".") {\n eat1();\n jsonPath.push(readAttributeToken());\n skipSpaces();\n }\n if (next() === "]") {\n eat1();\n return { name: jsonPath.join("."), jsonPath, op: "", value: null, caseSensitive: false };\n }\n const operator = readOperator();\n let value = void 0;\n let caseSensitive = true;\n skipSpaces();\n if (next() === "/") {\n if (operator !== "=")\n throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - cannot use ${operator} in attribute with regular expression`);\n value = readRegularExpression();\n } else if (next() === `\'` || next() === `"`) {\n value = readQuotedString(next()).slice(1, -1);\n skipSpaces();\n if (next() === "i" || next() === "I") {\n caseSensitive = false;\n eat1();\n } else if (next() === "s" || next() === "S") {\n caseSensitive = true;\n eat1();\n }\n } else {\n value = "";\n while (!EOL && (isCSSNameChar(next()) || next() === "+" || next() === "."))\n value += eat1();\n if (value === "true") {\n value = true;\n } else if (value === "false") {\n value = false;\n } else {\n if (!allowUnquotedStrings) {\n value = +value;\n if (Number.isNaN(value))\n syntaxError("parsing attribute value");\n }\n }\n }\n skipSpaces();\n if (next() !== "]")\n syntaxError("parsing attribute value");\n eat1();\n if (operator !== "=" && typeof value !== "string")\n throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - cannot use ${operator} in attribute with non-string matching value - ${value}`);\n return { name: jsonPath.join("."), jsonPath, op: operator, value, caseSensitive };\n }\n const result = {\n name: "",\n attributes: []\n };\n result.name = readIdentifier();\n skipSpaces();\n while (next() === "[") {\n result.attributes.push(readAttribute());\n skipSpaces();\n }\n if (!EOL)\n syntaxError(void 0);\n if (!result.name && !result.attributes.length)\n throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - selector cannot be empty`);\n return result;\n}\n\n// packages/isomorphic/stringUtils.ts\nfunction escapeWithQuotes(text, char = "\'") {\n const stringified = JSON.stringify(text);\n const escapedText = stringified.substring(1, stringified.length - 1).replace(/\\\\"/g, \'"\');\n if (char === "\'")\n return char + escapedText.replace(/[\']/g, "\\\\\'") + char;\n if (char === \'"\')\n return char + escapedText.replace(/["]/g, \'\\\\"\') + char;\n if (char === "`")\n return char + escapedText.replace(/[`]/g, "\\\\`") + char;\n throw new Error("Invalid escape char");\n}\nfunction toTitleCase(name) {\n return name.charAt(0).toUpperCase() + name.substring(1);\n}\nfunction toSnakeCase(name) {\n return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase();\n}\nfunction quoteCSSAttributeValue(text) {\n return `"${text.replace(/["\\\\]/g, (char) => "\\\\" + char)}"`;\n}\nvar normalizedWhitespaceCache;\nfunction cacheNormalizedWhitespaces() {\n normalizedWhitespaceCache = /* @__PURE__ */ new Map();\n}\nfunction normalizeWhiteSpace(text) {\n let result = normalizedWhitespaceCache == null ? void 0 : normalizedWhitespaceCache.get(text);\n if (result === void 0) {\n result = text.replace(/[\\u200b\\u00ad]/g, "").trim().replace(/\\s+/g, " ");\n normalizedWhitespaceCache == null ? void 0 : normalizedWhitespaceCache.set(text, result);\n }\n return result;\n}\nfunction normalizeEscapedRegexQuotes(source) {\n return source.replace(/(^|[^\\\\])(\\\\\\\\)*\\\\([\'"`])/g, "$1$2$3");\n}\nfunction escapeRegexForSelector(re) {\n if (re.unicode || re.unicodeSets)\n return String(re);\n return String(re).replace(/(^|[^\\\\])(\\\\\\\\)*(["\'`])/g, "$1$2\\\\$3").replace(/>>/g, "\\\\>\\\\>");\n}\nfunction escapeForTextSelector(text, exact) {\n if (typeof text !== "string")\n return escapeRegexForSelector(text);\n return `${JSON.stringify(text)}${exact ? "s" : "i"}`;\n}\nfunction escapeForAttributeSelector(value, exact) {\n if (typeof value !== "string")\n return escapeRegexForSelector(value);\n return `"${value.replace(/\\\\/g, "\\\\\\\\").replace(/["]/g, \'\\\\"\')}"${exact ? "s" : "i"}`;\n}\nfunction trimString(input, cap, suffix = "") {\n if (input.length <= cap)\n return input;\n const chars = [...input];\n if (chars.length > cap)\n return chars.slice(0, cap - suffix.length).join("") + suffix;\n return chars.join("");\n}\nfunction trimStringWithEllipsis(input, cap) {\n return trimString(input, cap, "\\u2026");\n}\nfunction escapeRegExp(s) {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\\\$&");\n}\nfunction longestCommonSubstring(s1, s2) {\n const n = s1.length;\n const m = s2.length;\n let maxLen = 0;\n let endingIndex = 0;\n const dp = Array(n + 1).fill(null).map(() => Array(m + 1).fill(0));\n for (let i = 1; i <= n; i++) {\n for (let j = 1; j <= m; j++) {\n if (s1[i - 1] === s2[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1] + 1;\n if (dp[i][j] > maxLen) {\n maxLen = dp[i][j];\n endingIndex = i;\n }\n }\n }\n }\n return s1.slice(endingIndex - maxLen, endingIndex);\n}\nvar ansiRegex = new RegExp("([\\\\u001B\\\\u009B][[\\\\]()#?]*(?:(?:(?:[a-zA-Z\\\\d]*(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?\\\\u0007)|(?:(?:\\\\d{0,4}(?:;\\\\d{0,4})*)?[\\\\dA-PR-TZcf-ntqry=><~])))", "g");\n\n// packages/isomorphic/locatorGenerators.ts\nfunction asLocator(lang, selector, isFrameLocator = false) {\n return asLocators(lang, selector, isFrameLocator, 1)[0];\n}\nfunction asLocators(lang, selector, isFrameLocator = false, maxOutputSize = 20, preferredQuote) {\n try {\n return innerAsLocators(new generators[lang](preferredQuote), parseSelector(selector), isFrameLocator, maxOutputSize);\n } catch (e) {\n return [selector];\n }\n}\nfunction innerAsLocators(factory, parsed, isFrameLocator = false, maxOutputSize = 20) {\n const parts = [...parsed.parts];\n const tokens = [];\n let nextBase = isFrameLocator ? "frame-locator" : "page";\n for (let index = 0; index < parts.length; index++) {\n const part = parts[index];\n const base = nextBase;\n nextBase = "locator";\n if (part.name === "internal:describe")\n continue;\n if (part.name === "nth") {\n if (part.body === "0")\n tokens.push([factory.generateLocator(base, "first", ""), factory.generateLocator(base, "nth", "0")]);\n else if (part.body === "-1")\n tokens.push([factory.generateLocator(base, "last", ""), factory.generateLocator(base, "nth", "-1")]);\n else\n tokens.push([factory.generateLocator(base, "nth", part.body)]);\n continue;\n }\n if (part.name === "visible") {\n tokens.push([factory.generateLocator(base, "visible", part.body), factory.generateLocator(base, "default", `visible=${part.body}`)]);\n continue;\n }\n if (part.name === "internal:text") {\n const { exact, text } = detectExact(part.body);\n tokens.push([factory.generateLocator(base, "text", text, { exact })]);\n continue;\n }\n if (part.name === "internal:has-text") {\n const { exact, text } = detectExact(part.body);\n if (!exact) {\n tokens.push([factory.generateLocator(base, "has-text", text, { exact })]);\n continue;\n }\n }\n if (part.name === "internal:has-not-text") {\n const { exact, text } = detectExact(part.body);\n if (!exact) {\n tokens.push([factory.generateLocator(base, "has-not-text", text, { exact })]);\n continue;\n }\n }\n if (part.name === "internal:has") {\n const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);\n tokens.push(inners.map((inner) => factory.generateLocator(base, "has", inner)));\n continue;\n }\n if (part.name === "internal:has-not") {\n const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);\n tokens.push(inners.map((inner) => factory.generateLocator(base, "hasNot", inner)));\n continue;\n }\n if (part.name === "internal:and") {\n const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);\n tokens.push(inners.map((inner) => factory.generateLocator(base, "and", inner)));\n continue;\n }\n if (part.name === "internal:or") {\n const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);\n tokens.push(inners.map((inner) => factory.generateLocator(base, "or", inner)));\n continue;\n }\n if (part.name === "internal:chain") {\n const inners = innerAsLocators(factory, part.body.parsed, false, maxOutputSize);\n tokens.push(inners.map((inner) => factory.generateLocator(base, "chain", inner)));\n continue;\n }\n if (part.name === "internal:label") {\n const { exact, text } = detectExact(part.body);\n tokens.push([factory.generateLocator(base, "label", text, { exact })]);\n continue;\n }\n if (part.name === "internal:role") {\n const attrSelector = parseAttributeSelector(part.body, true);\n const options = { attrs: [] };\n for (const attr of attrSelector.attributes) {\n if (attr.name === "name") {\n if (options.exact !== void 0 && options.exact !== attr.caseSensitive)\n throw new Error(`Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}`);\n options.exact = attr.caseSensitive;\n options.name = attr.value;\n } else if (attr.name === "description") {\n if (options.exact !== void 0 && options.exact !== attr.caseSensitive)\n throw new Error(`Conflicting exactness in internal:role selector: ${stringifySelector({ parts: [part] })}`);\n options.exact = attr.caseSensitive;\n options.description = attr.value;\n } else {\n if (attr.name === "level" && typeof attr.value === "string")\n attr.value = +attr.value;\n options.attrs.push({ name: attr.name === "include-hidden" ? "includeHidden" : attr.name, value: attr.value });\n }\n }\n tokens.push([factory.generateLocator(base, "role", attrSelector.name, options)]);\n continue;\n }\n if (part.name === "internal:testid") {\n const attrSelector = parseAttributeSelector(part.body, true);\n const { value } = attrSelector.attributes[0];\n tokens.push([factory.generateLocator(base, "test-id", value)]);\n continue;\n }\n if (part.name === "internal:attr") {\n const attrSelector = parseAttributeSelector(part.body, true);\n const { name, value, caseSensitive } = attrSelector.attributes[0];\n const text = value;\n const exact = !!caseSensitive;\n if (name === "placeholder") {\n tokens.push([factory.generateLocator(base, "placeholder", text, { exact })]);\n continue;\n }\n if (name === "alt") {\n tokens.push([factory.generateLocator(base, "alt", text, { exact })]);\n continue;\n }\n if (name === "title") {\n tokens.push([factory.generateLocator(base, "title", text, { exact })]);\n continue;\n }\n }\n if (part.name === "internal:control" && part.body === "enter-frame") {\n const lastTokens = tokens[tokens.length - 1];\n const lastPart = parts[index - 1];\n const transformed = lastTokens.map((token) => factory.chainLocators([token, factory.generateLocator(base, "frame", "")]));\n if (["xpath", "css"].includes(lastPart.name)) {\n transformed.push(\n factory.generateLocator(base, "frame-locator", stringifySelector({ parts: [lastPart] })),\n factory.generateLocator(base, "frame-locator", stringifySelector({ parts: [lastPart] }, true))\n );\n }\n lastTokens.splice(0, lastTokens.length, ...transformed);\n nextBase = "frame-locator";\n continue;\n }\n const nextPart = parts[index + 1];\n const selectorPart = stringifySelector({ parts: [part] });\n const locatorPart = factory.generateLocator(base, "default", selectorPart);\n if (nextPart && ["internal:has-text", "internal:has-not-text"].includes(nextPart.name)) {\n const { exact, text } = detectExact(nextPart.body);\n if (!exact) {\n const nextLocatorPart = factory.generateLocator("locator", nextPart.name === "internal:has-text" ? "has-text" : "has-not-text", text, { exact });\n const options = {};\n if (nextPart.name === "internal:has-text")\n options.hasText = text;\n else\n options.hasNotText = text;\n const combinedPart = factory.generateLocator(base, "default", selectorPart, options);\n tokens.push([factory.chainLocators([locatorPart, nextLocatorPart]), combinedPart]);\n index++;\n continue;\n }\n }\n let locatorPartWithEngine;\n if (["xpath", "css"].includes(part.name)) {\n const selectorPart2 = stringifySelector(\n { parts: [part] },\n /* forceEngineName */\n true\n );\n locatorPartWithEngine = factory.generateLocator(base, "default", selectorPart2);\n }\n tokens.push([locatorPart, locatorPartWithEngine].filter(Boolean));\n }\n return combineTokens(factory, tokens, maxOutputSize);\n}\nfunction combineTokens(factory, tokens, maxOutputSize) {\n const currentTokens = tokens.map(() => "");\n const result = [];\n const visit = (index) => {\n if (index === tokens.length) {\n result.push(factory.chainLocators(currentTokens));\n return result.length < maxOutputSize;\n }\n for (const taken of tokens[index]) {\n currentTokens[index] = taken;\n if (!visit(index + 1))\n return false;\n }\n return true;\n };\n visit(0);\n return result;\n}\nfunction detectExact(text) {\n let exact = false;\n const match = text.match(/^\\/(.*)\\/([igm]*)$/);\n if (match)\n return { text: new RegExp(match[1], match[2]) };\n if (text.endsWith(\'"\')) {\n text = JSON.parse(text);\n exact = true;\n } else if (text.endsWith(\'"s\')) {\n text = JSON.parse(text.substring(0, text.length - 1));\n exact = true;\n } else if (text.endsWith(\'"i\')) {\n text = JSON.parse(text.substring(0, text.length - 1));\n exact = false;\n }\n return { exact, text };\n}\nvar JavaScriptLocatorFactory = class {\n constructor(preferredQuote) {\n this.preferredQuote = preferredQuote;\n }\n generateLocator(base, kind, body, options = {}) {\n switch (kind) {\n case "default":\n if (options.hasText !== void 0)\n return `locator(${this.quote(body)}, { hasText: ${this.toHasText(options.hasText)} })`;\n if (options.hasNotText !== void 0)\n return `locator(${this.quote(body)}, { hasNotText: ${this.toHasText(options.hasNotText)} })`;\n return `locator(${this.quote(body)})`;\n case "frame-locator":\n return `frameLocator(${this.quote(body)})`;\n case "frame":\n return `contentFrame()`;\n case "nth":\n return `nth(${body})`;\n case "first":\n return `first()`;\n case "last":\n return `last()`;\n case "visible":\n return `filter({ visible: ${body === "true" ? "true" : "false"} })`;\n case "role":\n const attrs = [];\n if (isRegExp(options.name))\n attrs.push(`name: ${this.regexToSourceString(options.name)}`);\n else if (typeof options.name === "string")\n attrs.push(`name: ${this.quote(options.name)}`);\n if (isRegExp(options.description))\n attrs.push(`description: ${this.regexToSourceString(options.description)}`);\n else if (typeof options.description === "string")\n attrs.push(`description: ${this.quote(options.description)}`);\n if (options.exact && (typeof options.name === "string" || typeof options.description === "string"))\n attrs.push(`exact: true`);\n for (const { name, value } of options.attrs)\n attrs.push(`${name}: ${typeof value === "string" ? this.quote(value) : value}`);\n const attrString = attrs.length ? `, { ${attrs.join(", ")} }` : "";\n return `getByRole(${this.quote(body)}${attrString})`;\n case "has-text":\n return `filter({ hasText: ${this.toHasText(body)} })`;\n case "has-not-text":\n return `filter({ hasNotText: ${this.toHasText(body)} })`;\n case "has":\n return `filter({ has: ${body} })`;\n case "hasNot":\n return `filter({ hasNot: ${body} })`;\n case "and":\n return `and(${body})`;\n case "or":\n return `or(${body})`;\n case "chain":\n return `locator(${body})`;\n case "test-id":\n return `getByTestId(${this.toTestIdValue(body)})`;\n case "text":\n return this.toCallWithExact("getByText", body, !!options.exact);\n case "alt":\n return this.toCallWithExact("getByAltText", body, !!options.exact);\n case "placeholder":\n return this.toCallWithExact("getByPlaceholder", body, !!options.exact);\n case "label":\n return this.toCallWithExact("getByLabel", body, !!options.exact);\n case "title":\n return this.toCallWithExact("getByTitle", body, !!options.exact);\n default:\n throw new Error("Unknown selector kind " + kind);\n }\n }\n chainLocators(locators) {\n return locators.join(".");\n }\n regexToSourceString(re) {\n return normalizeEscapedRegexQuotes(String(re));\n }\n toCallWithExact(method, body, exact) {\n if (isRegExp(body))\n return `${method}(${this.regexToSourceString(body)})`;\n return exact ? `${method}(${this.quote(body)}, { exact: true })` : `${method}(${this.quote(body)})`;\n }\n toHasText(body) {\n if (isRegExp(body))\n return this.regexToSourceString(body);\n return this.quote(body);\n }\n toTestIdValue(value) {\n if (isRegExp(value))\n return this.regexToSourceString(value);\n return this.quote(value);\n }\n quote(text) {\n var _a;\n return escapeWithQuotes(text, (_a = this.preferredQuote) != null ? _a : "\'");\n }\n};\nvar PythonLocatorFactory = class {\n generateLocator(base, kind, body, options = {}) {\n switch (kind) {\n case "default":\n if (options.hasText !== void 0)\n return `locator(${this.quote(body)}, has_text=${this.toHasText(options.hasText)})`;\n if (options.hasNotText !== void 0)\n return `locator(${this.quote(body)}, has_not_text=${this.toHasText(options.hasNotText)})`;\n return `locator(${this.quote(body)})`;\n case "frame-locator":\n return `frame_locator(${this.quote(body)})`;\n case "frame":\n return `content_frame`;\n case "nth":\n return `nth(${body})`;\n case "first":\n return `first`;\n case "last":\n return `last`;\n case "visible":\n return `filter(visible=${body === "true" ? "True" : "False"})`;\n case "role":\n const attrs = [];\n if (isRegExp(options.name))\n attrs.push(`name=${this.regexToString(options.name)}`);\n else if (typeof options.name === "string")\n attrs.push(`name=${this.quote(options.name)}`);\n if (isRegExp(options.description))\n attrs.push(`description=${this.regexToString(options.description)}`);\n else if (typeof options.description === "string")\n attrs.push(`description=${this.quote(options.description)}`);\n if (options.exact && (typeof options.name === "string" || typeof options.description === "string"))\n attrs.push(`exact=True`);\n for (const { name, value } of options.attrs) {\n let valueString = typeof value === "string" ? this.quote(value) : value;\n if (typeof value === "boolean")\n valueString = value ? "True" : "False";\n attrs.push(`${toSnakeCase(name)}=${valueString}`);\n }\n const attrString = attrs.length ? `, ${attrs.join(", ")}` : "";\n return `get_by_role(${this.quote(body)}${attrString})`;\n case "has-text":\n return `filter(has_text=${this.toHasText(body)})`;\n case "has-not-text":\n return `filter(has_not_text=${this.toHasText(body)})`;\n case "has":\n return `filter(has=${body})`;\n case "hasNot":\n return `filter(has_not=${body})`;\n case "and":\n return `and_(${body})`;\n case "or":\n return `or_(${body})`;\n case "chain":\n return `locator(${body})`;\n case "test-id":\n return `get_by_test_id(${this.toTestIdValue(body)})`;\n case "text":\n return this.toCallWithExact("get_by_text", body, !!options.exact);\n case "alt":\n return this.toCallWithExact("get_by_alt_text", body, !!options.exact);\n case "placeholder":\n return this.toCallWithExact("get_by_placeholder", body, !!options.exact);\n case "label":\n return this.toCallWithExact("get_by_label", body, !!options.exact);\n case "title":\n return this.toCallWithExact("get_by_title", body, !!options.exact);\n default:\n throw new Error("Unknown selector kind " + kind);\n }\n }\n chainLocators(locators) {\n return locators.join(".");\n }\n regexToString(body) {\n const suffix = body.flags.includes("i") ? ", re.IGNORECASE" : "";\n return `re.compile(r"${normalizeEscapedRegexQuotes(body.source).replace(/\\\\\\//, "/").replace(/"/g, \'\\\\"\')}"${suffix})`;\n }\n toCallWithExact(method, body, exact) {\n if (isRegExp(body))\n return `${method}(${this.regexToString(body)})`;\n if (exact)\n return `${method}(${this.quote(body)}, exact=True)`;\n return `${method}(${this.quote(body)})`;\n }\n toHasText(body) {\n if (isRegExp(body))\n return this.regexToString(body);\n return `${this.quote(body)}`;\n }\n toTestIdValue(value) {\n if (isRegExp(value))\n return this.regexToString(value);\n return this.quote(value);\n }\n quote(text) {\n return escapeWithQuotes(text, \'"\');\n }\n};\nvar JavaLocatorFactory = class {\n generateLocator(base, kind, body, options = {}) {\n let clazz;\n switch (base) {\n case "page":\n clazz = "Page";\n break;\n case "frame-locator":\n clazz = "FrameLocator";\n break;\n case "locator":\n clazz = "Locator";\n break;\n }\n switch (kind) {\n case "default":\n if (options.hasText !== void 0)\n return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasText(${this.toHasText(options.hasText)}))`;\n if (options.hasNotText !== void 0)\n return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasNotText(${this.toHasText(options.hasNotText)}))`;\n return `locator(${this.quote(body)})`;\n case "frame-locator":\n return `frameLocator(${this.quote(body)})`;\n case "frame":\n return `contentFrame()`;\n case "nth":\n return `nth(${body})`;\n case "first":\n return `first()`;\n case "last":\n return `last()`;\n case "visible":\n return `filter(new ${clazz}.FilterOptions().setVisible(${body === "true" ? "true" : "false"}))`;\n case "role":\n const attrs = [];\n if (isRegExp(options.name))\n attrs.push(`.setName(${this.regexToString(options.name)})`);\n else if (typeof options.name === "string")\n attrs.push(`.setName(${this.quote(options.name)})`);\n if (isRegExp(options.description))\n attrs.push(`.setDescription(${this.regexToString(options.description)})`);\n else if (typeof options.description === "string")\n attrs.push(`.setDescription(${this.quote(options.description)})`);\n if (options.exact && (typeof options.name === "string" || typeof options.description === "string"))\n attrs.push(`.setExact(true)`);\n for (const { name, value } of options.attrs)\n attrs.push(`.set${toTitleCase(name)}(${typeof value === "string" ? this.quote(value) : value})`);\n const attrString = attrs.length ? `, new ${clazz}.GetByRoleOptions()${attrs.join("")}` : "";\n return `getByRole(AriaRole.${toSnakeCase(body).toUpperCase()}${attrString})`;\n case "has-text":\n return `filter(new ${clazz}.FilterOptions().setHasText(${this.toHasText(body)}))`;\n case "has-not-text":\n return `filter(new ${clazz}.FilterOptions().setHasNotText(${this.toHasText(body)}))`;\n case "has":\n return `filter(new ${clazz}.FilterOptions().setHas(${body}))`;\n case "hasNot":\n return `filter(new ${clazz}.FilterOptions().setHasNot(${body}))`;\n case "and":\n return `and(${body})`;\n case "or":\n return `or(${body})`;\n case "chain":\n return `locator(${body})`;\n case "test-id":\n return `getByTestId(${this.toTestIdValue(body)})`;\n case "text":\n return this.toCallWithExact(clazz, "getByText", body, !!options.exact);\n case "alt":\n return this.toCallWithExact(clazz, "getByAltText", body, !!options.exact);\n case "placeholder":\n return this.toCallWithExact(clazz, "getByPlaceholder", body, !!options.exact);\n case "label":\n return this.toCallWithExact(clazz, "getByLabel", body, !!options.exact);\n case "title":\n return this.toCallWithExact(clazz, "getByTitle", body, !!options.exact);\n default:\n throw new Error("Unknown selector kind " + kind);\n }\n }\n chainLocators(locators) {\n return locators.join(".");\n }\n regexToString(body) {\n const suffix = body.flags.includes("i") ? ", Pattern.CASE_INSENSITIVE" : "";\n return `Pattern.compile(${this.quote(normalizeEscapedRegexQuotes(body.source))}${suffix})`;\n }\n toCallWithExact(clazz, method, body, exact) {\n if (isRegExp(body))\n return `${method}(${this.regexToString(body)})`;\n if (exact)\n return `${method}(${this.quote(body)}, new ${clazz}.${toTitleCase(method)}Options().setExact(true))`;\n return `${method}(${this.quote(body)})`;\n }\n toHasText(body) {\n if (isRegExp(body))\n return this.regexToString(body);\n return this.quote(body);\n }\n toTestIdValue(value) {\n if (isRegExp(value))\n return this.regexToString(value);\n return this.quote(value);\n }\n quote(text) {\n return escapeWithQuotes(text, \'"\');\n }\n};\nvar CSharpLocatorFactory = class {\n generateLocator(base, kind, body, options = {}) {\n switch (kind) {\n case "default":\n if (options.hasText !== void 0)\n return `Locator(${this.quote(body)}, new() { ${this.toHasText(options.hasText)} })`;\n if (options.hasNotText !== void 0)\n return `Locator(${this.quote(body)}, new() { ${this.toHasNotText(options.hasNotText)} })`;\n return `Locator(${this.quote(body)})`;\n case "frame-locator":\n return `FrameLocator(${this.quote(body)})`;\n case "frame":\n return `ContentFrame`;\n case "nth":\n return `Nth(${body})`;\n case "first":\n return `First`;\n case "last":\n return `Last`;\n case "visible":\n return `Filter(new() { Visible = ${body === "true" ? "true" : "false"} })`;\n case "role":\n const attrs = [];\n if (isRegExp(options.name))\n attrs.push(`NameRegex = ${this.regexToString(options.name)}`);\n else if (typeof options.name === "string")\n attrs.push(`Name = ${this.quote(options.name)}`);\n if (isRegExp(options.description))\n attrs.push(`DescriptionRegex = ${this.regexToString(options.description)}`);\n else if (typeof options.description === "string")\n attrs.push(`Description = ${this.quote(options.description)}`);\n if (options.exact && (typeof options.name === "string" || typeof options.description === "string"))\n attrs.push(`Exact = true`);\n for (const { name, value } of options.attrs)\n attrs.push(`${toTitleCase(name)} = ${typeof value === "string" ? this.quote(value) : value}`);\n const attrString = attrs.length ? `, new() { ${attrs.join(", ")} }` : "";\n return `GetByRole(AriaRole.${toTitleCase(body)}${attrString})`;\n case "has-text":\n return `Filter(new() { ${this.toHasText(body)} })`;\n case "has-not-text":\n return `Filter(new() { ${this.toHasNotText(body)} })`;\n case "has":\n return `Filter(new() { Has = ${body} })`;\n case "hasNot":\n return `Filter(new() { HasNot = ${body} })`;\n case "and":\n return `And(${body})`;\n case "or":\n return `Or(${body})`;\n case "chain":\n return `Locator(${body})`;\n case "test-id":\n return `GetByTestId(${this.toTestIdValue(body)})`;\n case "text":\n return this.toCallWithExact("GetByText", body, !!options.exact);\n case "alt":\n return this.toCallWithExact("GetByAltText", body, !!options.exact);\n case "placeholder":\n return this.toCallWithExact("GetByPlaceholder", body, !!options.exact);\n case "label":\n return this.toCallWithExact("GetByLabel", body, !!options.exact);\n case "title":\n return this.toCallWithExact("GetByTitle", body, !!options.exact);\n default:\n throw new Error("Unknown selector kind " + kind);\n }\n }\n chainLocators(locators) {\n return locators.join(".");\n }\n regexToString(body) {\n const suffix = body.flags.includes("i") ? ", RegexOptions.IgnoreCase" : "";\n return `new Regex(${this.quote(normalizeEscapedRegexQuotes(body.source))}${suffix})`;\n }\n toCallWithExact(method, body, exact) {\n if (isRegExp(body))\n return `${method}(${this.regexToString(body)})`;\n if (exact)\n return `${method}(${this.quote(body)}, new() { Exact = true })`;\n return `${method}(${this.quote(body)})`;\n }\n toHasText(body) {\n if (isRegExp(body))\n return `HasTextRegex = ${this.regexToString(body)}`;\n return `HasText = ${this.quote(body)}`;\n }\n toTestIdValue(value) {\n if (isRegExp(value))\n return this.regexToString(value);\n return this.quote(value);\n }\n toHasNotText(body) {\n if (isRegExp(body))\n return `HasNotTextRegex = ${this.regexToString(body)}`;\n return `HasNotText = ${this.quote(body)}`;\n }\n quote(text) {\n return escapeWithQuotes(text, \'"\');\n }\n};\nvar JsonlLocatorFactory = class {\n generateLocator(base, kind, body, options = {}) {\n return JSON.stringify({\n kind,\n body,\n options\n });\n }\n chainLocators(locators) {\n const objects = locators.map((l) => JSON.parse(l));\n for (let i = 0; i < objects.length - 1; ++i)\n objects[i].next = objects[i + 1];\n return JSON.stringify(objects[0]);\n }\n};\nvar generators = {\n javascript: JavaScriptLocatorFactory,\n python: PythonLocatorFactory,\n java: JavaLocatorFactory,\n csharp: CSharpLocatorFactory,\n jsonl: JsonlLocatorFactory\n};\nfunction isRegExp(obj) {\n return obj instanceof RegExp;\n}\n\n// packages/isomorphic/locatorUtils.ts\nfunction getByAttributeTextSelector(attrName, text, options) {\n return `internal:attr=[${attrName}=${escapeForAttributeSelector(text, (options == null ? void 0 : options.exact) || false)}]`;\n}\nfunction splitTestIdAttributeNames(testIdAttributeName) {\n return testIdAttributeName.split(",");\n}\nfunction encodeTestIdAttributeName(testIdAttributeName) {\n return testIdAttributeName.includes(",") ? JSON.stringify(testIdAttributeName) : testIdAttributeName;\n}\nfunction getByTestIdSelector(testIdAttributeName, testId) {\n return `internal:testid=[${encodeTestIdAttributeName(testIdAttributeName)}=${escapeForAttributeSelector(testId, true)}]`;\n}\nfunction getByLabelSelector(text, options) {\n return "internal:label=" + escapeForTextSelector(text, !!(options == null ? void 0 : options.exact));\n}\nfunction getByAltTextSelector(text, options) {\n return getByAttributeTextSelector("alt", text, options);\n}\nfunction getByTitleSelector(text, options) {\n return getByAttributeTextSelector("title", text, options);\n}\nfunction getByPlaceholderSelector(text, options) {\n return getByAttributeTextSelector("placeholder", text, options);\n}\nfunction getByTextSelector(text, options) {\n return "internal:text=" + escapeForTextSelector(text, !!(options == null ? void 0 : options.exact));\n}\nfunction getByRoleSelector(role, options = {}) {\n const props = [];\n if (options.checked !== void 0)\n props.push(["checked", String(options.checked)]);\n if (options.disabled !== void 0)\n props.push(["disabled", String(options.disabled)]);\n if (options.selected !== void 0)\n props.push(["selected", String(options.selected)]);\n if (options.expanded !== void 0)\n props.push(["expanded", String(options.expanded)]);\n if (options.includeHidden !== void 0)\n props.push(["include-hidden", String(options.includeHidden)]);\n if (options.level !== void 0)\n props.push(["level", String(options.level)]);\n if (options.name !== void 0)\n props.push(["name", escapeForAttributeSelector(options.name, !!options.exact)]);\n if (options.description !== void 0)\n props.push(["description", escapeForAttributeSelector(options.description, !!options.exact)]);\n if (options.pressed !== void 0)\n props.push(["pressed", String(options.pressed)]);\n return `internal:role=${role}${props.map(([n, v]) => `[${n}=${v}]`).join("")}`;\n}\n\n// packages/isomorphic/yaml.ts\nfunction yamlEscapeKeyIfNeeded(str) {\n if (!yamlStringNeedsQuotes(str))\n return str;\n return `\'` + str.replace(/\'/g, `\'\'`) + `\'`;\n}\nfunction yamlEscapeValueIfNeeded(str) {\n if (!yamlStringNeedsQuotes(str))\n return str;\n return \'"\' + str.replace(/[\\\\"\\x00-\\x1f\\x7f-\\x9f]/g, (c) => {\n switch (c) {\n case "\\\\":\n return "\\\\\\\\";\n case \'"\':\n return \'\\\\"\';\n case "\\b":\n return "\\\\b";\n case "\\f":\n return "\\\\f";\n case "\\n":\n return "\\\\n";\n case "\\r":\n return "\\\\r";\n case " ":\n return "\\\\t";\n default:\n const code = c.charCodeAt(0);\n return "\\\\x" + code.toString(16).padStart(2, "0");\n }\n }) + \'"\';\n}\nfunction yamlStringNeedsQuotes(str) {\n if (str.length === 0)\n return true;\n if (/^\\s|\\s$/.test(str))\n return true;\n if (/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f-\\x9f]/.test(str))\n return true;\n if (/^-/.test(str))\n return true;\n if (/[\\n:](\\s|$)/.test(str))\n return true;\n if (/\\s#/.test(str))\n return true;\n if (/[\\n\\r]/.test(str))\n return true;\n if (/^[&*\\],?!>|@"\'#%]/.test(str))\n return true;\n if (/[{}`]/.test(str))\n return true;\n if (/^\\[/.test(str))\n return true;\n if (!isNaN(Number(str)) || ["y", "n", "yes", "no", "true", "false", "on", "off", "null"].includes(str.toLowerCase()))\n return true;\n return false;\n}\n\n// packages/injected/src/domUtils.ts\nvar globalOptions = {};\nfunction setGlobalOptions(options) {\n globalOptions = options;\n}\nfunction isInsideScope(scope, element) {\n while (element) {\n if (scope.contains(element))\n return true;\n element = enclosingShadowHost(element);\n }\n return false;\n}\nfunction parentElementOrShadowHost(element) {\n if (element.parentElement)\n return element.parentElement;\n if (!element.parentNode)\n return;\n if (element.parentNode.nodeType === 11 && element.parentNode.host)\n return element.parentNode.host;\n}\nfunction enclosingShadowRootOrDocument(element) {\n let node = element;\n while (node.parentNode)\n node = node.parentNode;\n if (node.nodeType === 11 || node.nodeType === 9)\n return node;\n}\nfunction enclosingShadowHost(element) {\n while (element.parentElement)\n element = element.parentElement;\n return parentElementOrShadowHost(element);\n}\nfunction closestCrossShadow(element, css, scope) {\n while (element) {\n const closest = element.closest(css);\n if (scope && closest !== scope && (closest == null ? void 0 : closest.contains(scope)))\n return;\n if (closest)\n return closest;\n element = enclosingShadowHost(element);\n }\n}\nfunction getElementComputedStyle(element, pseudo) {\n const cache = pseudo === "::before" ? cacheStyleBefore : pseudo === "::after" ? cacheStyleAfter : cacheStyle;\n if (cache && cache.has(element))\n return cache.get(element);\n const style = element.ownerDocument && element.ownerDocument.defaultView ? element.ownerDocument.defaultView.getComputedStyle(element, pseudo) : void 0;\n cache == null ? void 0 : cache.set(element, style);\n return style;\n}\nfunction isElementStyleVisibilityVisible(element, style) {\n style = style != null ? style : getElementComputedStyle(element);\n if (!style)\n return true;\n if (Element.prototype.checkVisibility && globalOptions.browserNameForWorkarounds !== "webkit") {\n if (!element.checkVisibility())\n return false;\n } else {\n const detailsOrSummary = element.closest("details,summary");\n if (detailsOrSummary !== element && (detailsOrSummary == null ? void 0 : detailsOrSummary.nodeName) === "DETAILS" && !detailsOrSummary.open)\n return false;\n }\n if (style.visibility !== "visible")\n return false;\n return true;\n}\nfunction computeBox(element) {\n const style = getElementComputedStyle(element);\n if (!style)\n return { visible: true, inline: false };\n const cursor = style.cursor;\n if (style.display === "contents") {\n for (let child = element.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === 1 && isElementVisible(child))\n return { visible: true, inline: false, cursor };\n if (child.nodeType === 3 && isVisibleTextNode(child))\n return { visible: true, inline: true, cursor };\n }\n return { visible: false, inline: false, cursor };\n }\n if (!isElementStyleVisibilityVisible(element, style))\n return { cursor, visible: false, inline: false };\n const rect = element.getBoundingClientRect();\n return { cursor, visible: rect.width > 0 && rect.height > 0, inline: style.display === "inline" };\n}\nfunction isElementVisible(element) {\n return computeBox(element).visible;\n}\nfunction isVisibleTextNode(node) {\n const range = node.ownerDocument.createRange();\n range.selectNode(node);\n const rect = range.getBoundingClientRect();\n return rect.width > 0 && rect.height > 0;\n}\nfunction elementSafeTagName(element) {\n const tagName = element.tagName;\n if (typeof tagName === "string")\n return tagName.toUpperCase();\n if (element instanceof HTMLFormElement)\n return "FORM";\n return element.tagName.toUpperCase();\n}\nvar cacheStyle;\nvar cacheStyleBefore;\nvar cacheStyleAfter;\nvar cachesCounter = 0;\nfunction beginDOMCaches() {\n ++cachesCounter;\n cacheStyle != null ? cacheStyle : cacheStyle = /* @__PURE__ */ new Map();\n cacheStyleBefore != null ? cacheStyleBefore : cacheStyleBefore = /* @__PURE__ */ new Map();\n cacheStyleAfter != null ? cacheStyleAfter : cacheStyleAfter = /* @__PURE__ */ new Map();\n}\nfunction endDOMCaches() {\n if (!--cachesCounter) {\n cacheStyle = void 0;\n cacheStyleBefore = void 0;\n cacheStyleAfter = void 0;\n }\n}\n\n// packages/injected/src/roleUtils.ts\nfunction hasExplicitAccessibleName(e) {\n return e.hasAttribute("aria-label") || e.hasAttribute("aria-labelledby");\n}\nvar kAncestorPreventingLandmark = "article:not([role]), aside:not([role]), main:not([role]), nav:not([role]), section:not([role]), [role=article], [role=complementary], [role=main], [role=navigation], [role=region]";\nvar kGlobalAriaAttributes = [\n ["aria-atomic", void 0],\n ["aria-busy", void 0],\n ["aria-controls", void 0],\n ["aria-current", void 0],\n ["aria-describedby", void 0],\n ["aria-details", void 0],\n // Global use deprecated in ARIA 1.2\n // [\'aria-disabled\', undefined],\n ["aria-dropeffect", void 0],\n // Global use deprecated in ARIA 1.2\n // [\'aria-errormessage\', undefined],\n ["aria-flowto", void 0],\n ["aria-grabbed", void 0],\n // Global use deprecated in ARIA 1.2\n // [\'aria-haspopup\', undefined],\n ["aria-hidden", void 0],\n // Global use deprecated in ARIA 1.2\n // [\'aria-invalid\', undefined],\n ["aria-keyshortcuts", void 0],\n ["aria-label", ["caption", "code", "deletion", "emphasis", "generic", "insertion", "paragraph", "presentation", "strong", "subscript", "superscript"]],\n ["aria-labelledby", ["caption", "code", "deletion", "emphasis", "generic", "insertion", "paragraph", "presentation", "strong", "subscript", "superscript"]],\n ["aria-live", void 0],\n ["aria-owns", void 0],\n ["aria-relevant", void 0],\n ["aria-roledescription", ["generic"]]\n];\nfunction hasGlobalAriaAttribute(element, forRole) {\n return kGlobalAriaAttributes.some(([attr, prohibited]) => {\n return !(prohibited == null ? void 0 : prohibited.includes(forRole || "")) && element.hasAttribute(attr);\n });\n}\nfunction hasTabIndex(element) {\n return !Number.isNaN(Number(String(element.getAttribute("tabindex"))));\n}\nfunction isFocusable(element) {\n return !isNativelyDisabled(element) && (isNativelyFocusable(element) || hasTabIndex(element));\n}\nfunction isNativelyFocusable(element) {\n const tagName = elementSafeTagName(element);\n if (["BUTTON", "DETAILS", "SELECT", "TEXTAREA"].includes(tagName))\n return true;\n if (tagName === "A" || tagName === "AREA")\n return element.hasAttribute("href");\n if (tagName === "INPUT")\n return !element.hidden;\n return false;\n}\nvar kImplicitRoleByTagName = {\n "A": (e) => {\n return e.hasAttribute("href") ? "link" : null;\n },\n "AREA": (e) => {\n return e.hasAttribute("href") ? "link" : null;\n },\n "ARTICLE": () => "article",\n "ASIDE": () => "complementary",\n "BLOCKQUOTE": () => "blockquote",\n "BUTTON": () => "button",\n "CAPTION": () => "caption",\n "CODE": () => "code",\n "DATALIST": () => "listbox",\n "DD": () => "definition",\n "DEL": () => "deletion",\n "DETAILS": () => "group",\n "DFN": () => "term",\n "DIALOG": () => "dialog",\n "DT": () => "term",\n "EM": () => "emphasis",\n "FIELDSET": () => "group",\n "FIGURE": () => "figure",\n "FOOTER": (e) => closestCrossShadow(e, kAncestorPreventingLandmark) ? null : "contentinfo",\n "FORM": (e) => hasExplicitAccessibleName(e) ? "form" : null,\n "H1": () => "heading",\n "H2": () => "heading",\n "H3": () => "heading",\n "H4": () => "heading",\n "H5": () => "heading",\n "H6": () => "heading",\n "HEADER": (e) => closestCrossShadow(e, kAncestorPreventingLandmark) ? null : "banner",\n "HR": () => "separator",\n "HTML": () => "document",\n "IMG": (e) => e.getAttribute("alt") === "" && !e.getAttribute("title") && !hasGlobalAriaAttribute(e) && !hasTabIndex(e) ? "presentation" : "img",\n "INPUT": (e) => {\n const type = e.type.toLowerCase();\n if (type === "search")\n return e.hasAttribute("list") ? "combobox" : "searchbox";\n if (["email", "tel", "text", "url", ""].includes(type)) {\n const list = getIdRefs(e, e.getAttribute("list"))[0];\n return list && elementSafeTagName(list) === "DATALIST" ? "combobox" : "textbox";\n }\n if (type === "hidden")\n return null;\n if (type === "file")\n return "button";\n return inputTypeToRole[type] || "textbox";\n },\n "INS": () => "insertion",\n "LI": () => "listitem",\n "MAIN": () => "main",\n "MARK": () => "mark",\n "MATH": () => "math",\n "MENU": () => "list",\n "METER": () => "meter",\n "NAV": () => "navigation",\n "OL": () => "list",\n "OPTGROUP": () => "group",\n "OPTION": () => "option",\n "OUTPUT": () => "status",\n "P": () => "paragraph",\n "PROGRESS": () => "progressbar",\n "SEARCH": () => "search",\n "SECTION": (e) => hasExplicitAccessibleName(e) ? "region" : null,\n "SELECT": (e) => e.hasAttribute("multiple") || e.size > 1 ? "listbox" : "combobox",\n "STRONG": () => "strong",\n "SUB": () => "subscript",\n "SUP": () => "superscript",\n // For we default to Chrome behavior:\n // - Chrome reports \'img\'.\n // - Firefox reports \'diagram\' that is not in official ARIA spec yet.\n // - Safari reports \'no role\', but still computes accessible name.\n "SVG": () => "img",\n "TABLE": () => "table",\n "TBODY": () => "rowgroup",\n "TD": (e) => {\n const table = closestCrossShadow(e, "table");\n const role = table ? getExplicitAriaRole(table) : "";\n return role === "grid" || role === "treegrid" ? "gridcell" : "cell";\n },\n "TEXTAREA": () => "textbox",\n "TFOOT": () => "rowgroup",\n "TH": (e) => {\n const scope = e.getAttribute("scope");\n if (scope === "col" || scope === "colgroup")\n return "columnheader";\n if (scope === "row" || scope === "rowgroup")\n return "rowheader";\n const nextSibling = e.nextElementSibling;\n const prevSibling = e.previousElementSibling;\n const row = !!e.parentElement && elementSafeTagName(e.parentElement) === "TR" ? e.parentElement : void 0;\n if (!nextSibling && !prevSibling) {\n if (row) {\n const table = closestCrossShadow(row, "table");\n if (table && table.rows.length <= 1)\n return null;\n }\n return "columnheader";\n }\n if (isHeaderCell(nextSibling) && isHeaderCell(prevSibling))\n return "columnheader";\n if (isNonEmptyDataCell(nextSibling) || isNonEmptyDataCell(prevSibling))\n return "rowheader";\n return "columnheader";\n },\n "THEAD": () => "rowgroup",\n "TIME": () => "time",\n "TR": () => "row",\n "UL": () => "list"\n};\nfunction isHeaderCell(element) {\n return !!element && elementSafeTagName(element) === "TH";\n}\nfunction isNonEmptyDataCell(element) {\n var _a;\n if (!element || elementSafeTagName(element) !== "TD")\n return false;\n return !!(((_a = element.textContent) == null ? void 0 : _a.trim()) || element.children.length > 0);\n}\nvar kPresentationInheritanceParents = {\n "DD": ["DL", "DIV"],\n "DIV": ["DL"],\n "DT": ["DL", "DIV"],\n "LI": ["OL", "UL"],\n "TBODY": ["TABLE"],\n "TD": ["TR"],\n "TFOOT": ["TABLE"],\n "TH": ["TR"],\n "THEAD": ["TABLE"],\n "TR": ["THEAD", "TBODY", "TFOOT", "TABLE"]\n};\nfunction getImplicitAriaRole(element) {\n var _a;\n const implicitRole = ((_a = kImplicitRoleByTagName[elementSafeTagName(element)]) == null ? void 0 : _a.call(kImplicitRoleByTagName, element)) || "";\n if (!implicitRole)\n return null;\n let ancestor = element;\n while (ancestor) {\n const parent = parentElementOrShadowHost(ancestor);\n const parents = kPresentationInheritanceParents[elementSafeTagName(ancestor)];\n if (!parents || !parent || !parents.includes(elementSafeTagName(parent)))\n break;\n const parentExplicitRole = getExplicitAriaRole(parent);\n if ((parentExplicitRole === "none" || parentExplicitRole === "presentation") && !hasPresentationConflictResolution(parent, parentExplicitRole))\n return parentExplicitRole;\n ancestor = parent;\n }\n return implicitRole;\n}\nvar validRoles = [\n "alert",\n "alertdialog",\n "application",\n "article",\n "banner",\n "blockquote",\n "button",\n "caption",\n "cell",\n "checkbox",\n "code",\n "columnheader",\n "combobox",\n "complementary",\n "contentinfo",\n "definition",\n "deletion",\n "dialog",\n "directory",\n "document",\n "emphasis",\n "feed",\n "figure",\n "form",\n "generic",\n "grid",\n "gridcell",\n "group",\n "heading",\n "img",\n "insertion",\n "link",\n "list",\n "listbox",\n "listitem",\n "log",\n "main",\n "mark",\n "marquee",\n "math",\n "meter",\n "menu",\n "menubar",\n "menuitem",\n "menuitemcheckbox",\n "menuitemradio",\n "navigation",\n "none",\n "note",\n "option",\n "paragraph",\n "presentation",\n "progressbar",\n "radio",\n "radiogroup",\n "region",\n "row",\n "rowgroup",\n "rowheader",\n "scrollbar",\n "search",\n "searchbox",\n "separator",\n "slider",\n "spinbutton",\n "status",\n "strong",\n "subscript",\n "superscript",\n "switch",\n "tab",\n "table",\n "tablist",\n "tabpanel",\n "term",\n "textbox",\n "time",\n "timer",\n "toolbar",\n "tooltip",\n "tree",\n "treegrid",\n "treeitem"\n];\nfunction getExplicitAriaRole(element) {\n const roles = (element.getAttribute("role") || "").split(" ").map((role) => role.trim());\n return roles.find((role) => validRoles.includes(role)) || null;\n}\nfunction hasPresentationConflictResolution(element, role) {\n return hasGlobalAriaAttribute(element, role) || isFocusable(element);\n}\nfunction getAriaRole(element) {\n const explicitRole = getExplicitAriaRole(element);\n if (!explicitRole)\n return getImplicitAriaRole(element);\n if (explicitRole === "none" || explicitRole === "presentation") {\n const implicitRole = getImplicitAriaRole(element);\n if (hasPresentationConflictResolution(element, implicitRole))\n return implicitRole;\n }\n return explicitRole;\n}\nfunction getAriaBoolean(attr) {\n return attr === null ? void 0 : attr.toLowerCase() === "true";\n}\nfunction isElementIgnoredForAria(element) {\n return ["STYLE", "SCRIPT", "NOSCRIPT", "TEMPLATE"].includes(elementSafeTagName(element));\n}\nfunction isElementHiddenForAria(element) {\n if (isElementIgnoredForAria(element))\n return true;\n const style = getElementComputedStyle(element);\n const isSlot = element.nodeName === "SLOT";\n if ((style == null ? void 0 : style.display) === "contents" && !isSlot) {\n for (let child = element.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === 1 && !isElementHiddenForAria(child))\n return false;\n if (child.nodeType === 3 && isVisibleTextNode(child))\n return false;\n }\n return true;\n }\n const isOptionInsideSelect = element.nodeName === "OPTION" && !!element.closest("select");\n if (!isOptionInsideSelect && !isSlot && !isElementStyleVisibilityVisible(element, style))\n return true;\n return belongsToDisplayNoneOrAriaHiddenOrNonSlotted(element);\n}\nfunction belongsToDisplayNoneOrAriaHiddenOrNonSlotted(element) {\n let hidden = cacheIsHidden == null ? void 0 : cacheIsHidden.get(element);\n if (hidden === void 0) {\n hidden = false;\n if (element.parentElement && element.parentElement.shadowRoot && !element.assignedSlot)\n hidden = true;\n if (!hidden) {\n const style = getElementComputedStyle(element);\n hidden = !style || style.display === "none" || getAriaBoolean(element.getAttribute("aria-hidden")) === true;\n }\n if (!hidden) {\n const parent = parentElementOrShadowHost(element);\n if (parent)\n hidden = belongsToDisplayNoneOrAriaHiddenOrNonSlotted(parent);\n }\n cacheIsHidden == null ? void 0 : cacheIsHidden.set(element, hidden);\n }\n return hidden;\n}\nfunction getIdRefs(element, ref) {\n if (!ref)\n return [];\n const root = enclosingShadowRootOrDocument(element);\n if (!root)\n return [];\n try {\n const ids = ref.split(" ").filter((id) => !!id);\n const result = [];\n for (const id of ids) {\n const firstElement = root.querySelector("#" + CSS.escape(id));\n if (firstElement && !result.includes(firstElement))\n result.push(firstElement);\n }\n return result;\n } catch (e) {\n return [];\n }\n}\nfunction trimFlatString(s) {\n return s.trim();\n}\nfunction asFlatString(s) {\n return s.split("\\xA0").map((chunk) => chunk.replace(/\\r\\n/g, "\\n").replace(/[\\u200b\\u00ad]/g, "").replace(/\\s\\s*/g, " ")).join("\\xA0").trim();\n}\nfunction queryInAriaOwned(element, selector) {\n const result = [...element.querySelectorAll(selector)];\n for (const owned of getIdRefs(element, element.getAttribute("aria-owns"))) {\n if (owned.matches(selector))\n result.push(owned);\n result.push(...owned.querySelectorAll(selector));\n }\n return result;\n}\nfunction getCSSContent(element, pseudo) {\n const cache = pseudo === "::before" ? cachePseudoContentBefore : pseudo === "::after" ? cachePseudoContentAfter : cachePseudoContent;\n if (cache == null ? void 0 : cache.has(element))\n return cache == null ? void 0 : cache.get(element);\n const style = getElementComputedStyle(element, pseudo);\n let content;\n if (style) {\n const contentValue = style.content;\n if (contentValue && contentValue !== "none" && contentValue !== "normal") {\n if (style.display !== "none" && style.visibility !== "hidden") {\n content = parseCSSContentPropertyAsString(element, contentValue, !!pseudo);\n }\n }\n }\n if (pseudo && content !== void 0) {\n const display = (style == null ? void 0 : style.display) || "inline";\n if (display !== "inline")\n content = " " + content + " ";\n }\n if (cache)\n cache.set(element, content);\n return content;\n}\nfunction parseCSSContentPropertyAsString(element, content, isPseudo) {\n if (!content || content === "none" || content === "normal") {\n return;\n }\n try {\n let tokens = tokenize(content).filter((token) => !(token instanceof WhitespaceToken));\n const delimIndex = tokens.findIndex((token) => token instanceof DelimToken && token.value === "/");\n if (delimIndex !== -1) {\n tokens = tokens.slice(delimIndex + 1);\n } else if (!isPseudo) {\n return;\n }\n const accumulated = [];\n let index = 0;\n while (index < tokens.length) {\n if (tokens[index] instanceof StringToken) {\n accumulated.push(tokens[index].value);\n index++;\n } else if (index + 2 < tokens.length && tokens[index] instanceof FunctionToken && tokens[index].value === "attr" && tokens[index + 1] instanceof IdentToken && tokens[index + 2] instanceof CloseParenToken) {\n const attrName = tokens[index + 1].value;\n accumulated.push(element.getAttribute(attrName) || "");\n index += 3;\n } else {\n return;\n }\n }\n return accumulated.join("");\n } catch {\n }\n}\nfunction getAriaLabelledByElements(element) {\n const ref = element.getAttribute("aria-labelledby");\n if (ref === null)\n return null;\n const refs = getIdRefs(element, ref);\n return refs.length ? refs : null;\n}\nfunction allowsNameFromContent(role, targetDescendant) {\n const alwaysAllowsNameFromContent = ["button", "cell", "checkbox", "columnheader", "gridcell", "heading", "link", "menuitem", "menuitemcheckbox", "menuitemradio", "option", "radio", "row", "rowheader", "switch", "tab", "tooltip", "treeitem"].includes(role);\n const descendantAllowsNameFromContent = targetDescendant && ["", "caption", "code", "contentinfo", "definition", "deletion", "emphasis", "insertion", "list", "listitem", "mark", "none", "paragraph", "presentation", "region", "row", "rowgroup", "section", "strong", "subscript", "superscript", "table", "term", "time"].includes(role);\n return alwaysAllowsNameFromContent || descendantAllowsNameFromContent;\n}\nfunction getElementAccessibleName(element, includeHidden) {\n const cache = includeHidden ? cacheAccessibleNameHidden : cacheAccessibleName;\n let accessibleName = cache == null ? void 0 : cache.get(element);\n if (accessibleName === void 0) {\n accessibleName = "";\n const elementProhibitsNaming = ["caption", "code", "definition", "deletion", "emphasis", "generic", "insertion", "mark", "paragraph", "presentation", "strong", "subscript", "suggestion", "superscript", "term", "time"].includes(getAriaRole(element) || "");\n if (!elementProhibitsNaming) {\n accessibleName = asFlatString(getTextAlternativeInternal(element, {\n includeHidden,\n visitedElements: /* @__PURE__ */ new Set(),\n embeddedInTargetElement: "self"\n }));\n }\n cache == null ? void 0 : cache.set(element, accessibleName);\n }\n return accessibleName;\n}\nfunction getElementAccessibleDescription(element, includeHidden) {\n const cache = includeHidden ? cacheAccessibleDescriptionHidden : cacheAccessibleDescription;\n let accessibleDescription = cache == null ? void 0 : cache.get(element);\n if (accessibleDescription === void 0) {\n accessibleDescription = "";\n if (element.hasAttribute("aria-describedby")) {\n const describedBy = getIdRefs(element, element.getAttribute("aria-describedby"));\n accessibleDescription = asFlatString(describedBy.map((ref) => getTextAlternativeInternal(ref, {\n includeHidden,\n visitedElements: /* @__PURE__ */ new Set(),\n embeddedInDescribedBy: { element: ref, hidden: isElementHiddenForAria(ref) }\n })).join(" "));\n } else if (element.hasAttribute("aria-description")) {\n accessibleDescription = asFlatString(element.getAttribute("aria-description") || "");\n } else {\n accessibleDescription = asFlatString(element.getAttribute("title") || "");\n }\n cache == null ? void 0 : cache.set(element, accessibleDescription);\n }\n return accessibleDescription;\n}\nvar kAriaInvalidRoles = [\n "application",\n "checkbox",\n "columnheader",\n "combobox",\n "gridcell",\n "listbox",\n "radiogroup",\n "rowheader",\n "searchbox",\n "slider",\n "spinbutton",\n "switch",\n "textbox",\n "tree"\n];\nfunction getAriaInvalid(element) {\n const ariaInvalid = element.getAttribute("aria-invalid");\n if (!ariaInvalid || ariaInvalid.trim() === "" || ariaInvalid.toLocaleLowerCase() === "false")\n return "false";\n if (ariaInvalid === "true" || ariaInvalid === "grammar" || ariaInvalid === "spelling")\n return ariaInvalid;\n return "true";\n}\nfunction getValidityInvalid(element) {\n if ("validity" in element) {\n const validity = element.validity;\n return (validity == null ? void 0 : validity.valid) === false;\n }\n return false;\n}\nfunction getElementAccessibleErrorMessage(element) {\n const cache = cacheAccessibleErrorMessage;\n let accessibleErrorMessage = cacheAccessibleErrorMessage == null ? void 0 : cacheAccessibleErrorMessage.get(element);\n if (accessibleErrorMessage === void 0) {\n accessibleErrorMessage = "";\n const isAriaInvalid = getAriaInvalid(element) !== "false";\n const isValidityInvalid = getValidityInvalid(element);\n if (isAriaInvalid || isValidityInvalid) {\n const errorMessageId = element.getAttribute("aria-errormessage");\n const errorMessages = getIdRefs(element, errorMessageId);\n const parts = errorMessages.map((errorMessage) => asFlatString(\n getTextAlternativeInternal(errorMessage, {\n visitedElements: /* @__PURE__ */ new Set(),\n embeddedInDescribedBy: { element: errorMessage, hidden: isElementHiddenForAria(errorMessage) }\n })\n ));\n accessibleErrorMessage = parts.join(" ").trim();\n }\n cache == null ? void 0 : cache.set(element, accessibleErrorMessage);\n }\n return accessibleErrorMessage;\n}\nfunction getTextAlternativeInternal(element, options) {\n var _a, _b, _c, _d;\n if (options.visitedElements.has(element))\n return "";\n const childOptions = {\n ...options,\n embeddedInTargetElement: options.embeddedInTargetElement === "self" ? "descendant" : options.embeddedInTargetElement\n };\n if (!options.includeHidden) {\n const isEmbeddedInHiddenReferenceTraversal = !!((_a = options.embeddedInLabelledBy) == null ? void 0 : _a.hidden) || !!((_b = options.embeddedInDescribedBy) == null ? void 0 : _b.hidden) || !!((_c = options.embeddedInNativeTextAlternative) == null ? void 0 : _c.hidden) || !!((_d = options.embeddedInLabel) == null ? void 0 : _d.hidden);\n if (isElementIgnoredForAria(element) || !isEmbeddedInHiddenReferenceTraversal && isElementHiddenForAria(element)) {\n options.visitedElements.add(element);\n return "";\n }\n }\n const labelledBy = getAriaLabelledByElements(element);\n if (!options.embeddedInLabelledBy) {\n const accessibleName = (labelledBy || []).map((ref) => getTextAlternativeInternal(ref, {\n ...options,\n embeddedInLabelledBy: { element: ref, hidden: isElementHiddenForAria(ref) },\n embeddedInDescribedBy: void 0,\n embeddedInTargetElement: void 0,\n embeddedInLabel: void 0,\n embeddedInNativeTextAlternative: void 0\n })).join(" ");\n if (accessibleName)\n return accessibleName;\n }\n const role = getAriaRole(element) || "";\n const tagName = elementSafeTagName(element);\n if (!!options.embeddedInLabel || !!options.embeddedInLabelledBy || options.embeddedInTargetElement === "descendant") {\n const isOwnLabel = [...element.labels || []].includes(element);\n const isOwnLabelledBy = (labelledBy || []).includes(element);\n if (!isOwnLabel && !isOwnLabelledBy) {\n if (role === "textbox") {\n options.visitedElements.add(element);\n if (tagName === "INPUT" || tagName === "TEXTAREA")\n return element.value;\n return element.textContent || "";\n }\n if (["combobox", "listbox"].includes(role)) {\n options.visitedElements.add(element);\n let selectedOptions;\n if (tagName === "SELECT") {\n selectedOptions = [...element.selectedOptions];\n if (!selectedOptions.length && element.options.length)\n selectedOptions.push(element.options[0]);\n } else {\n const listbox = role === "combobox" ? queryInAriaOwned(element, "*").find((e) => getAriaRole(e) === "listbox") : element;\n selectedOptions = listbox ? queryInAriaOwned(listbox, \'[aria-selected="true"]\').filter((e) => getAriaRole(e) === "option") : [];\n }\n if (!selectedOptions.length && tagName === "INPUT") {\n return element.value;\n }\n return selectedOptions.map((option) => getTextAlternativeInternal(option, childOptions)).join(" ");\n }\n if (["progressbar", "scrollbar", "slider", "spinbutton", "meter"].includes(role)) {\n options.visitedElements.add(element);\n if (element.hasAttribute("aria-valuetext"))\n return element.getAttribute("aria-valuetext") || "";\n if (element.hasAttribute("aria-valuenow"))\n return element.getAttribute("aria-valuenow") || "";\n return element.getAttribute("value") || "";\n }\n if (["menu"].includes(role)) {\n options.visitedElements.add(element);\n return "";\n }\n }\n }\n const ariaLabel = element.getAttribute("aria-label") || "";\n if (trimFlatString(ariaLabel)) {\n options.visitedElements.add(element);\n return ariaLabel;\n }\n if (!["presentation", "none"].includes(role)) {\n if (tagName === "INPUT" && ["button", "submit", "reset"].includes(element.type)) {\n options.visitedElements.add(element);\n const value = element.value || "";\n if (trimFlatString(value))\n return value;\n if (element.type === "submit")\n return "Submit";\n if (element.type === "reset")\n return "Reset";\n const title = element.getAttribute("title") || "";\n return title;\n }\n if (tagName === "INPUT" && element.type === "file") {\n options.visitedElements.add(element);\n const labels = element.labels || [];\n if (labels.length && !options.embeddedInLabelledBy)\n return getAccessibleNameFromAssociatedLabels(labels, options);\n return "Choose File";\n }\n if (tagName === "INPUT" && element.type === "image") {\n options.visitedElements.add(element);\n const labels = element.labels || [];\n if (labels.length && !options.embeddedInLabelledBy)\n return getAccessibleNameFromAssociatedLabels(labels, options);\n const alt = element.getAttribute("alt") || "";\n if (trimFlatString(alt))\n return alt;\n const title = element.getAttribute("title") || "";\n if (trimFlatString(title))\n return title;\n return "Submit";\n }\n if (!labelledBy && tagName === "BUTTON") {\n options.visitedElements.add(element);\n const labels = element.labels || [];\n if (labels.length)\n return getAccessibleNameFromAssociatedLabels(labels, options);\n }\n if (!labelledBy && tagName === "OUTPUT") {\n options.visitedElements.add(element);\n const labels = element.labels || [];\n if (labels.length)\n return getAccessibleNameFromAssociatedLabels(labels, options);\n return element.getAttribute("title") || "";\n }\n if (!labelledBy && (tagName === "TEXTAREA" || tagName === "SELECT" || tagName === "INPUT")) {\n options.visitedElements.add(element);\n const labels = element.labels || [];\n if (labels.length)\n return getAccessibleNameFromAssociatedLabels(labels, options);\n const usePlaceholder = tagName === "INPUT" && ["text", "password", "search", "tel", "email", "url"].includes(element.type) || tagName === "TEXTAREA";\n const placeholder = element.getAttribute("placeholder") || "";\n const title = element.getAttribute("title") || "";\n if (!usePlaceholder || title)\n return title;\n return placeholder;\n }\n if (!labelledBy && tagName === "FIELDSET") {\n options.visitedElements.add(element);\n for (let child = element.firstElementChild; child; child = child.nextElementSibling) {\n if (elementSafeTagName(child) === "LEGEND") {\n return getTextAlternativeInternal(child, {\n ...childOptions,\n embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) }\n });\n }\n }\n const title = element.getAttribute("title") || "";\n return title;\n }\n if (!labelledBy && tagName === "FIGURE") {\n options.visitedElements.add(element);\n for (let child = element.firstElementChild; child; child = child.nextElementSibling) {\n if (elementSafeTagName(child) === "FIGCAPTION") {\n return getTextAlternativeInternal(child, {\n ...childOptions,\n embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) }\n });\n }\n }\n const title = element.getAttribute("title") || "";\n return title;\n }\n if (tagName === "IMG") {\n options.visitedElements.add(element);\n const alt = element.getAttribute("alt") || "";\n if (trimFlatString(alt))\n return alt;\n const title = element.getAttribute("title") || "";\n return title;\n }\n if (tagName === "TABLE") {\n options.visitedElements.add(element);\n for (let child = element.firstElementChild; child; child = child.nextElementSibling) {\n if (elementSafeTagName(child) === "CAPTION") {\n return getTextAlternativeInternal(child, {\n ...childOptions,\n embeddedInNativeTextAlternative: { element: child, hidden: isElementHiddenForAria(child) }\n });\n }\n }\n const summary = element.getAttribute("summary") || "";\n if (summary)\n return summary;\n }\n if (tagName === "AREA") {\n options.visitedElements.add(element);\n const alt = element.getAttribute("alt") || "";\n if (trimFlatString(alt))\n return alt;\n const title = element.getAttribute("title") || "";\n return title;\n }\n if (tagName === "SVG" || element.ownerSVGElement) {\n options.visitedElements.add(element);\n for (let child = element.firstElementChild; child; child = child.nextElementSibling) {\n if (elementSafeTagName(child) === "TITLE" && child.ownerSVGElement) {\n return getTextAlternativeInternal(child, {\n ...childOptions,\n embeddedInLabelledBy: { element: child, hidden: isElementHiddenForAria(child) }\n });\n }\n }\n }\n if (element.ownerSVGElement && tagName === "A") {\n const title = element.getAttribute("xlink:title") || "";\n if (trimFlatString(title)) {\n options.visitedElements.add(element);\n return title;\n }\n }\n }\n const shouldNameFromContentForSummary = tagName === "SUMMARY" && !["presentation", "none"].includes(role);\n if (allowsNameFromContent(role, options.embeddedInTargetElement === "descendant") || shouldNameFromContentForSummary || !!options.embeddedInLabelledBy || !!options.embeddedInDescribedBy || !!options.embeddedInLabel || !!options.embeddedInNativeTextAlternative) {\n options.visitedElements.add(element);\n const accessibleName = innerAccumulatedElementText(element, childOptions);\n const maybeTrimmedAccessibleName = options.embeddedInTargetElement === "self" ? trimFlatString(accessibleName) : accessibleName;\n if (maybeTrimmedAccessibleName)\n return accessibleName;\n }\n if (!["presentation", "none"].includes(role) || tagName === "IFRAME") {\n options.visitedElements.add(element);\n const title = element.getAttribute("title") || "";\n if (trimFlatString(title))\n return title;\n }\n options.visitedElements.add(element);\n return "";\n}\nfunction innerAccumulatedElementText(element, options) {\n const tokens = [];\n const visit = (node, skipSlotted) => {\n var _a;\n if (skipSlotted && node.assignedSlot)\n return;\n if (node.nodeType === 1) {\n const display = ((_a = getElementComputedStyle(node)) == null ? void 0 : _a.display) || "inline";\n let token = getTextAlternativeInternal(node, options);\n if (display !== "inline" || node.nodeName === "BR")\n token = " " + token + " ";\n tokens.push(token);\n } else if (node.nodeType === 3) {\n tokens.push(node.textContent || "");\n }\n };\n tokens.push(getCSSContent(element, "::before") || "");\n const content = getCSSContent(element);\n if (content !== void 0) {\n tokens.push(content);\n } else {\n const assignedNodes = element.nodeName === "SLOT" ? element.assignedNodes() : [];\n if (assignedNodes.length) {\n for (const child of assignedNodes)\n visit(child, false);\n } else {\n for (let child = element.firstChild; child; child = child.nextSibling)\n visit(child, true);\n if (element.shadowRoot) {\n for (let child = element.shadowRoot.firstChild; child; child = child.nextSibling)\n visit(child, true);\n }\n for (const owned of getIdRefs(element, element.getAttribute("aria-owns")))\n visit(owned, true);\n }\n }\n tokens.push(getCSSContent(element, "::after") || "");\n return tokens.join("");\n}\nvar kAriaSelectedRoles = ["gridcell", "option", "row", "tab", "rowheader", "columnheader", "treeitem"];\nfunction getAriaSelected(element) {\n if (elementSafeTagName(element) === "OPTION")\n return element.selected;\n if (kAriaSelectedRoles.includes(getAriaRole(element) || ""))\n return getAriaBoolean(element.getAttribute("aria-selected")) === true;\n return false;\n}\nvar kAriaCheckedRoles = ["checkbox", "menuitemcheckbox", "option", "radio", "switch", "menuitemradio", "treeitem"];\nfunction getAriaChecked(element) {\n const result = getChecked(element, true);\n return result === "error" ? false : result;\n}\nfunction getCheckedAllowMixed(element) {\n return getChecked(element, true);\n}\nfunction getCheckedWithoutMixed(element) {\n const result = getChecked(element, false);\n return result;\n}\nfunction getChecked(element, allowMixed) {\n const tagName = elementSafeTagName(element);\n if (allowMixed && tagName === "INPUT" && element.indeterminate)\n return "mixed";\n if (tagName === "INPUT" && ["checkbox", "radio"].includes(element.type))\n return element.checked;\n if (kAriaCheckedRoles.includes(getAriaRole(element) || "")) {\n const checked = element.getAttribute("aria-checked");\n if (checked === "true")\n return true;\n if (allowMixed && checked === "mixed")\n return "mixed";\n return false;\n }\n return "error";\n}\nvar kAriaReadonlyRoles = ["checkbox", "combobox", "grid", "gridcell", "listbox", "radiogroup", "slider", "spinbutton", "textbox", "columnheader", "rowheader", "searchbox", "switch", "treegrid"];\nfunction getReadonly(element) {\n const tagName = elementSafeTagName(element);\n if (["INPUT", "TEXTAREA", "SELECT"].includes(tagName))\n return element.hasAttribute("readonly");\n if (kAriaReadonlyRoles.includes(getAriaRole(element) || ""))\n return element.getAttribute("aria-readonly") === "true";\n if (element.isContentEditable)\n return false;\n return "error";\n}\nvar kAriaPressedRoles = ["button"];\nfunction getAriaPressed(element) {\n if (kAriaPressedRoles.includes(getAriaRole(element) || "")) {\n const pressed = element.getAttribute("aria-pressed");\n if (pressed === "true")\n return true;\n if (pressed === "mixed")\n return "mixed";\n }\n return false;\n}\nvar kAriaExpandedRoles = ["application", "button", "checkbox", "combobox", "gridcell", "link", "listbox", "menuitem", "row", "rowheader", "tab", "treeitem", "columnheader", "menuitemcheckbox", "menuitemradio", "rowheader", "switch"];\nfunction getAriaExpanded(element) {\n if (elementSafeTagName(element) === "DETAILS")\n return element.open;\n if (kAriaExpandedRoles.includes(getAriaRole(element) || "")) {\n const expanded = element.getAttribute("aria-expanded");\n if (expanded === null)\n return void 0;\n if (expanded === "true")\n return true;\n return false;\n }\n return void 0;\n}\nvar kAriaLevelRoles = ["heading", "listitem", "row", "treeitem"];\nfunction getAriaLevel(element) {\n const native = { "H1": 1, "H2": 2, "H3": 3, "H4": 4, "H5": 5, "H6": 6 }[elementSafeTagName(element)];\n if (native)\n return native;\n if (kAriaLevelRoles.includes(getAriaRole(element) || "")) {\n const attr = element.getAttribute("aria-level");\n const value = attr === null ? Number.NaN : Number(attr);\n if (Number.isInteger(value) && value >= 1)\n return value;\n }\n return 0;\n}\nvar kAriaDisabledRoles = ["application", "button", "composite", "gridcell", "group", "input", "link", "menuitem", "scrollbar", "separator", "tab", "checkbox", "columnheader", "combobox", "grid", "listbox", "menu", "menubar", "menuitemcheckbox", "menuitemradio", "option", "radio", "radiogroup", "row", "rowheader", "searchbox", "select", "slider", "spinbutton", "switch", "tablist", "textbox", "toolbar", "tree", "treegrid", "treeitem"];\nfunction getAriaDisabled(element) {\n return isNativelyDisabled(element) || hasExplicitAriaDisabled(element);\n}\nfunction isNativelyDisabled(element) {\n const isNativeFormControl = ["BUTTON", "INPUT", "SELECT", "TEXTAREA", "OPTION", "OPTGROUP"].includes(elementSafeTagName(element));\n return isNativeFormControl && (element.hasAttribute("disabled") || belongsToDisabledOptGroup(element) || belongsToDisabledFieldSet(element));\n}\nfunction belongsToDisabledOptGroup(element) {\n return elementSafeTagName(element) === "OPTION" && !!element.closest("OPTGROUP[DISABLED]");\n}\nfunction belongsToDisabledFieldSet(element) {\n const fieldSetElement = element == null ? void 0 : element.closest("FIELDSET[DISABLED]");\n if (!fieldSetElement)\n return false;\n const legendElement = fieldSetElement.querySelector(":scope > LEGEND");\n return !legendElement || !legendElement.contains(element);\n}\nfunction hasExplicitAriaDisabled(element, isAncestor = false) {\n if (!element)\n return false;\n if (isAncestor || kAriaDisabledRoles.includes(getAriaRole(element) || "")) {\n const attribute = (element.getAttribute("aria-disabled") || "").toLowerCase();\n if (attribute === "true")\n return true;\n if (attribute === "false")\n return false;\n return hasExplicitAriaDisabled(parentElementOrShadowHost(element), true);\n }\n return false;\n}\nfunction getAccessibleNameFromAssociatedLabels(labels, options) {\n return [...labels].map((label) => getTextAlternativeInternal(label, {\n ...options,\n embeddedInLabel: { element: label, hidden: isElementHiddenForAria(label) },\n embeddedInNativeTextAlternative: void 0,\n embeddedInLabelledBy: void 0,\n embeddedInDescribedBy: void 0,\n embeddedInTargetElement: void 0\n })).filter((accessibleName) => !!accessibleName).join(" ");\n}\nfunction receivesPointerEvents(element) {\n const cache = cachePointerEvents;\n let e = element;\n let result;\n const parents = [];\n for (; e; e = parentElementOrShadowHost(e)) {\n const cached = cache.get(e);\n if (cached !== void 0) {\n result = cached;\n break;\n }\n parents.push(e);\n const style = getElementComputedStyle(e);\n if (!style) {\n result = true;\n break;\n }\n const value = style.pointerEvents;\n if (value) {\n result = value !== "none";\n break;\n }\n }\n if (result === void 0)\n result = true;\n for (const parent of parents)\n cache.set(parent, result);\n return result;\n}\nvar cacheAccessibleName;\nvar cacheAccessibleNameHidden;\nvar cacheAccessibleDescription;\nvar cacheAccessibleDescriptionHidden;\nvar cacheAccessibleErrorMessage;\nvar cacheIsHidden;\nvar cachePseudoContent;\nvar cachePseudoContentBefore;\nvar cachePseudoContentAfter;\nvar cachePointerEvents;\nvar cachesCounter2 = 0;\nfunction beginAriaCaches() {\n beginDOMCaches();\n ++cachesCounter2;\n cacheAccessibleName != null ? cacheAccessibleName : cacheAccessibleName = /* @__PURE__ */ new Map();\n cacheAccessibleNameHidden != null ? cacheAccessibleNameHidden : cacheAccessibleNameHidden = /* @__PURE__ */ new Map();\n cacheAccessibleDescription != null ? cacheAccessibleDescription : cacheAccessibleDescription = /* @__PURE__ */ new Map();\n cacheAccessibleDescriptionHidden != null ? cacheAccessibleDescriptionHidden : cacheAccessibleDescriptionHidden = /* @__PURE__ */ new Map();\n cacheAccessibleErrorMessage != null ? cacheAccessibleErrorMessage : cacheAccessibleErrorMessage = /* @__PURE__ */ new Map();\n cacheIsHidden != null ? cacheIsHidden : cacheIsHidden = /* @__PURE__ */ new Map();\n cachePseudoContent != null ? cachePseudoContent : cachePseudoContent = /* @__PURE__ */ new Map();\n cachePseudoContentBefore != null ? cachePseudoContentBefore : cachePseudoContentBefore = /* @__PURE__ */ new Map();\n cachePseudoContentAfter != null ? cachePseudoContentAfter : cachePseudoContentAfter = /* @__PURE__ */ new Map();\n cachePointerEvents != null ? cachePointerEvents : cachePointerEvents = /* @__PURE__ */ new Map();\n}\nfunction endAriaCaches() {\n if (!--cachesCounter2) {\n cacheAccessibleName = void 0;\n cacheAccessibleNameHidden = void 0;\n cacheAccessibleDescription = void 0;\n cacheAccessibleDescriptionHidden = void 0;\n cacheAccessibleErrorMessage = void 0;\n cacheIsHidden = void 0;\n cachePseudoContent = void 0;\n cachePseudoContentBefore = void 0;\n cachePseudoContentAfter = void 0;\n cachePointerEvents = void 0;\n }\n endDOMCaches();\n}\nvar inputTypeToRole = {\n "button": "button",\n "checkbox": "checkbox",\n "image": "button",\n "number": "spinbutton",\n "radio": "radio",\n "range": "slider",\n "reset": "button",\n "submit": "button"\n};\n\n// packages/injected/src/ariaSnapshot.ts\nvar lastRef = 0;\nfunction toInternalOptions(options) {\n const renderBoxes = options.boxes;\n if (options.mode === "ai") {\n return {\n visibility: "ariaOrVisible",\n refs: "interactable",\n refPrefix: options.refPrefix,\n includeGenericRole: true,\n renderActive: !options.doNotRenderActive,\n renderCursorPointer: true,\n renderBoxes\n };\n }\n if (options.mode === "autoexpect") {\n return { visibility: "ariaAndVisible", refs: "none", renderBoxes };\n }\n if (options.mode === "codegen") {\n return { visibility: "aria", refs: "none", renderStringsAsRegex: true, renderBoxes };\n }\n return { visibility: "aria", refs: "none", renderBoxes };\n}\nfunction generateAriaTree(rootElement, publicOptions) {\n const options = toInternalOptions(publicOptions);\n const visited = /* @__PURE__ */ new Set();\n const snapshot = {\n root: { role: "fragment", name: "", children: [], props: {}, box: computeBox(rootElement), receivesPointerEvents: true },\n elements: /* @__PURE__ */ new Map(),\n refs: /* @__PURE__ */ new Map(),\n iframeRefs: []\n };\n setAriaNodeElement(snapshot.root, rootElement);\n const visit = (ariaNode, node, parentElementVisible) => {\n if (visited.has(node))\n return;\n visited.add(node);\n if (node.nodeType === Node.TEXT_NODE && node.nodeValue) {\n if (!parentElementVisible)\n return;\n const text = node.nodeValue;\n if (ariaNode.role !== "textbox" && text)\n ariaNode.children.push(node.nodeValue || "");\n return;\n }\n if (node.nodeType !== Node.ELEMENT_NODE)\n return;\n const element = node;\n const isElementVisibleForAria = !isElementHiddenForAria(element);\n let visible = isElementVisibleForAria;\n if (options.visibility === "ariaOrVisible")\n visible = isElementVisibleForAria || isElementVisible(element);\n if (options.visibility === "ariaAndVisible")\n visible = isElementVisibleForAria && isElementVisible(element);\n if (options.visibility === "aria" && !visible)\n return;\n const ariaChildren = [];\n if (element.hasAttribute("aria-owns")) {\n const ids = element.getAttribute("aria-owns").split(/\\s+/);\n for (const id of ids) {\n const ownedElement = rootElement.ownerDocument.getElementById(id);\n if (ownedElement)\n ariaChildren.push(ownedElement);\n }\n }\n const childAriaNode = visible ? toAriaNode(element, options) : null;\n if (childAriaNode) {\n if (childAriaNode.ref) {\n snapshot.elements.set(childAriaNode.ref, element);\n snapshot.refs.set(element, childAriaNode.ref);\n if (childAriaNode.role === "iframe")\n snapshot.iframeRefs.push(childAriaNode.ref);\n }\n ariaNode.children.push(childAriaNode);\n }\n processElement(childAriaNode || ariaNode, element, ariaChildren, visible);\n };\n function processElement(ariaNode, element, ariaChildren, parentElementVisible) {\n var _a;\n const display = ((_a = getElementComputedStyle(element)) == null ? void 0 : _a.display) || "inline";\n const treatAsBlock = display !== "inline" || element.nodeName === "BR" ? " " : "";\n if (treatAsBlock)\n ariaNode.children.push(treatAsBlock);\n ariaNode.children.push(getCSSContent(element, "::before") || "");\n const assignedNodes = element.nodeName === "SLOT" ? element.assignedNodes() : [];\n if (assignedNodes.length) {\n for (const child of assignedNodes)\n visit(ariaNode, child, parentElementVisible);\n } else {\n for (let child = element.firstChild; child; child = child.nextSibling) {\n if (!child.assignedSlot)\n visit(ariaNode, child, parentElementVisible);\n }\n if (element.shadowRoot) {\n for (let child = element.shadowRoot.firstChild; child; child = child.nextSibling)\n visit(ariaNode, child, parentElementVisible);\n }\n }\n for (const child of ariaChildren)\n visit(ariaNode, child, parentElementVisible);\n ariaNode.children.push(getCSSContent(element, "::after") || "");\n if (treatAsBlock)\n ariaNode.children.push(treatAsBlock);\n if (ariaNode.children.length === 1 && ariaNode.name === ariaNode.children[0])\n ariaNode.children = [];\n if (ariaNode.role === "link" && element.hasAttribute("href")) {\n const href = element.getAttribute("href");\n ariaNode.props["url"] = href;\n }\n if (ariaNode.role === "textbox" && element.hasAttribute("placeholder") && element.getAttribute("placeholder") !== ariaNode.name) {\n const placeholder = element.getAttribute("placeholder");\n ariaNode.props["placeholder"] = placeholder;\n }\n }\n beginAriaCaches();\n try {\n visit(snapshot.root, rootElement, true);\n } finally {\n endAriaCaches();\n }\n normalizeStringChildren(snapshot.root);\n normalizeGenericRoles(snapshot.root);\n return snapshot;\n}\nfunction computeAriaRef(ariaNode, options) {\n var _a;\n if (options.refs === "none")\n return;\n if (options.refs === "interactable" && (!ariaNode.box.visible || !ariaNode.receivesPointerEvents))\n return;\n const element = ariaNodeElement(ariaNode);\n let ariaRef = element._ariaRef;\n if (!ariaRef || ariaRef.role !== ariaNode.role || ariaRef.name !== ariaNode.name) {\n ariaRef = { role: ariaNode.role, name: ariaNode.name, ref: ((_a = options.refPrefix) != null ? _a : "") + "e" + ++lastRef };\n element._ariaRef = ariaRef;\n }\n ariaNode.ref = ariaRef.ref;\n}\nfunction toAriaNode(element, options) {\n var _a;\n const active = element.ownerDocument.activeElement === element;\n if (element.nodeName === "IFRAME") {\n const ariaNode = {\n role: "iframe",\n name: "",\n children: [],\n props: {},\n box: computeBox(element),\n receivesPointerEvents: true,\n active\n };\n setAriaNodeElement(ariaNode, element);\n computeAriaRef(ariaNode, options);\n return ariaNode;\n }\n const defaultRole = options.includeGenericRole ? "generic" : null;\n const role = (_a = getAriaRole(element)) != null ? _a : defaultRole;\n if (!role || role === "presentation" || role === "none")\n return null;\n const name = normalizeWhiteSpace(getElementAccessibleName(element, false) || "");\n const receivesPointerEvents2 = receivesPointerEvents(element);\n const box = computeBox(element);\n if (role === "generic" && box.inline && element.childNodes.length === 1 && element.childNodes[0].nodeType === Node.TEXT_NODE)\n return null;\n const result = {\n role,\n name,\n children: [],\n props: {},\n box,\n receivesPointerEvents: receivesPointerEvents2,\n active\n };\n setAriaNodeElement(result, element);\n computeAriaRef(result, options);\n if (kAriaCheckedRoles.includes(role))\n result.checked = getAriaChecked(element);\n if (kAriaDisabledRoles.includes(role))\n result.disabled = getAriaDisabled(element);\n if (kAriaExpandedRoles.includes(role))\n result.expanded = getAriaExpanded(element);\n if (kAriaInvalidRoles.includes(role)) {\n const invalid = getAriaInvalid(element);\n result.invalid = invalid === "false" ? false : invalid === "true" ? true : invalid;\n }\n if (kAriaLevelRoles.includes(role))\n result.level = getAriaLevel(element);\n if (kAriaPressedRoles.includes(role))\n result.pressed = getAriaPressed(element);\n if (kAriaSelectedRoles.includes(role))\n result.selected = getAriaSelected(element);\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n if (element.type !== "checkbox" && element.type !== "radio" && element.type !== "file")\n result.children = [element.value];\n }\n return result;\n}\nfunction normalizeGenericRoles(node) {\n const normalizeChildren = (node2) => {\n const result = [];\n for (const child of node2.children || []) {\n if (typeof child === "string") {\n result.push(child);\n continue;\n }\n const normalized = normalizeChildren(child);\n result.push(...normalized);\n }\n const removeSelf = node2.role === "generic" && !node2.name && result.length <= 1 && result.every((c) => typeof c !== "string" && !!c.ref);\n if (removeSelf)\n return result;\n node2.children = result;\n return [node2];\n };\n normalizeChildren(node);\n}\nfunction normalizeStringChildren(rootA11yNode) {\n const flushChildren = (buffer, normalizedChildren) => {\n if (!buffer.length)\n return;\n const text = normalizeWhiteSpace(buffer.join(""));\n if (text)\n normalizedChildren.push(text);\n buffer.length = 0;\n };\n const visit = (ariaNode) => {\n const normalizedChildren = [];\n const buffer = [];\n for (const child of ariaNode.children || []) {\n if (typeof child === "string") {\n buffer.push(child);\n } else {\n flushChildren(buffer, normalizedChildren);\n visit(child);\n normalizedChildren.push(child);\n }\n }\n flushChildren(buffer, normalizedChildren);\n ariaNode.children = normalizedChildren.length ? normalizedChildren : [];\n if (ariaNode.children.length === 1 && ariaNode.children[0] === ariaNode.name)\n ariaNode.children = [];\n };\n visit(rootA11yNode);\n}\nfunction matchesStringOrRegex(text, template) {\n if (!template)\n return true;\n if (!text)\n return false;\n if (typeof template === "string")\n return text === template;\n return !!text.match(new RegExp(template.pattern));\n}\nfunction matchesTextValue(text, template) {\n if (!(template == null ? void 0 : template.normalized))\n return true;\n if (!text)\n return false;\n if (text === template.normalized)\n return true;\n if (text === template.raw)\n return true;\n const regex = cachedRegex(template);\n if (regex)\n return !!text.match(regex);\n return false;\n}\nvar cachedRegexSymbol = Symbol("cachedRegex");\nfunction cachedRegex(template) {\n if (template[cachedRegexSymbol] !== void 0)\n return template[cachedRegexSymbol];\n const { raw } = template;\n const canBeRegex = raw.startsWith("/") && raw.endsWith("/") && raw.length > 1;\n let regex;\n try {\n regex = canBeRegex ? new RegExp(raw.slice(1, -1)) : null;\n } catch (e) {\n regex = null;\n }\n template[cachedRegexSymbol] = regex;\n return regex;\n}\nfunction matchesExpectAriaTemplate(rootElement, template) {\n const snapshot = generateAriaTree(rootElement, { mode: "default" });\n const matches = matchesNodeDeep(snapshot.root, template, false, false);\n return {\n matches,\n received: {\n raw: renderAriaTree(snapshot, { mode: "default" }).text,\n regex: renderAriaTree(snapshot, { mode: "codegen" }).text\n }\n };\n}\nfunction getAllElementsMatchingExpectAriaTemplate(rootElement, template) {\n const root = generateAriaTree(rootElement, { mode: "default" }).root;\n const matches = matchesNodeDeep(root, template, true, false);\n return matches.map((n) => ariaNodeElement(n));\n}\nfunction matchesNode(node, template, isDeepEqual) {\n var _a;\n if (typeof node === "string" && template.kind === "text")\n return matchesTextValue(node, template.text);\n if (node === null || typeof node !== "object" || template.kind !== "role")\n return false;\n if (template.role !== "fragment" && template.role !== node.role)\n return false;\n if (template.checked !== void 0 && template.checked !== node.checked)\n return false;\n if (template.disabled !== void 0 && template.disabled !== node.disabled)\n return false;\n if (template.expanded !== void 0 && template.expanded !== node.expanded)\n return false;\n if (template.invalid !== void 0 && template.invalid !== node.invalid)\n return false;\n if (template.level !== void 0 && template.level !== node.level)\n return false;\n if (template.pressed !== void 0 && template.pressed !== node.pressed)\n return false;\n if (template.selected !== void 0 && template.selected !== node.selected)\n return false;\n if (!matchesStringOrRegex(node.name, template.name))\n return false;\n if (!matchesTextValue(node.props.url, (_a = template.props) == null ? void 0 : _a.url))\n return false;\n if (template.containerMode === "contain")\n return containsList(node.children || [], template.children || []);\n if (template.containerMode === "equal")\n return listEqual(node.children || [], template.children || [], false);\n if (template.containerMode === "deep-equal" || isDeepEqual)\n return listEqual(node.children || [], template.children || [], true);\n return containsList(node.children || [], template.children || []);\n}\nfunction listEqual(children, template, isDeepEqual) {\n if (template.length !== children.length)\n return false;\n for (let i = 0; i < template.length; ++i) {\n if (!matchesNode(children[i], template[i], isDeepEqual))\n return false;\n }\n return true;\n}\nfunction containsList(children, template) {\n if (template.length > children.length)\n return false;\n const cc = children.slice();\n const tt = template.slice();\n for (const t of tt) {\n let c = cc.shift();\n while (c) {\n if (matchesNode(c, t, false))\n break;\n c = cc.shift();\n }\n if (!c)\n return false;\n }\n return true;\n}\nfunction matchesNodeDeep(root, template, collectAll, isDeepEqual) {\n const results = [];\n const visit = (node, parent) => {\n if (matchesNode(node, template, isDeepEqual)) {\n const result = typeof node === "string" ? parent : node;\n if (result)\n results.push(result);\n return !collectAll;\n }\n if (typeof node === "string")\n return false;\n for (const child of node.children || []) {\n if (visit(child, node))\n return true;\n }\n return false;\n };\n visit(root, null);\n return results;\n}\nfunction buildByRefMap(root, map = /* @__PURE__ */ new Map()) {\n if (root == null ? void 0 : root.ref)\n map.set(root.ref, root);\n for (const child of (root == null ? void 0 : root.children) || []) {\n if (typeof child !== "string")\n buildByRefMap(child, map);\n }\n return map;\n}\nfunction compareSnapshots(ariaSnapshot, previousSnapshot) {\n var _a;\n const previousByRef = buildByRefMap(previousSnapshot == null ? void 0 : previousSnapshot.root);\n const result = /* @__PURE__ */ new Map();\n const visit = (ariaNode, previousNode) => {\n let same = ariaNode.children.length === (previousNode == null ? void 0 : previousNode.children.length) && ariaNodesEqual(ariaNode, previousNode);\n let canBeSkipped = same;\n for (let childIndex = 0; childIndex < ariaNode.children.length; childIndex++) {\n const child = ariaNode.children[childIndex];\n const previousChild = previousNode == null ? void 0 : previousNode.children[childIndex];\n if (typeof child === "string") {\n same && (same = child === previousChild);\n canBeSkipped && (canBeSkipped = child === previousChild);\n } else {\n let previous = typeof previousChild !== "string" ? previousChild : void 0;\n if (child.ref)\n previous = previousByRef.get(child.ref);\n const sameChild = visit(child, previous);\n if (!previous || !sameChild && !child.ref || previous !== previousChild)\n canBeSkipped = false;\n same && (same = sameChild && previous === previousChild);\n }\n }\n result.set(ariaNode, same ? "same" : canBeSkipped ? "skip" : "changed");\n return same;\n };\n visit(ariaSnapshot.root, previousByRef.get((_a = previousSnapshot == null ? void 0 : previousSnapshot.root) == null ? void 0 : _a.ref));\n return result;\n}\nfunction filterSnapshotDiff(nodes, statusMap) {\n const result = [];\n const visit = (ariaNode) => {\n const status = statusMap.get(ariaNode);\n if (status === "same") {\n } else if (status === "skip") {\n for (const child of ariaNode.children) {\n if (typeof child !== "string")\n visit(child);\n }\n } else {\n result.push(ariaNode);\n }\n };\n for (const node of nodes) {\n if (typeof node === "string")\n result.push(node);\n else\n visit(node);\n }\n return result;\n}\nfunction indent(depth) {\n return " ".repeat(depth);\n}\nfunction renderAriaTree(ariaSnapshot, publicOptions, previousSnapshot) {\n const options = toInternalOptions(publicOptions);\n const lines = [];\n const iframeDepths = {};\n const includeText = options.renderStringsAsRegex ? textContributesInfo : () => true;\n const renderString = options.renderStringsAsRegex ? convertToBestGuessRegex : (str) => str;\n let nodesToRender = ariaSnapshot.root.role === "fragment" ? ariaSnapshot.root.children : [ariaSnapshot.root];\n const statusMap = compareSnapshots(ariaSnapshot, previousSnapshot);\n if (previousSnapshot)\n nodesToRender = filterSnapshotDiff(nodesToRender, statusMap);\n const visitText = (text, depth) => {\n if (publicOptions.depth && depth > publicOptions.depth)\n return;\n const escaped = yamlEscapeValueIfNeeded(renderString(text));\n if (escaped)\n lines.push(indent(depth) + "- text: " + escaped);\n };\n const createKey = (ariaNode, renderCursorPointer) => {\n let key = ariaNode.role;\n if (ariaNode.name && ariaNode.name.length <= 900) {\n const name = renderString(ariaNode.name);\n if (name) {\n const stringifiedName = name.startsWith("/") && name.endsWith("/") ? name : JSON.stringify(name);\n key += " " + stringifiedName;\n }\n }\n if (ariaNode.checked === "mixed")\n key += ` [checked=mixed]`;\n if (ariaNode.checked === true)\n key += ` [checked]`;\n if (ariaNode.disabled)\n key += ` [disabled]`;\n if (ariaNode.expanded)\n key += ` [expanded]`;\n if (ariaNode.active && options.renderActive)\n key += ` [active]`;\n if (ariaNode.invalid === "grammar" || ariaNode.invalid === "spelling")\n key += ` [invalid=${ariaNode.invalid}]`;\n if (ariaNode.invalid === true)\n key += ` [invalid]`;\n if (ariaNode.level)\n key += ` [level=${ariaNode.level}]`;\n if (ariaNode.pressed === "mixed")\n key += ` [pressed=mixed]`;\n if (ariaNode.pressed === true)\n key += ` [pressed]`;\n if (ariaNode.selected === true)\n key += ` [selected]`;\n if (ariaNode.ref) {\n key += ` [ref=${ariaNode.ref}]`;\n if (renderCursorPointer && hasPointerCursor(ariaNode))\n key += " [cursor=pointer]";\n }\n if (options.renderBoxes) {\n const element = ariaNodeElement(ariaNode);\n if (element) {\n const r = element.getBoundingClientRect();\n key += ` [box=${Math.round(r.x)},${Math.round(r.y)},${Math.round(r.width)},${Math.round(r.height)}]`;\n }\n }\n return key;\n };\n const getSingleInlinedTextChild = (ariaNode) => {\n return (ariaNode == null ? void 0 : ariaNode.children.length) === 1 && typeof ariaNode.children[0] === "string" && !Object.keys(ariaNode.props).length ? ariaNode.children[0] : void 0;\n };\n const visit = (ariaNode, depth, renderCursorPointer) => {\n if (publicOptions.depth && depth > publicOptions.depth)\n return;\n if (ariaNode.role === "iframe" && ariaNode.ref)\n iframeDepths[ariaNode.ref] = depth;\n if (statusMap.get(ariaNode) === "same" && ariaNode.ref) {\n lines.push(indent(depth) + `- ref=${ariaNode.ref} [unchanged]`);\n return;\n }\n const isDiffRoot = !!previousSnapshot && !depth;\n const escapedKey = indent(depth) + "- " + (isDiffRoot ? " " : "") + yamlEscapeKeyIfNeeded(createKey(ariaNode, renderCursorPointer));\n const singleInlinedTextChild = getSingleInlinedTextChild(ariaNode);\n const isAtDepthLimit = !!publicOptions.depth && depth === publicOptions.depth;\n const hasNoChildren = !singleInlinedTextChild && (!ariaNode.children.length || isAtDepthLimit);\n if (hasNoChildren && !Object.keys(ariaNode.props).length) {\n lines.push(escapedKey);\n } else if (singleInlinedTextChild !== void 0) {\n const shouldInclude = includeText(ariaNode, singleInlinedTextChild);\n if (shouldInclude)\n lines.push(escapedKey + ": " + yamlEscapeValueIfNeeded(renderString(singleInlinedTextChild)));\n else\n lines.push(escapedKey);\n } else {\n lines.push(escapedKey + ":");\n for (const [name, value] of Object.entries(ariaNode.props))\n lines.push(indent(depth + 1) + "- /" + name + ": " + yamlEscapeValueIfNeeded(value));\n const inCursorPointer = !!ariaNode.ref && renderCursorPointer && hasPointerCursor(ariaNode);\n for (const child of ariaNode.children) {\n if (typeof child === "string")\n visitText(includeText(ariaNode, child) ? child : "", depth + 1);\n else\n visit(child, depth + 1, renderCursorPointer && !inCursorPointer);\n }\n }\n };\n for (const nodeToRender of nodesToRender) {\n if (typeof nodeToRender === "string")\n visitText(nodeToRender, 0);\n else\n visit(nodeToRender, 0, !!options.renderCursorPointer);\n }\n return { text: lines.join("\\n"), iframeDepths };\n}\nfunction convertToBestGuessRegex(text) {\n const dynamicContent = [\n // 550e8400-e29b-41d4-a716-446655440000\n { regex: /\\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\\b/, replacement: "[0-9a-fA-F-]+" },\n // 2mb\n { regex: /\\b[\\d,.]+[bkmBKM]+\\b/, replacement: "[\\\\d,.]+[bkmBKM]+" },\n // 2ms, 20s\n { regex: /\\b\\d+[hmsp]+\\b/, replacement: "\\\\d+[hmsp]+" },\n { regex: /\\b[\\d,.]+[hmsp]+\\b/, replacement: "[\\\\d,.]+[hmsp]+" },\n // Do not replace single digits with regex by default.\n // 2+ digits: [Issue 22, 22.3, 2.33, 2,333]\n { regex: /\\b\\d+,\\d+\\b/, replacement: "\\\\d+,\\\\d+" },\n { regex: /\\b\\d+\\.\\d{2,}\\b/, replacement: "\\\\d+\\\\.\\\\d+" },\n { regex: /\\b\\d{2,}\\.\\d+\\b/, replacement: "\\\\d+\\\\.\\\\d+" },\n { regex: /\\b\\d{2,}\\b/, replacement: "\\\\d+" }\n ];\n let pattern = "";\n let lastIndex = 0;\n const combinedRegex = new RegExp(dynamicContent.map((r) => "(" + r.regex.source + ")").join("|"), "g");\n text.replace(combinedRegex, (match, ...args) => {\n const offset = args[args.length - 2];\n const groups = args.slice(0, -2);\n pattern += escapeRegExp(text.slice(lastIndex, offset));\n for (let i = 0; i < groups.length; i++) {\n if (groups[i]) {\n const { replacement } = dynamicContent[i];\n pattern += replacement;\n break;\n }\n }\n lastIndex = offset + match.length;\n return match;\n });\n if (!pattern)\n return text;\n pattern += escapeRegExp(text.slice(lastIndex));\n return String(new RegExp(pattern));\n}\nfunction textContributesInfo(node, text) {\n if (!text.length)\n return false;\n if (!node.name)\n return true;\n const substr = text.length <= 200 && node.name.length <= 200 ? longestCommonSubstring(text, node.name) : "";\n let filtered = text;\n while (substr && filtered.includes(substr))\n filtered = filtered.replace(substr, "");\n return filtered.trim().length / text.length > 0.1;\n}\nvar elementSymbol = Symbol("element");\nfunction ariaNodeElement(ariaNode) {\n return ariaNode[elementSymbol];\n}\nfunction setAriaNodeElement(ariaNode, element) {\n ariaNode[elementSymbol] = element;\n}\nfunction findNewElement(from, to) {\n const node = findNewNode(from, to);\n return node ? ariaNodeElement(node) : void 0;\n}\n\n// packages/injected/src/highlight.css?inline\nvar highlight_default = ":host{font-size:13px;font-family:system-ui,Ubuntu,Droid Sans,sans-serif;color:#333;color-scheme:light}svg{position:absolute;height:0}x-pw-tooltip{backdrop-filter:blur(5px);background-color:#fff;border-radius:6px;box-shadow:0 .5rem 1.2rem #0000004d;display:none;font-size:12.8px;font-weight:400;left:0;line-height:1.5;max-width:600px;position:absolute;top:0;padding:0;flex-direction:column;overflow:hidden}x-pw-tooltip-line{display:flex;max-width:600px;padding:6px;user-select:none;cursor:pointer}x-pw-tooltip-footer{display:flex;max-width:600px;padding:6px;user-select:none;color:#777}x-pw-dialog{background-color:#fff;pointer-events:auto;border-radius:6px;box-shadow:0 .5rem 1.2rem #0000004d;display:flex;flex-direction:column;position:absolute;z-index:10;font-size:13px}x-pw-dialog:not(.autosize){width:400px;height:150px}x-pw-dialog-body{display:flex;flex-direction:column;flex:auto}x-pw-dialog-body label{margin:5px 8px;display:flex;flex-direction:row;align-items:center}x-pw-highlight{position:absolute;top:0;left:0;width:0;height:0}x-pw-action-point{position:absolute;width:20px;height:20px;background:red;border-radius:10px;margin:-10px 0 0 -10px;z-index:2}x-pw-action-cursor{position:absolute;width:18px;height:22px;pointer-events:none;z-index:4;filter:drop-shadow(0 1px 2px rgba(0,0,0,.4))}x-pw-action-cursor svg{width:100%;height:100%;position:static}x-pw-title{position:absolute;backdrop-filter:blur(5px);background-color:#00000080;color:#fff;border-radius:6px;padding:6px;font-size:24px;line-height:1.4;white-space:nowrap;user-select:none;z-index:3}x-pw-user-overlays,x-pw-user-overlay{position:absolute;inset:0}@keyframes pw-fade-out{0%{opacity:1}to{opacity:0}}x-pw-separator{height:1px;margin:6px 9px;background:#949494e5}x-pw-tool-gripper{height:28px;width:24px;margin:2px 0;cursor:grab}x-pw-tool-gripper:active{cursor:grabbing}x-pw-tool-gripper>x-div{width:16px;height:16px;margin:6px 4px;clip-path:url(#icon-gripper);background-color:#555}x-pw-tools-list>label{display:flex;align-items:center;margin:0 10px;user-select:none}x-pw-tools-list{display:flex;width:100%;border-bottom:1px solid #dddddd}x-pw-tool-item{pointer-events:auto;height:28px;width:28px;border-radius:3px}x-pw-tool-item:not(.disabled){cursor:pointer}x-pw-tool-item:not(.disabled):hover{background-color:#dbdbdb}x-pw-tool-item.toggled{background-color:#8acae480}x-pw-tool-item.toggled:not(.disabled):hover{background-color:#8acae4c4}x-pw-tool-item>x-div{width:16px;height:16px;margin:6px;background-color:#3a3a3a}x-pw-tool-item.disabled>x-div{background-color:#61616180;cursor:default}x-pw-tool-item.record.toggled{background-color:transparent}x-pw-tool-item.record.toggled:not(.disabled):hover{background-color:#dbdbdb}x-pw-tool-item.record.toggled>x-div{background-color:#a1260d}x-pw-tool-item.record.disabled.toggled>x-div{opacity:.8}x-pw-tool-item.accept>x-div{background-color:#388a34}x-pw-tool-item.record>x-div{clip-path:url(#icon-circle-large-filled)}x-pw-tool-item.record.toggled>x-div{clip-path:url(#icon-stop-circle)}x-pw-tool-item.pick-locator>x-div{clip-path:url(#icon-inspect)}x-pw-tool-item.text>x-div{clip-path:url(#icon-whole-word)}x-pw-tool-item.visibility>x-div{clip-path:url(#icon-eye)}x-pw-tool-item.value>x-div{clip-path:url(#icon-symbol-constant)}x-pw-tool-item.snapshot>x-div{clip-path:url(#icon-gist)}x-pw-tool-item.accept>x-div{clip-path:url(#icon-check)}x-pw-tool-item.cancel>x-div{clip-path:url(#icon-close)}x-pw-tool-item.succeeded>x-div{clip-path:url(#icon-pass);background-color:#388a34!important}x-pw-overlay{position:absolute;top:0;max-width:min-content;z-index:2147483647;background:transparent;pointer-events:auto}x-pw-overlay x-pw-tools-list{background-color:#fffd;box-shadow:#0000001a 0 5px 5px;border-radius:3px;border-bottom:none}x-pw-overlay x-pw-tool-item{margin:2px}textarea.text-editor{font-family:system-ui,Ubuntu,Droid Sans,sans-serif;flex:auto;border:none;margin:6px 10px;color:#333;outline:1px solid transparent!important;resize:none;padding:0;font-size:13px}textarea.text-editor.does-not-match{outline:1px solid red!important}x-div{display:block}x-spacer{flex:auto}*{box-sizing:border-box}*[hidden]{display:none!important}x-locator-editor{flex:none;width:100%;height:60px;padding:4px;border-bottom:1px solid #dddddd;outline:1px solid transparent}x-locator-editor.does-not-match{outline:1px solid red}.CodeMirror{width:100%!important;height:100%!important}x-pw-action-list{flex:auto;display:flex;flex-direction:column;user-select:none}x-pw-action-item{padding:6px 10px;cursor:pointer;overflow:hidden}x-pw-action-item:hover{background-color:#f2f2f2}x-pw-action-item:last-child{border-bottom-left-radius:6px;border-bottom-right-radius:6px}\\n";\n\n// packages/injected/src/highlight.ts\nvar Highlight = class {\n constructor(injectedScript) {\n this._renderedEntries = [];\n this._userOverlays = /* @__PURE__ */ new Map();\n this._userOverlayHidden = false;\n this._language = "javascript";\n this._elementHighlightSelectors = /* @__PURE__ */ new Map();\n this._injectedScript = injectedScript;\n const document = injectedScript.document;\n this._isUnderTest = injectedScript.isUnderTest;\n this._glassPaneElement = document.createElement("x-pw-glass");\n this._glassPaneElement.setAttribute("popover", "manual");\n this._glassPaneElement.style.inset = "0";\n this._glassPaneElement.style.width = "100%";\n this._glassPaneElement.style.height = "100%";\n this._glassPaneElement.style.maxWidth = "none";\n this._glassPaneElement.style.maxHeight = "none";\n this._glassPaneElement.style.padding = "0";\n this._glassPaneElement.style.margin = "0";\n this._glassPaneElement.style.border = "none";\n this._glassPaneElement.style.overflow = "visible";\n this._glassPaneElement.style.pointerEvents = "none";\n this._glassPaneElement.style.display = "flex";\n this._glassPaneElement.style.backgroundColor = "transparent";\n this._actionPointElement = document.createElement("x-pw-action-point");\n this._actionPointElement.setAttribute("hidden", "true");\n this._actionCursorElement = document.createElement("x-pw-action-cursor");\n this._actionCursorElement.style.visibility = "hidden";\n this._actionCursorElement.appendChild(this._createCursorSvg(document));\n this._titleElement = document.createElement("x-pw-title");\n this._titleElement.setAttribute("hidden", "true");\n this._userOverlayContainer = document.createElement("x-pw-user-overlays");\n this._userOverlayContainer.setAttribute("hidden", "true");\n this._glassPaneShadow = this._glassPaneElement.attachShadow({ mode: this._isUnderTest ? "open" : "closed" });\n if (typeof this._glassPaneShadow.adoptedStyleSheets.push === "function") {\n const sheet = new this._injectedScript.window.CSSStyleSheet();\n sheet.replaceSync(highlight_default);\n this._glassPaneShadow.adoptedStyleSheets.push(sheet);\n } else {\n const styleElement = this._injectedScript.document.createElement("style");\n styleElement.textContent = highlight_default;\n this._glassPaneShadow.appendChild(styleElement);\n }\n this._glassPaneShadow.appendChild(this._actionPointElement);\n this._glassPaneShadow.appendChild(this._actionCursorElement);\n this._glassPaneShadow.appendChild(this._titleElement);\n this._glassPaneShadow.appendChild(this._userOverlayContainer);\n }\n install() {\n if (!this._injectedScript.document.documentElement)\n return;\n if (!this._injectedScript.document.documentElement.contains(this._glassPaneElement) || this._glassPaneElement.nextElementSibling)\n this._injectedScript.document.documentElement.appendChild(this._glassPaneElement);\n this._bringToFront();\n }\n _bringToFront() {\n this._glassPaneElement.hidePopover();\n this._glassPaneElement.showPopover();\n }\n setLanguage(language) {\n this._language = language;\n }\n addElementHighlight(selector, cssStyle) {\n const key = stringifySelector(selector);\n this._elementHighlightSelectors.set(key, { selector, cssStyle });\n this._ensureElementHighlightRaf();\n }\n removeElementHighlight(selector) {\n const key = stringifySelector(selector);\n if (!this._elementHighlightSelectors.delete(key))\n return;\n if (this._elementHighlightSelectors.size === 0) {\n if (this._rafRequest) {\n this._injectedScript.utils.builtins.cancelAnimationFrame(this._rafRequest);\n this._rafRequest = void 0;\n }\n this.clearHighlight();\n }\n }\n _ensureElementHighlightRaf() {\n if (this._rafRequest)\n return;\n const tick = () => {\n const entries = [];\n for (const { selector, cssStyle } of this._elementHighlightSelectors.values()) {\n const elements = this._injectedScript.querySelectorAll(selector, this._injectedScript.document.documentElement);\n const locator = asLocator(this._language, stringifySelector(selector));\n const color = elements.length > 1 ? "#f6b26b7f" : "#6fa8dc7f";\n for (let i = 0; i < elements.length; ++i) {\n const suffix = elements.length > 1 ? ` [${i + 1} of ${elements.length}]` : "";\n entries.push({ element: elements[i], color, tooltipText: locator + suffix, cssStyle });\n }\n }\n this.updateHighlight(entries);\n this._rafRequest = this._injectedScript.utils.builtins.requestAnimationFrame(tick);\n };\n this._rafRequest = this._injectedScript.utils.builtins.requestAnimationFrame(tick);\n }\n uninstall() {\n if (this._rafRequest) {\n this._injectedScript.utils.builtins.cancelAnimationFrame(this._rafRequest);\n this._rafRequest = void 0;\n }\n this._elementHighlightSelectors.clear();\n this._glassPaneElement.remove();\n }\n showActionPoint(x, y, fadeDuration) {\n this._actionPointElement.style.top = y + "px";\n this._actionPointElement.style.left = x + "px";\n this._actionPointElement.hidden = false;\n if (fadeDuration)\n this._actionPointElement.style.animation = `pw-fade-out ${fadeDuration}ms ease-out forwards`;\n else\n this._actionPointElement.style.animation = "";\n }\n hideActionPoint() {\n this._actionPointElement.hidden = true;\n }\n moveActionCursor(x, y, fadeDuration) {\n const moveDuration = fadeDuration ? Math.max(80, Math.min(fadeDuration * 0.6, 400)) : 0;\n this._actionCursorElement.style.transition = `top ${moveDuration}ms ease, left ${moveDuration}ms ease`;\n this._actionCursorElement.style.left = x + "px";\n this._actionCursorElement.style.top = y + "px";\n this._actionCursorElement.style.visibility = "visible";\n }\n hideActionCursor() {\n this._actionCursorElement.style.visibility = "hidden";\n }\n _createCursorSvg(document) {\n const svgNs = "http://www.w3.org/2000/svg";\n const svg = document.createElementNS(svgNs, "svg");\n svg.setAttribute("viewBox", "0 0 18 22");\n const path = document.createElementNS(svgNs, "path");\n path.setAttribute("d", "M1 1 L1 17 L5.5 13 L8 20.5 L11 19.5 L8.5 12 L15 12 Z");\n path.setAttribute("fill", "white");\n path.setAttribute("stroke", "black");\n path.setAttribute("stroke-width", "1.5");\n path.setAttribute("stroke-linejoin", "round");\n svg.appendChild(path);\n return svg;\n }\n showActionTitle(text, fadeDuration, position, fontSize) {\n this._titleElement.textContent = text;\n this._titleElement.hidden = false;\n if (fadeDuration) {\n const fadeTime = fadeDuration / 4;\n this._titleElement.style.animation = `pw-fade-out ${fadeTime}ms ease-out ${fadeDuration - fadeTime}ms forwards`;\n } else {\n this._titleElement.style.animation = "";\n }\n this._titleElement.style.top = "";\n this._titleElement.style.bottom = "";\n this._titleElement.style.left = "";\n this._titleElement.style.right = "";\n this._titleElement.style.transform = "";\n switch (position) {\n case "top-left":\n this._titleElement.style.top = "6px";\n this._titleElement.style.left = "6px";\n break;\n case "top":\n this._titleElement.style.top = "6px";\n this._titleElement.style.left = "50%";\n this._titleElement.style.transform = "translateX(-50%)";\n break;\n case "bottom-left":\n this._titleElement.style.bottom = "6px";\n this._titleElement.style.left = "6px";\n break;\n case "bottom":\n this._titleElement.style.bottom = "6px";\n this._titleElement.style.left = "50%";\n this._titleElement.style.transform = "translateX(-50%)";\n break;\n case "bottom-right":\n this._titleElement.style.bottom = "6px";\n this._titleElement.style.right = "6px";\n break;\n case "top-right":\n default:\n this._titleElement.style.top = "6px";\n this._titleElement.style.right = "6px";\n break;\n }\n if (fontSize)\n this._titleElement.style.fontSize = fontSize + "px";\n }\n hideActionTitle() {\n this._titleElement.hidden = true;\n }\n addUserOverlay(id, html) {\n const element = this._injectedScript.document.createElement("div");\n element.className = "x-pw-user-overlay";\n element.innerHTML = html;\n for (const script of element.querySelectorAll("script"))\n script.remove();\n for (const el of element.querySelectorAll("*")) {\n for (const attr of [...el.attributes]) {\n if (attr.name.startsWith("on"))\n el.removeAttribute(attr.name);\n }\n }\n this._userOverlays.set(id, element);\n this._userOverlayContainer.appendChild(element);\n this._userOverlayContainer.hidden = this._userOverlayHidden;\n return id;\n }\n getUserOverlay(id) {\n return this._userOverlays.get(id);\n }\n removeUserOverlay(id) {\n const element = this._userOverlays.get(id);\n if (element) {\n element.remove();\n this._userOverlays.delete(id);\n }\n if (this._userOverlays.size === 0)\n this._userOverlayContainer.hidden = true;\n }\n setUserOverlaysVisible(visible) {\n this._userOverlayHidden = !visible;\n this._userOverlayContainer.hidden = !visible || this._userOverlays.size === 0;\n }\n clearHighlight() {\n var _a, _b;\n for (const entry of this._renderedEntries) {\n (_a = entry.highlightElement) == null ? void 0 : _a.remove();\n (_b = entry.tooltipElement) == null ? void 0 : _b.remove();\n }\n this._renderedEntries = [];\n }\n maskElements(elements, color) {\n this.updateHighlight(elements.map((element) => ({ element, color })));\n }\n updateHighlight(entries) {\n if (this._highlightIsUpToDate(entries))\n return;\n this.clearHighlight();\n for (const entry of entries) {\n const highlightElement = this._createHighlightElement();\n this._glassPaneShadow.appendChild(highlightElement);\n let tooltipElement;\n if (entry.tooltipText) {\n tooltipElement = this._injectedScript.document.createElement("x-pw-tooltip");\n this._glassPaneShadow.appendChild(tooltipElement);\n tooltipElement.style.top = "0";\n tooltipElement.style.left = "0";\n tooltipElement.style.display = "flex";\n const lineElement = this._injectedScript.document.createElement("x-pw-tooltip-line");\n lineElement.textContent = entry.tooltipText;\n tooltipElement.appendChild(lineElement);\n }\n this._renderedEntries.push({ targetElement: entry.element, box: toDOMRect(entry.box), color: entry.color, borderColor: entry.borderColor, fadeDuration: entry.fadeDuration, cssStyle: entry.cssStyle, tooltipElement, highlightElement });\n }\n for (const entry of this._renderedEntries) {\n if (!entry.box && !entry.targetElement)\n continue;\n entry.box = entry.box || entry.targetElement.getBoundingClientRect();\n if (!entry.tooltipElement)\n continue;\n const { anchorLeft, anchorTop } = this.tooltipPosition(entry.box, entry.tooltipElement);\n entry.tooltipTop = anchorTop;\n entry.tooltipLeft = anchorLeft;\n }\n for (const entry of this._renderedEntries) {\n if (entry.tooltipElement) {\n entry.tooltipElement.style.top = entry.tooltipTop + "px";\n entry.tooltipElement.style.left = entry.tooltipLeft + "px";\n }\n const box = entry.box;\n entry.highlightElement.style.backgroundColor = entry.color;\n entry.highlightElement.style.left = box.x + "px";\n entry.highlightElement.style.top = box.y + "px";\n entry.highlightElement.style.width = box.width + "px";\n entry.highlightElement.style.height = box.height + "px";\n entry.highlightElement.style.display = "block";\n if (entry.borderColor)\n entry.highlightElement.style.border = "2px solid " + entry.borderColor;\n if (entry.fadeDuration)\n entry.highlightElement.style.animation = `pw-fade-out ${entry.fadeDuration}ms ease-out forwards`;\n if (entry.cssStyle)\n entry.highlightElement.style.cssText += ";" + entry.cssStyle;\n if (this._isUnderTest)\n console.error("Highlight box for test: " + JSON.stringify({ x: box.x, y: box.y, width: box.width, height: box.height }));\n }\n }\n firstBox() {\n var _a;\n return (_a = this._renderedEntries[0]) == null ? void 0 : _a.box;\n }\n firstTooltipBox() {\n const entry = this._renderedEntries[0];\n if (!entry || !entry.tooltipElement || entry.tooltipLeft === void 0 || entry.tooltipTop === void 0)\n return;\n return {\n x: entry.tooltipLeft,\n y: entry.tooltipTop,\n left: entry.tooltipLeft,\n top: entry.tooltipTop,\n width: entry.tooltipElement.offsetWidth,\n height: entry.tooltipElement.offsetHeight,\n bottom: entry.tooltipTop + entry.tooltipElement.offsetHeight,\n right: entry.tooltipLeft + entry.tooltipElement.offsetWidth,\n toJSON: () => {\n }\n };\n }\n // Note: there is a copy of this method in dialog.tsx. Please fix bugs in both places.\n tooltipPosition(box, tooltipElement) {\n const tooltipWidth = tooltipElement.offsetWidth;\n const tooltipHeight = tooltipElement.offsetHeight;\n const totalWidth = this._glassPaneElement.offsetWidth;\n const totalHeight = this._glassPaneElement.offsetHeight;\n let anchorLeft = Math.max(5, box.left);\n if (anchorLeft + tooltipWidth > totalWidth - 5)\n anchorLeft = totalWidth - tooltipWidth - 5;\n let anchorTop = Math.max(0, box.bottom) + 5;\n if (anchorTop + tooltipHeight > totalHeight - 5) {\n if (Math.max(0, box.top) > tooltipHeight + 5) {\n anchorTop = Math.max(0, box.top) - tooltipHeight - 5;\n } else {\n anchorTop = totalHeight - 5 - tooltipHeight;\n }\n }\n return { anchorLeft, anchorTop };\n }\n _highlightIsUpToDate(entries) {\n if (entries.length !== this._renderedEntries.length)\n return false;\n for (let i = 0; i < this._renderedEntries.length; ++i) {\n if (entries[i].element !== this._renderedEntries[i].targetElement)\n return false;\n if (entries[i].color !== this._renderedEntries[i].color)\n return false;\n if (entries[i].cssStyle !== this._renderedEntries[i].cssStyle)\n return false;\n const oldBox = this._renderedEntries[i].box;\n if (!oldBox)\n return false;\n const box = entries[i].box ? toDOMRect(entries[i].box) : entries[i].element.getBoundingClientRect();\n if (box.top !== oldBox.top || box.right !== oldBox.right || box.bottom !== oldBox.bottom || box.left !== oldBox.left)\n return false;\n }\n return true;\n }\n _createHighlightElement() {\n return this._injectedScript.document.createElement("x-pw-highlight");\n }\n appendChild(element) {\n this._glassPaneShadow.appendChild(element);\n }\n onGlassPaneClick(handler) {\n this._glassPaneElement.style.pointerEvents = "auto";\n this._glassPaneElement.style.backgroundColor = "rgba(0, 0, 0, 0.3)";\n this._glassPaneElement.addEventListener("click", handler);\n }\n offGlassPaneClick(handler) {\n this._glassPaneElement.style.pointerEvents = "none";\n this._glassPaneElement.style.backgroundColor = "transparent";\n this._glassPaneElement.removeEventListener("click", handler);\n }\n};\nfunction toDOMRect(box) {\n if (!box)\n return void 0;\n return new DOMRect(box.x, box.y, box.width, box.height);\n}\n\n// packages/injected/src/layoutSelectorUtils.ts\nfunction boxRightOf(box1, box2, maxDistance) {\n const distance = box1.left - box2.right;\n if (distance < 0 || maxDistance !== void 0 && distance > maxDistance)\n return;\n return distance + Math.max(box2.bottom - box1.bottom, 0) + Math.max(box1.top - box2.top, 0);\n}\nfunction boxLeftOf(box1, box2, maxDistance) {\n const distance = box2.left - box1.right;\n if (distance < 0 || maxDistance !== void 0 && distance > maxDistance)\n return;\n return distance + Math.max(box2.bottom - box1.bottom, 0) + Math.max(box1.top - box2.top, 0);\n}\nfunction boxAbove(box1, box2, maxDistance) {\n const distance = box2.top - box1.bottom;\n if (distance < 0 || maxDistance !== void 0 && distance > maxDistance)\n return;\n return distance + Math.max(box1.left - box2.left, 0) + Math.max(box2.right - box1.right, 0);\n}\nfunction boxBelow(box1, box2, maxDistance) {\n const distance = box1.top - box2.bottom;\n if (distance < 0 || maxDistance !== void 0 && distance > maxDistance)\n return;\n return distance + Math.max(box1.left - box2.left, 0) + Math.max(box2.right - box1.right, 0);\n}\nfunction boxNear(box1, box2, maxDistance) {\n const kThreshold = maxDistance === void 0 ? 50 : maxDistance;\n let score = 0;\n if (box1.left - box2.right >= 0)\n score += box1.left - box2.right;\n if (box2.left - box1.right >= 0)\n score += box2.left - box1.right;\n if (box2.top - box1.bottom >= 0)\n score += box2.top - box1.bottom;\n if (box1.top - box2.bottom >= 0)\n score += box1.top - box2.bottom;\n return score > kThreshold ? void 0 : score;\n}\nvar kLayoutSelectorNames = ["left-of", "right-of", "above", "below", "near"];\nfunction layoutSelectorScore(name, element, inner, maxDistance) {\n const box = element.getBoundingClientRect();\n const scorer = { "left-of": boxLeftOf, "right-of": boxRightOf, "above": boxAbove, "below": boxBelow, "near": boxNear }[name];\n let bestScore;\n for (const e of inner) {\n if (e === element)\n continue;\n const score = scorer(box, e.getBoundingClientRect(), maxDistance);\n if (score === void 0)\n continue;\n if (bestScore === void 0 || score < bestScore)\n bestScore = score;\n }\n return bestScore;\n}\n\n// packages/injected/src/selectorUtils.ts\nfunction matchesAttributePart(value, attr) {\n const objValue = typeof value === "string" && !attr.caseSensitive ? value.toUpperCase() : value;\n const attrValue = typeof attr.value === "string" && !attr.caseSensitive ? attr.value.toUpperCase() : attr.value;\n if (attr.op === "")\n return !!objValue;\n if (attr.op === "=") {\n if (attrValue instanceof RegExp)\n return typeof objValue === "string" && !!objValue.match(attrValue);\n return objValue === attrValue;\n }\n if (typeof objValue !== "string" || typeof attrValue !== "string")\n return false;\n if (attr.op === "*=")\n return objValue.includes(attrValue);\n if (attr.op === "^=")\n return objValue.startsWith(attrValue);\n if (attr.op === "$=")\n return objValue.endsWith(attrValue);\n if (attr.op === "|=")\n return objValue === attrValue || objValue.startsWith(attrValue + "-");\n if (attr.op === "~=")\n return objValue.split(" ").includes(attrValue);\n return false;\n}\nfunction shouldSkipForTextMatching(element) {\n const document = element.ownerDocument;\n return element.nodeName === "SCRIPT" || element.nodeName === "NOSCRIPT" || element.nodeName === "STYLE" || document.head && document.head.contains(element);\n}\nfunction elementText(cache, root) {\n let value = cache.get(root);\n if (value === void 0) {\n value = { full: "", normalized: "", immediate: [] };\n if (!shouldSkipForTextMatching(root)) {\n let currentImmediate = "";\n if (root instanceof HTMLInputElement && (root.type === "submit" || root.type === "button")) {\n value = { full: root.value, normalized: normalizeWhiteSpace(root.value), immediate: [root.value] };\n } else {\n for (let child = root.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === Node.TEXT_NODE) {\n value.full += child.nodeValue || "";\n currentImmediate += child.nodeValue || "";\n } else if (child.nodeType === Node.COMMENT_NODE) {\n continue;\n } else {\n if (currentImmediate)\n value.immediate.push(currentImmediate);\n currentImmediate = "";\n if (child.nodeType === Node.ELEMENT_NODE)\n value.full += elementText(cache, child).full;\n }\n }\n if (currentImmediate)\n value.immediate.push(currentImmediate);\n if (root.shadowRoot)\n value.full += elementText(cache, root.shadowRoot).full;\n if (value.full)\n value.normalized = normalizeWhiteSpace(value.full);\n }\n }\n cache.set(root, value);\n }\n return value;\n}\nfunction elementMatchesText(cache, element, matcher) {\n if (shouldSkipForTextMatching(element))\n return "none";\n if (!matcher(elementText(cache, element)))\n return "none";\n for (let child = element.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === Node.ELEMENT_NODE && matcher(elementText(cache, child)))\n return "selfAndChildren";\n }\n if (element.shadowRoot && matcher(elementText(cache, element.shadowRoot)))\n return "selfAndChildren";\n return "self";\n}\nfunction getElementLabels(textCache, element) {\n const labels = getAriaLabelledByElements(element);\n if (labels)\n return labels.map((label) => elementText(textCache, label));\n const ariaLabel = element.getAttribute("aria-label");\n if (ariaLabel !== null && !!ariaLabel.trim())\n return [{ full: ariaLabel, normalized: normalizeWhiteSpace(ariaLabel), immediate: [ariaLabel] }];\n const isNonHiddenInput = element.nodeName === "INPUT" && element.type !== "hidden";\n if (["BUTTON", "METER", "OUTPUT", "PROGRESS", "SELECT", "TEXTAREA"].includes(element.nodeName) || isNonHiddenInput) {\n const labels2 = element.labels;\n if (labels2)\n return [...labels2].map((label) => elementText(textCache, label));\n }\n return [];\n}\n\n// packages/injected/src/roleSelectorEngine.ts\nvar kSupportedAttributes = ["selected", "checked", "pressed", "expanded", "level", "disabled", "name", "description", "include-hidden"];\nkSupportedAttributes.sort();\nfunction validateSupportedRole(attr, roles, role) {\n if (!roles.includes(role))\n throw new Error(`"${attr}" attribute is only supported for roles: ${roles.slice().sort().map((role2) => `"${role2}"`).join(", ")}`);\n}\nfunction validateSupportedValues(attr, values) {\n if (attr.op !== "" && !values.includes(attr.value))\n throw new Error(`"${attr.name}" must be one of ${values.map((v) => JSON.stringify(v)).join(", ")}`);\n}\nfunction validateSupportedOp(attr, ops) {\n if (!ops.includes(attr.op))\n throw new Error(`"${attr.name}" does not support "${attr.op}" matcher`);\n}\nfunction validateAttributes(attrs, role) {\n const options = { role };\n for (const attr of attrs) {\n switch (attr.name) {\n case "checked": {\n validateSupportedRole(attr.name, kAriaCheckedRoles, role);\n validateSupportedValues(attr, [true, false, "mixed"]);\n validateSupportedOp(attr, ["", "="]);\n options.checked = attr.op === "" ? true : attr.value;\n break;\n }\n case "pressed": {\n validateSupportedRole(attr.name, kAriaPressedRoles, role);\n validateSupportedValues(attr, [true, false, "mixed"]);\n validateSupportedOp(attr, ["", "="]);\n options.pressed = attr.op === "" ? true : attr.value;\n break;\n }\n case "selected": {\n validateSupportedRole(attr.name, kAriaSelectedRoles, role);\n validateSupportedValues(attr, [true, false]);\n validateSupportedOp(attr, ["", "="]);\n options.selected = attr.op === "" ? true : attr.value;\n break;\n }\n case "expanded": {\n validateSupportedRole(attr.name, kAriaExpandedRoles, role);\n validateSupportedValues(attr, [true, false]);\n validateSupportedOp(attr, ["", "="]);\n options.expanded = attr.op === "" ? true : attr.value;\n break;\n }\n case "level": {\n validateSupportedRole(attr.name, kAriaLevelRoles, role);\n if (typeof attr.value === "string")\n attr.value = +attr.value;\n if (attr.op !== "=" || typeof attr.value !== "number" || Number.isNaN(attr.value))\n throw new Error(`"level" attribute must be compared to a number`);\n options.level = attr.value;\n break;\n }\n case "disabled": {\n validateSupportedValues(attr, [true, false]);\n validateSupportedOp(attr, ["", "="]);\n options.disabled = attr.op === "" ? true : attr.value;\n break;\n }\n case "name": {\n if (attr.op === "")\n throw new Error(`"name" attribute must have a value`);\n if (typeof attr.value !== "string" && !(attr.value instanceof RegExp))\n throw new Error(`"name" attribute must be a string or a regular expression`);\n options.name = attr.value;\n options.nameOp = attr.op;\n options.nameExact = attr.caseSensitive;\n break;\n }\n case "description": {\n if (attr.op === "")\n throw new Error(`"description" attribute must have a value`);\n if (typeof attr.value !== "string" && !(attr.value instanceof RegExp))\n throw new Error(`"description" attribute must be a string or a regular expression`);\n options.description = attr.value;\n options.descriptionOp = attr.op;\n options.descriptionExact = attr.caseSensitive;\n break;\n }\n case "include-hidden": {\n validateSupportedValues(attr, [true, false]);\n validateSupportedOp(attr, ["", "="]);\n options.includeHidden = attr.op === "" ? true : attr.value;\n break;\n }\n default: {\n throw new Error(`Unknown attribute "${attr.name}", must be one of ${kSupportedAttributes.map((a) => `"${a}"`).join(", ")}.`);\n }\n }\n }\n return options;\n}\nfunction queryRole(scope, options, internal) {\n const result = [];\n const match = (element) => {\n if (getAriaRole(element) !== options.role)\n return;\n if (options.selected !== void 0 && getAriaSelected(element) !== options.selected)\n return;\n if (options.checked !== void 0 && getAriaChecked(element) !== options.checked)\n return;\n if (options.pressed !== void 0 && getAriaPressed(element) !== options.pressed)\n return;\n if (options.expanded !== void 0 && getAriaExpanded(element) !== options.expanded)\n return;\n if (options.level !== void 0 && getAriaLevel(element) !== options.level)\n return;\n if (options.disabled !== void 0 && getAriaDisabled(element) !== options.disabled)\n return;\n if (!options.includeHidden) {\n const isHidden = isElementHiddenForAria(element);\n if (isHidden)\n return;\n }\n if (options.name !== void 0) {\n const accessibleName = normalizeWhiteSpace(getElementAccessibleName(element, !!options.includeHidden));\n if (typeof options.name === "string")\n options.name = normalizeWhiteSpace(options.name);\n if (internal && !options.nameExact && options.nameOp === "=")\n options.nameOp = "*=";\n if (!matchesAttributePart(accessibleName, { name: "", jsonPath: [], op: options.nameOp || "=", value: options.name, caseSensitive: !!options.nameExact }))\n return;\n }\n if (options.description !== void 0) {\n const accessibleDescription = normalizeWhiteSpace(getElementAccessibleDescription(element, !!options.includeHidden));\n if (typeof options.description === "string")\n options.description = normalizeWhiteSpace(options.description);\n if (internal && !options.descriptionExact && options.descriptionOp === "=")\n options.descriptionOp = "*=";\n if (!matchesAttributePart(accessibleDescription, { name: "", jsonPath: [], op: options.descriptionOp || "=", value: options.description, caseSensitive: !!options.descriptionExact }))\n return;\n }\n result.push(element);\n };\n const query = (root) => {\n const shadows = [];\n if (root.shadowRoot)\n shadows.push(root.shadowRoot);\n for (const element of root.querySelectorAll("*")) {\n match(element);\n if (element.shadowRoot)\n shadows.push(element.shadowRoot);\n }\n shadows.forEach(query);\n };\n query(scope);\n return result;\n}\nfunction createRoleEngine(internal) {\n return {\n queryAll: (scope, selector) => {\n const parsed = parseAttributeSelector(selector, true);\n const role = parsed.name.toLowerCase();\n if (!role)\n throw new Error(`Role must not be empty`);\n const options = validateAttributes(parsed.attributes, role);\n beginAriaCaches();\n try {\n return queryRole(scope, options, internal);\n } finally {\n endAriaCaches();\n }\n }\n };\n}\n\n// packages/injected/src/selectorEvaluator.ts\nvar SelectorEvaluatorImpl = class {\n constructor() {\n this._retainCacheCounter = 0;\n this._cacheText = /* @__PURE__ */ new Map();\n this._cacheQueryCSS = /* @__PURE__ */ new Map();\n this._cacheMatches = /* @__PURE__ */ new Map();\n this._cacheQuery = /* @__PURE__ */ new Map();\n this._cacheMatchesSimple = /* @__PURE__ */ new Map();\n this._cacheMatchesParents = /* @__PURE__ */ new Map();\n this._cacheCallMatches = /* @__PURE__ */ new Map();\n this._cacheCallQuery = /* @__PURE__ */ new Map();\n this._cacheQuerySimple = /* @__PURE__ */ new Map();\n this._engines = /* @__PURE__ */ new Map();\n this._engines.set("not", notEngine);\n this._engines.set("is", isEngine);\n this._engines.set("where", isEngine);\n this._engines.set("has", hasEngine);\n this._engines.set("scope", scopeEngine);\n this._engines.set("light", lightEngine);\n this._engines.set("visible", visibleEngine);\n this._engines.set("text", textEngine);\n this._engines.set("text-is", textIsEngine);\n this._engines.set("text-matches", textMatchesEngine);\n this._engines.set("has-text", hasTextEngine);\n this._engines.set("right-of", createLayoutEngine("right-of"));\n this._engines.set("left-of", createLayoutEngine("left-of"));\n this._engines.set("above", createLayoutEngine("above"));\n this._engines.set("below", createLayoutEngine("below"));\n this._engines.set("near", createLayoutEngine("near"));\n this._engines.set("nth-match", nthMatchEngine);\n const allNames = [...this._engines.keys()];\n allNames.sort();\n const parserNames = [...customCSSNames];\n parserNames.sort();\n if (allNames.join("|") !== parserNames.join("|"))\n throw new Error(`Please keep customCSSNames in sync with evaluator engines: ${allNames.join("|")} vs ${parserNames.join("|")}`);\n }\n begin() {\n ++this._retainCacheCounter;\n }\n end() {\n --this._retainCacheCounter;\n if (!this._retainCacheCounter) {\n this._cacheQueryCSS.clear();\n this._cacheMatches.clear();\n this._cacheQuery.clear();\n this._cacheMatchesSimple.clear();\n this._cacheMatchesParents.clear();\n this._cacheCallMatches.clear();\n this._cacheCallQuery.clear();\n this._cacheQuerySimple.clear();\n this._cacheText.clear();\n }\n }\n _cached(cache, main, rest, cb) {\n if (!cache.has(main))\n cache.set(main, []);\n const entries = cache.get(main);\n const entry = entries.find((e) => rest.every((value, index) => e.rest[index] === value));\n if (entry)\n return entry.result;\n const result = cb();\n entries.push({ rest, result });\n return result;\n }\n _checkSelector(s) {\n const wellFormed = typeof s === "object" && s && (Array.isArray(s) || "simples" in s && s.simples.length);\n if (!wellFormed)\n throw new Error(`Malformed selector "${s}"`);\n return s;\n }\n matches(element, s, context) {\n const selector = this._checkSelector(s);\n this.begin();\n try {\n return this._cached(this._cacheMatches, element, [selector, context.scope, context.pierceShadow, context.originalScope], () => {\n if (Array.isArray(selector))\n return this._matchesEngine(isEngine, element, selector, context);\n if (this._hasScopeClause(selector))\n context = this._expandContextForScopeMatching(context);\n if (!this._matchesSimple(element, selector.simples[selector.simples.length - 1].selector, context))\n return false;\n return this._matchesParents(element, selector, selector.simples.length - 2, context);\n });\n } finally {\n this.end();\n }\n }\n query(context, s) {\n const selector = this._checkSelector(s);\n this.begin();\n try {\n return this._cached(this._cacheQuery, selector, [context.scope, context.pierceShadow, context.originalScope], () => {\n if (Array.isArray(selector))\n return this._queryEngine(isEngine, context, selector);\n if (this._hasScopeClause(selector))\n context = this._expandContextForScopeMatching(context);\n const previousScoreMap = this._scoreMap;\n this._scoreMap = /* @__PURE__ */ new Map();\n let elements = this._querySimple(context, selector.simples[selector.simples.length - 1].selector);\n elements = elements.filter((element) => this._matchesParents(element, selector, selector.simples.length - 2, context));\n if (this._scoreMap.size) {\n elements.sort((a, b) => {\n const aScore = this._scoreMap.get(a);\n const bScore = this._scoreMap.get(b);\n if (aScore === bScore)\n return 0;\n if (aScore === void 0)\n return 1;\n if (bScore === void 0)\n return -1;\n return aScore - bScore;\n });\n }\n this._scoreMap = previousScoreMap;\n return elements;\n });\n } finally {\n this.end();\n }\n }\n _markScore(element, score) {\n if (this._scoreMap)\n this._scoreMap.set(element, score);\n }\n _hasScopeClause(selector) {\n return selector.simples.some((simple) => simple.selector.functions.some((f) => f.name === "scope"));\n }\n _expandContextForScopeMatching(context) {\n if (context.scope.nodeType !== 1)\n return context;\n const scope = parentElementOrShadowHost(context.scope);\n if (!scope)\n return context;\n return { ...context, scope, originalScope: context.originalScope || context.scope };\n }\n _matchesSimple(element, simple, context) {\n return this._cached(this._cacheMatchesSimple, element, [simple, context.scope, context.pierceShadow, context.originalScope], () => {\n if (element === context.scope)\n return false;\n if (simple.css && !this._matchesCSS(element, simple.css))\n return false;\n for (const func of simple.functions) {\n if (!this._matchesEngine(this._getEngine(func.name), element, func.args, context))\n return false;\n }\n return true;\n });\n }\n _querySimple(context, simple) {\n if (!simple.functions.length)\n return this._queryCSS(context, simple.css || "*");\n return this._cached(this._cacheQuerySimple, simple, [context.scope, context.pierceShadow, context.originalScope], () => {\n let css = simple.css;\n const funcs = simple.functions;\n if (css === "*" && funcs.length)\n css = void 0;\n let elements;\n let firstIndex = -1;\n if (css !== void 0) {\n elements = this._queryCSS(context, css);\n } else {\n firstIndex = funcs.findIndex((func) => this._getEngine(func.name).query !== void 0);\n if (firstIndex === -1)\n firstIndex = 0;\n elements = this._queryEngine(this._getEngine(funcs[firstIndex].name), context, funcs[firstIndex].args);\n }\n for (let i = 0; i < funcs.length; i++) {\n if (i === firstIndex)\n continue;\n const engine = this._getEngine(funcs[i].name);\n if (engine.matches !== void 0)\n elements = elements.filter((e) => this._matchesEngine(engine, e, funcs[i].args, context));\n }\n for (let i = 0; i < funcs.length; i++) {\n if (i === firstIndex)\n continue;\n const engine = this._getEngine(funcs[i].name);\n if (engine.matches === void 0)\n elements = elements.filter((e) => this._matchesEngine(engine, e, funcs[i].args, context));\n }\n return elements;\n });\n }\n _matchesParents(element, complex, index, context) {\n if (index < 0)\n return true;\n return this._cached(this._cacheMatchesParents, element, [complex, index, context.scope, context.pierceShadow, context.originalScope], () => {\n const { selector: simple, combinator } = complex.simples[index];\n if (combinator === ">") {\n const parent = parentElementOrShadowHostInContext(element, context);\n if (!parent || !this._matchesSimple(parent, simple, context))\n return false;\n return this._matchesParents(parent, complex, index - 1, context);\n }\n if (combinator === "+") {\n const previousSibling = previousSiblingInContext(element, context);\n if (!previousSibling || !this._matchesSimple(previousSibling, simple, context))\n return false;\n return this._matchesParents(previousSibling, complex, index - 1, context);\n }\n if (combinator === "") {\n let parent = parentElementOrShadowHostInContext(element, context);\n while (parent) {\n if (this._matchesSimple(parent, simple, context)) {\n if (this._matchesParents(parent, complex, index - 1, context))\n return true;\n if (complex.simples[index - 1].combinator === "")\n break;\n }\n parent = parentElementOrShadowHostInContext(parent, context);\n }\n return false;\n }\n if (combinator === "~") {\n let previousSibling = previousSiblingInContext(element, context);\n while (previousSibling) {\n if (this._matchesSimple(previousSibling, simple, context)) {\n if (this._matchesParents(previousSibling, complex, index - 1, context))\n return true;\n if (complex.simples[index - 1].combinator === "~")\n break;\n }\n previousSibling = previousSiblingInContext(previousSibling, context);\n }\n return false;\n }\n if (combinator === ">=") {\n let parent = element;\n while (parent) {\n if (this._matchesSimple(parent, simple, context)) {\n if (this._matchesParents(parent, complex, index - 1, context))\n return true;\n if (complex.simples[index - 1].combinator === "")\n break;\n }\n parent = parentElementOrShadowHostInContext(parent, context);\n }\n return false;\n }\n throw new Error(`Unsupported combinator "${combinator}"`);\n });\n }\n _matchesEngine(engine, element, args, context) {\n if (engine.matches)\n return this._callMatches(engine, element, args, context);\n if (engine.query)\n return this._callQuery(engine, args, context).includes(element);\n throw new Error(`Selector engine should implement "matches" or "query"`);\n }\n _queryEngine(engine, context, args) {\n if (engine.query)\n return this._callQuery(engine, args, context);\n if (engine.matches)\n return this._queryCSS(context, "*").filter((element) => this._callMatches(engine, element, args, context));\n throw new Error(`Selector engine should implement "matches" or "query"`);\n }\n _callMatches(engine, element, args, context) {\n return this._cached(this._cacheCallMatches, element, [engine, context.scope, context.pierceShadow, context.originalScope, ...args], () => {\n return engine.matches(element, args, context, this);\n });\n }\n _callQuery(engine, args, context) {\n return this._cached(this._cacheCallQuery, engine, [context.scope, context.pierceShadow, context.originalScope, ...args], () => {\n return engine.query(context, args, this);\n });\n }\n _matchesCSS(element, css) {\n return element.matches(css);\n }\n _queryCSS(context, css) {\n return this._cached(this._cacheQueryCSS, css, [context.scope, context.pierceShadow, context.originalScope], () => {\n let result = [];\n function query(root) {\n result = result.concat([...root.querySelectorAll(css)]);\n if (!context.pierceShadow)\n return;\n if (root.shadowRoot)\n query(root.shadowRoot);\n for (const element of root.querySelectorAll("*")) {\n if (element.shadowRoot)\n query(element.shadowRoot);\n }\n }\n query(context.scope);\n return result;\n });\n }\n _getEngine(name) {\n const engine = this._engines.get(name);\n if (!engine)\n throw new Error(`Unknown selector engine "${name}"`);\n return engine;\n }\n};\nvar isEngine = {\n matches(element, args, context, evaluator) {\n if (args.length === 0)\n throw new Error(`"is" engine expects non-empty selector list`);\n return args.some((selector) => evaluator.matches(element, selector, context));\n },\n query(context, args, evaluator) {\n if (args.length === 0)\n throw new Error(`"is" engine expects non-empty selector list`);\n let elements = [];\n for (const arg of args)\n elements = elements.concat(evaluator.query(context, arg));\n return args.length === 1 ? elements : sortInDOMOrder(elements);\n }\n};\nvar hasEngine = {\n matches(element, args, context, evaluator) {\n if (args.length === 0)\n throw new Error(`"has" engine expects non-empty selector list`);\n return evaluator.query({ ...context, scope: element }, args).length > 0;\n }\n // TODO: we can implement efficient "query" by matching "args" and returning\n // all parents/descendants, just have to be careful with the ":scope" matching.\n};\nvar scopeEngine = {\n matches(element, args, context, evaluator) {\n if (args.length !== 0)\n throw new Error(`"scope" engine expects no arguments`);\n const actualScope = context.originalScope || context.scope;\n if (actualScope.nodeType === 9)\n return element === actualScope.documentElement;\n return element === actualScope;\n },\n query(context, args, evaluator) {\n if (args.length !== 0)\n throw new Error(`"scope" engine expects no arguments`);\n const actualScope = context.originalScope || context.scope;\n if (actualScope.nodeType === 9) {\n const root = actualScope.documentElement;\n return root ? [root] : [];\n }\n if (actualScope.nodeType === 1)\n return [actualScope];\n return [];\n }\n};\nvar notEngine = {\n matches(element, args, context, evaluator) {\n if (args.length === 0)\n throw new Error(`"not" engine expects non-empty selector list`);\n return !evaluator.matches(element, args, context);\n }\n};\nvar lightEngine = {\n query(context, args, evaluator) {\n return evaluator.query({ ...context, pierceShadow: false }, args);\n },\n matches(element, args, context, evaluator) {\n return evaluator.matches(element, args, { ...context, pierceShadow: false });\n }\n};\nvar visibleEngine = {\n matches(element, args, context, evaluator) {\n if (args.length)\n throw new Error(`"visible" engine expects no arguments`);\n return isElementVisible(element);\n }\n};\nvar textEngine = {\n matches(element, args, context, evaluator) {\n if (args.length !== 1 || typeof args[0] !== "string")\n throw new Error(`"text" engine expects a single string`);\n const text = normalizeWhiteSpace(args[0]).toLowerCase();\n const matcher = (elementText2) => elementText2.normalized.toLowerCase().includes(text);\n return elementMatchesText(evaluator._cacheText, element, matcher) === "self";\n }\n};\nvar textIsEngine = {\n matches(element, args, context, evaluator) {\n if (args.length !== 1 || typeof args[0] !== "string")\n throw new Error(`"text-is" engine expects a single string`);\n const text = normalizeWhiteSpace(args[0]);\n const matcher = (elementText2) => {\n if (!text && !elementText2.immediate.length)\n return true;\n return elementText2.immediate.some((s) => normalizeWhiteSpace(s) === text);\n };\n return elementMatchesText(evaluator._cacheText, element, matcher) !== "none";\n }\n};\nvar textMatchesEngine = {\n matches(element, args, context, evaluator) {\n if (args.length === 0 || typeof args[0] !== "string" || args.length > 2 || args.length === 2 && typeof args[1] !== "string")\n throw new Error(`"text-matches" engine expects a regexp body and optional regexp flags`);\n const re = new RegExp(args[0], args.length === 2 ? args[1] : void 0);\n const matcher = (elementText2) => re.test(elementText2.full);\n return elementMatchesText(evaluator._cacheText, element, matcher) === "self";\n }\n};\nvar hasTextEngine = {\n matches(element, args, context, evaluator) {\n if (args.length !== 1 || typeof args[0] !== "string")\n throw new Error(`"has-text" engine expects a single string`);\n if (shouldSkipForTextMatching(element))\n return false;\n const text = normalizeWhiteSpace(args[0]).toLowerCase();\n const matcher = (elementText2) => elementText2.normalized.toLowerCase().includes(text);\n return matcher(elementText(evaluator._cacheText, element));\n }\n};\nfunction createLayoutEngine(name) {\n return {\n matches(element, args, context, evaluator) {\n const maxDistance = args.length && typeof args[args.length - 1] === "number" ? args[args.length - 1] : void 0;\n const queryArgs = maxDistance === void 0 ? args : args.slice(0, args.length - 1);\n if (args.length < 1 + (maxDistance === void 0 ? 0 : 1))\n throw new Error(`"${name}" engine expects a selector list and optional maximum distance in pixels`);\n const inner = evaluator.query(context, queryArgs);\n const score = layoutSelectorScore(name, element, inner, maxDistance);\n if (score === void 0)\n return false;\n evaluator._markScore(element, score);\n return true;\n }\n };\n}\nvar nthMatchEngine = {\n query(context, args, evaluator) {\n let index = args[args.length - 1];\n if (args.length < 2)\n throw new Error(`"nth-match" engine expects non-empty selector list and an index argument`);\n if (typeof index !== "number" || index < 1)\n throw new Error(`"nth-match" engine expects a one-based index as the last argument`);\n const elements = isEngine.query(context, args.slice(0, args.length - 1), evaluator);\n index--;\n return index < elements.length ? [elements[index]] : [];\n }\n};\nfunction parentElementOrShadowHostInContext(element, context) {\n if (element === context.scope)\n return;\n if (!context.pierceShadow)\n return element.parentElement || void 0;\n return parentElementOrShadowHost(element);\n}\nfunction previousSiblingInContext(element, context) {\n if (element === context.scope)\n return;\n return element.previousElementSibling || void 0;\n}\nfunction sortInDOMOrder(elements) {\n const elementToEntry = /* @__PURE__ */ new Map();\n const roots = [];\n const result = [];\n function append(element) {\n let entry = elementToEntry.get(element);\n if (entry)\n return entry;\n const parent = parentElementOrShadowHost(element);\n if (parent) {\n const parentEntry = append(parent);\n parentEntry.children.push(element);\n } else {\n roots.push(element);\n }\n entry = { children: [], taken: false };\n elementToEntry.set(element, entry);\n return entry;\n }\n for (const e of elements)\n append(e).taken = true;\n function visit(element) {\n const entry = elementToEntry.get(element);\n if (entry.taken)\n result.push(element);\n if (entry.children.length > 1) {\n const set = new Set(entry.children);\n entry.children = [];\n let child = element.firstElementChild;\n while (child && entry.children.length < set.size) {\n if (set.has(child))\n entry.children.push(child);\n child = child.nextElementSibling;\n }\n child = element.shadowRoot ? element.shadowRoot.firstElementChild : null;\n while (child && entry.children.length < set.size) {\n if (set.has(child))\n entry.children.push(child);\n child = child.nextElementSibling;\n }\n }\n entry.children.forEach(visit);\n }\n roots.forEach(visit);\n return result;\n}\n\n// packages/injected/src/selectorGenerator.ts\nvar kTextScoreRange = 10;\nvar kExactPenalty = kTextScoreRange / 2;\nvar kTestIdScore = 1;\nvar kOtherTestIdScore = 2;\nvar kIframeByAttributeScore = 10;\nvar kBeginPenalizedScore = 50;\nvar kRoleWithNameScore = 100;\nvar kPlaceholderScore = 120;\nvar kLabelScore = 140;\nvar kAltTextScore = 160;\nvar kTextScore = 180;\nvar kTitleScore = 200;\nvar kTextScoreRegex = 250;\nvar kPlaceholderScoreExact = kPlaceholderScore + kExactPenalty;\nvar kLabelScoreExact = kLabelScore + kExactPenalty;\nvar kRoleWithNameScoreExact = kRoleWithNameScore + kExactPenalty;\nvar kAltTextScoreExact = kAltTextScore + kExactPenalty;\nvar kTextScoreExact = kTextScore + kExactPenalty;\nvar kTitleScoreExact = kTitleScore + kExactPenalty;\nvar kEndPenalizedScore = 300;\nvar kCSSIdScore = 500;\nvar kRoleWithoutNameScore = 510;\nvar kCSSInputTypeNameScore = 520;\nvar kCSSTagNameScore = 530;\nvar kNthScore = 1e4;\nvar kCSSFallbackScore = 1e7;\nvar kScoreThresholdForTextExpect = 1e3;\nfunction generateSelector(injectedScript, targetElement, options) {\n var _a;\n injectedScript._evaluator.begin();\n const cache = { allowText: /* @__PURE__ */ new Map(), disallowText: /* @__PURE__ */ new Map() };\n beginAriaCaches();\n beginDOMCaches();\n try {\n let selectors = [];\n if (options.forTextExpect) {\n let targetTokens = cssFallback(injectedScript, targetElement.ownerDocument.documentElement, options);\n for (let element = targetElement; element; element = parentElementOrShadowHost(element)) {\n const tokens = generateSelectorFor(cache, injectedScript, element, { ...options, noText: true });\n if (!tokens)\n continue;\n const score = combineScores(tokens);\n if (score <= kScoreThresholdForTextExpect) {\n targetTokens = tokens;\n break;\n }\n }\n selectors = [joinTokens(targetTokens)];\n } else {\n if (!targetElement.matches("input,textarea,select") && !targetElement.isContentEditable) {\n const interactiveParent = closestCrossShadow(targetElement, "button,select,input,[role=button],[role=checkbox],[role=radio],a,[role=link]", options.root);\n if (interactiveParent && isElementVisible(interactiveParent))\n targetElement = interactiveParent;\n }\n if (options.multiple) {\n const withText = generateSelectorFor(cache, injectedScript, targetElement, options);\n const withoutText = generateSelectorFor(cache, injectedScript, targetElement, { ...options, noText: true });\n let tokens = [withText, withoutText];\n cache.allowText.clear();\n cache.disallowText.clear();\n if (withText && hasCSSIdToken(withText))\n tokens.push(generateSelectorFor(cache, injectedScript, targetElement, { ...options, noCSSId: true }));\n if (withoutText && hasCSSIdToken(withoutText))\n tokens.push(generateSelectorFor(cache, injectedScript, targetElement, { ...options, noText: true, noCSSId: true }));\n tokens = tokens.filter(Boolean);\n if (!tokens.length) {\n const css = cssFallback(injectedScript, targetElement, options);\n tokens.push(css);\n if (hasCSSIdToken(css))\n tokens.push(cssFallback(injectedScript, targetElement, { ...options, noCSSId: true }));\n }\n selectors = [...new Set(tokens.map((t) => joinTokens(t)))];\n } else {\n const targetTokens = generateSelectorFor(cache, injectedScript, targetElement, options) || cssFallback(injectedScript, targetElement, options);\n selectors = [joinTokens(targetTokens)];\n }\n }\n const selector = selectors[0];\n const parsedSelector = injectedScript.parseSelector(selector);\n return {\n selector,\n selectors,\n elements: injectedScript.querySelectorAll(parsedSelector, (_a = options.root) != null ? _a : targetElement.ownerDocument)\n };\n } finally {\n endDOMCaches();\n endAriaCaches();\n injectedScript._evaluator.end();\n }\n}\nfunction generateSelectorFor(cache, injectedScript, targetElement, options) {\n var _a;\n if (options.root && !isInsideScope(options.root, targetElement))\n throw new Error(`Target element must belong to the root\'s subtree`);\n if (targetElement === options.root)\n return [{ engine: "css", selector: ":scope", score: 1 }];\n if (targetElement.ownerDocument.documentElement === targetElement)\n return [{ engine: "css", selector: "html", score: 1 }];\n let result = null;\n const updateResult = (candidate) => {\n if (!result || combineScores(candidate) < combineScores(result))\n result = candidate;\n };\n const candidates = [];\n if (!options.noText) {\n for (const candidate of buildTextCandidates(injectedScript, targetElement, !options.isRecursive))\n candidates.push({ candidate, isTextCandidate: true });\n }\n for (const token of buildNoTextCandidates(injectedScript, targetElement, options)) {\n if (options.omitInternalEngines && token.engine.startsWith("internal:"))\n continue;\n candidates.push({ candidate: [token], isTextCandidate: false });\n }\n candidates.sort((a, b) => combineScores(a.candidate) - combineScores(b.candidate));\n for (const { candidate, isTextCandidate } of candidates) {\n const elements = injectedScript.querySelectorAll(injectedScript.parseSelector(joinTokens(candidate)), (_a = options.root) != null ? _a : targetElement.ownerDocument);\n if (!elements.includes(targetElement)) {\n continue;\n }\n if (elements.length === 1) {\n updateResult(candidate);\n break;\n }\n const index = elements.indexOf(targetElement);\n if (index > 5) {\n continue;\n }\n updateResult([...candidate, { engine: "nth", selector: String(index), score: kNthScore }]);\n if (options.isRecursive) {\n continue;\n }\n for (let parent = parentElementOrShadowHost(targetElement); parent && parent !== options.root; parent = parentElementOrShadowHost(parent)) {\n const filtered = elements.filter((e) => isInsideScope(parent, e) && e !== parent);\n const newIndex = filtered.indexOf(targetElement);\n if (filtered.length > 5 || newIndex === -1 || newIndex === index && filtered.length > 1) {\n continue;\n }\n const inParent = filtered.length === 1 ? candidate : [...candidate, { engine: "nth", selector: String(newIndex), score: kNthScore }];\n const idealSelectorForParent = { engine: "", selector: "", score: 1 };\n if (result && combineScores([idealSelectorForParent, ...inParent]) >= combineScores(result)) {\n continue;\n }\n const noText = !!options.noText || isTextCandidate;\n const cacheMap = noText ? cache.disallowText : cache.allowText;\n let parentTokens = cacheMap.get(parent);\n if (parentTokens === void 0) {\n parentTokens = generateSelectorFor(cache, injectedScript, parent, { ...options, isRecursive: true, noText }) || cssFallback(injectedScript, parent, options);\n cacheMap.set(parent, parentTokens);\n }\n if (!parentTokens)\n continue;\n updateResult([...parentTokens, ...inParent]);\n }\n }\n return result;\n}\nfunction buildNoTextCandidates(injectedScript, element, options) {\n const candidates = [];\n const testIdAttributeNames = splitTestIdAttributeNames(options.testIdAttributeName);\n {\n for (const attr of ["data-testid", "data-test-id", "data-test"]) {\n if (!testIdAttributeNames.includes(attr) && element.getAttribute(attr))\n candidates.push({ engine: "css", selector: `[${attr}=${quoteCSSAttributeValue(element.getAttribute(attr))}]`, score: kOtherTestIdScore });\n }\n if (!options.noCSSId) {\n const idAttr = element.getAttribute("id");\n if (idAttr && !isGuidLike(idAttr))\n candidates.push({ engine: "css", selector: makeSelectorForId(idAttr), score: kCSSIdScore });\n }\n candidates.push({ engine: "css", selector: escapeNodeName(element), score: kCSSTagNameScore });\n }\n if (element.nodeName === "IFRAME") {\n for (const attribute of ["name", "title"]) {\n if (element.getAttribute(attribute))\n candidates.push({ engine: "css", selector: `${escapeNodeName(element)}[${attribute}=${quoteCSSAttributeValue(element.getAttribute(attribute))}]`, score: kIframeByAttributeScore });\n }\n for (const testIdAttr of testIdAttributeNames) {\n if (element.getAttribute(testIdAttr))\n candidates.push({ engine: "css", selector: `[${testIdAttr}=${quoteCSSAttributeValue(element.getAttribute(testIdAttr))}]`, score: kTestIdScore });\n }\n penalizeScoreForLength([candidates]);\n return candidates;\n }\n for (const testIdAttr of testIdAttributeNames) {\n if (element.getAttribute(testIdAttr))\n candidates.push({ engine: "internal:testid", selector: `[${testIdAttr}=${escapeForAttributeSelector(element.getAttribute(testIdAttr), true)}]`, score: kTestIdScore });\n }\n if (element.nodeName === "INPUT" || element.nodeName === "TEXTAREA") {\n const input = element;\n if (input.placeholder) {\n candidates.push({ engine: "internal:attr", selector: `[placeholder=${escapeForAttributeSelector(input.placeholder, true)}]`, score: kPlaceholderScoreExact });\n for (const alternative of suitableTextAlternatives(input.placeholder))\n candidates.push({ engine: "internal:attr", selector: `[placeholder=${escapeForAttributeSelector(alternative.text, false)}]`, score: kPlaceholderScore - alternative.scoreBonus });\n }\n }\n const labels = getElementLabels(injectedScript._evaluator._cacheText, element);\n for (const label of labels) {\n const labelText = label.normalized;\n candidates.push({ engine: "internal:label", selector: escapeForTextSelector(labelText, true), score: kLabelScoreExact });\n for (const alternative of suitableTextAlternatives(labelText))\n candidates.push({ engine: "internal:label", selector: escapeForTextSelector(alternative.text, false), score: kLabelScore - alternative.scoreBonus });\n }\n const ariaRole = getAriaRole(element);\n if (ariaRole && !["none", "presentation"].includes(ariaRole))\n candidates.push({ engine: "internal:role", selector: ariaRole, score: kRoleWithoutNameScore });\n if (element.getAttribute("name") && ["BUTTON", "FORM", "FIELDSET", "FRAME", "IFRAME", "INPUT", "KEYGEN", "OBJECT", "OUTPUT", "SELECT", "TEXTAREA", "MAP", "META", "PARAM"].includes(element.nodeName))\n candidates.push({ engine: "css", selector: `${escapeNodeName(element)}[name=${quoteCSSAttributeValue(element.getAttribute("name"))}]`, score: kCSSInputTypeNameScore });\n if (["INPUT", "TEXTAREA"].includes(element.nodeName) && element.getAttribute("type") !== "hidden") {\n if (element.getAttribute("type"))\n candidates.push({ engine: "css", selector: `${escapeNodeName(element)}[type=${quoteCSSAttributeValue(element.getAttribute("type"))}]`, score: kCSSInputTypeNameScore });\n }\n if (["INPUT", "TEXTAREA", "SELECT"].includes(element.nodeName) && element.getAttribute("type") !== "hidden")\n candidates.push({ engine: "css", selector: escapeNodeName(element), score: kCSSInputTypeNameScore + 1 });\n penalizeScoreForLength([candidates]);\n return candidates;\n}\nfunction buildTextCandidates(injectedScript, element, isTargetNode) {\n if (element.nodeName === "SELECT")\n return [];\n const candidates = [];\n const title = element.getAttribute("title");\n if (title) {\n candidates.push([{ engine: "internal:attr", selector: `[title=${escapeForAttributeSelector(title, true)}]`, score: kTitleScoreExact }]);\n for (const alternative of suitableTextAlternatives(title))\n candidates.push([{ engine: "internal:attr", selector: `[title=${escapeForAttributeSelector(alternative.text, false)}]`, score: kTitleScore - alternative.scoreBonus }]);\n }\n const alt = element.getAttribute("alt");\n if (alt && ["APPLET", "AREA", "IMG", "INPUT"].includes(element.nodeName)) {\n candidates.push([{ engine: "internal:attr", selector: `[alt=${escapeForAttributeSelector(alt, true)}]`, score: kAltTextScoreExact }]);\n for (const alternative of suitableTextAlternatives(alt))\n candidates.push([{ engine: "internal:attr", selector: `[alt=${escapeForAttributeSelector(alternative.text, false)}]`, score: kAltTextScore - alternative.scoreBonus }]);\n }\n const text = elementText(injectedScript._evaluator._cacheText, element).normalized;\n const textAlternatives = text ? suitableTextAlternatives(text) : [];\n if (text) {\n if (isTargetNode) {\n if (text.length <= 80)\n candidates.push([{ engine: "internal:text", selector: escapeForTextSelector(text, true), score: kTextScoreExact }]);\n for (const alternative of textAlternatives)\n candidates.push([{ engine: "internal:text", selector: escapeForTextSelector(alternative.text, false), score: kTextScore - alternative.scoreBonus }]);\n }\n const cssToken = { engine: "css", selector: escapeNodeName(element), score: kCSSTagNameScore };\n for (const alternative of textAlternatives)\n candidates.push([cssToken, { engine: "internal:has-text", selector: escapeForTextSelector(alternative.text, false), score: kTextScore - alternative.scoreBonus }]);\n if (isTargetNode && text.length <= 80) {\n const re = new RegExp("^" + escapeRegExp(text) + "$");\n candidates.push([cssToken, { engine: "internal:has-text", selector: escapeForTextSelector(re, false), score: kTextScoreRegex }]);\n }\n }\n const ariaRole = getAriaRole(element);\n if (ariaRole && !["none", "presentation"].includes(ariaRole)) {\n const ariaName = getElementAccessibleName(element, false);\n if (ariaName && !ariaName.match(/^\\p{Co}+$/u)) {\n const roleToken = { engine: "internal:role", selector: `${ariaRole}[name=${escapeForAttributeSelector(ariaName, true)}]`, score: kRoleWithNameScoreExact };\n candidates.push([roleToken]);\n for (const alternative of suitableTextAlternatives(ariaName))\n candidates.push([{ engine: "internal:role", selector: `${ariaRole}[name=${escapeForAttributeSelector(alternative.text, false)}]`, score: kRoleWithNameScore - alternative.scoreBonus }]);\n const ariaDescription = getElementAccessibleDescription(element, false);\n if (ariaDescription) {\n candidates.push([{ engine: "internal:role", selector: `${ariaRole}[name=${escapeForAttributeSelector(ariaName, true)}][description=${escapeForAttributeSelector(ariaDescription, true)}]`, score: kRoleWithNameScoreExact + 1 }]);\n for (const alternative of suitableTextAlternatives(ariaName))\n candidates.push([{ engine: "internal:role", selector: `${ariaRole}[name=${escapeForAttributeSelector(alternative.text, false)}][description=${escapeForAttributeSelector(ariaDescription, false)}]`, score: kRoleWithNameScore - alternative.scoreBonus + 1 }]);\n }\n } else {\n const roleToken = { engine: "internal:role", selector: `${ariaRole}`, score: kRoleWithoutNameScore };\n const ariaDescription = getElementAccessibleDescription(element, false);\n if (ariaDescription)\n candidates.push([{ engine: "internal:role", selector: `${ariaRole}[description=${escapeForAttributeSelector(ariaDescription, true)}]`, score: kRoleWithoutNameScore + 1 }]);\n for (const alternative of textAlternatives)\n candidates.push([roleToken, { engine: "internal:has-text", selector: escapeForTextSelector(alternative.text, false), score: kTextScore - alternative.scoreBonus }]);\n if (isTargetNode && text.length <= 80) {\n const re = new RegExp("^" + escapeRegExp(text) + "$");\n candidates.push([roleToken, { engine: "internal:has-text", selector: escapeForTextSelector(re, false), score: kTextScoreRegex }]);\n }\n }\n }\n penalizeScoreForLength(candidates);\n return candidates;\n}\nfunction makeSelectorForId(id) {\n return /^[a-zA-Z][a-zA-Z0-9\\-\\_]+$/.test(id) ? "#" + id : `[id=${quoteCSSAttributeValue(id)}]`;\n}\nfunction hasCSSIdToken(tokens) {\n return tokens.some((token) => token.engine === "css" && (token.selector.startsWith("#") || token.selector.startsWith(\'[id="\')));\n}\nfunction cssFallback(injectedScript, targetElement, options) {\n var _a;\n const root = (_a = options.root) != null ? _a : targetElement.ownerDocument;\n const tokens = [];\n function uniqueCSSSelector(prefix) {\n const path = tokens.slice();\n if (prefix)\n path.unshift(prefix);\n const selector = path.join(" > ");\n const parsedSelector = injectedScript.parseSelector(selector);\n const node = injectedScript.querySelector(parsedSelector, root, false);\n return node === targetElement ? selector : void 0;\n }\n function makeStrict(selector) {\n const token = { engine: "css", selector, score: kCSSFallbackScore };\n const parsedSelector = injectedScript.parseSelector(selector);\n const elements = injectedScript.querySelectorAll(parsedSelector, root);\n if (elements.length === 1)\n return [token];\n const nth = { engine: "nth", selector: String(elements.indexOf(targetElement)), score: kNthScore };\n return [token, nth];\n }\n for (let element = targetElement; element && element !== root; element = parentElementOrShadowHost(element)) {\n let bestTokenForLevel = "";\n if (element.id && !options.noCSSId) {\n const token = makeSelectorForId(element.id);\n const selector = uniqueCSSSelector(token);\n if (selector)\n return makeStrict(selector);\n bestTokenForLevel = token;\n }\n const parent = element.parentNode;\n const classes = [...element.classList].map(escapeClassName);\n for (let i = 0; i < classes.length; ++i) {\n const token = "." + classes.slice(0, i + 1).join(".");\n const selector = uniqueCSSSelector(token);\n if (selector)\n return makeStrict(selector);\n if (!bestTokenForLevel && parent) {\n const sameClassSiblings = parent.querySelectorAll(token);\n if (sameClassSiblings.length === 1)\n bestTokenForLevel = token;\n }\n }\n if (parent) {\n const siblings = [...parent.children];\n const nodeName = element.nodeName;\n const sameTagSiblings = siblings.filter((sibling) => sibling.nodeName === nodeName);\n const token = sameTagSiblings.indexOf(element) === 0 ? escapeNodeName(element) : `${escapeNodeName(element)}:nth-child(${1 + siblings.indexOf(element)})`;\n const selector = uniqueCSSSelector(token);\n if (selector)\n return makeStrict(selector);\n if (!bestTokenForLevel)\n bestTokenForLevel = token;\n } else if (!bestTokenForLevel) {\n bestTokenForLevel = escapeNodeName(element);\n }\n tokens.unshift(bestTokenForLevel);\n }\n return makeStrict(uniqueCSSSelector());\n}\nfunction penalizeScoreForLength(groups) {\n for (const group of groups) {\n for (const token of group) {\n if (token.score > kBeginPenalizedScore && token.score < kEndPenalizedScore)\n token.score += Math.min(kTextScoreRange, token.selector.length / 10 | 0);\n }\n }\n}\nfunction joinTokens(tokens) {\n const parts = [];\n let lastEngine = "";\n for (const { engine, selector } of tokens) {\n if (parts.length && (lastEngine !== "css" || engine !== "css" || selector.startsWith(":nth-match(")))\n parts.push(">>");\n lastEngine = engine;\n if (engine === "css")\n parts.push(selector);\n else\n parts.push(`${engine}=${selector}`);\n }\n return parts.join(" ");\n}\nfunction combineScores(tokens) {\n let score = 0;\n for (let i = 0; i < tokens.length; i++)\n score += tokens[i].score * (tokens.length - i);\n return score;\n}\nfunction isGuidLike(id) {\n let lastCharacterType;\n let transitionCount = 0;\n for (let i = 0; i < id.length; ++i) {\n const c = id[i];\n let characterType;\n if (c === "-" || c === "_")\n continue;\n if (c >= "a" && c <= "z")\n characterType = "lower";\n else if (c >= "A" && c <= "Z")\n characterType = "upper";\n else if (c >= "0" && c <= "9")\n characterType = "digit";\n else\n characterType = "other";\n if (characterType === "lower" && lastCharacterType === "upper") {\n lastCharacterType = characterType;\n continue;\n }\n if (lastCharacterType && lastCharacterType !== characterType)\n ++transitionCount;\n lastCharacterType = characterType;\n }\n return transitionCount >= id.length / 4;\n}\nfunction trimWordBoundary(text, maxLength) {\n if (text.length <= maxLength)\n return text;\n text = text.substring(0, maxLength);\n const match = text.match(/^(.*)\\b(.+?)$/);\n if (!match)\n return "";\n return match[1].trimEnd();\n}\nfunction suitableTextAlternatives(text) {\n let result = [];\n {\n const match = text.match(/^([\\d.,]+)[^.,\\w]/);\n const leadingNumberLength = match ? match[1].length : 0;\n if (leadingNumberLength) {\n const alt = trimWordBoundary(text.substring(leadingNumberLength).trimStart(), 80);\n result.push({ text: alt, scoreBonus: alt.length <= 30 ? 2 : 1 });\n }\n }\n {\n const match = text.match(/[^.,\\w]([\\d.,]+)$/);\n const trailingNumberLength = match ? match[1].length : 0;\n if (trailingNumberLength) {\n const alt = trimWordBoundary(text.substring(0, text.length - trailingNumberLength).trimEnd(), 80);\n result.push({ text: alt, scoreBonus: alt.length <= 30 ? 2 : 1 });\n }\n }\n if (text.length <= 30) {\n result.push({ text, scoreBonus: 0 });\n } else {\n result.push({ text: trimWordBoundary(text, 80), scoreBonus: 0 });\n result.push({ text: trimWordBoundary(text, 30), scoreBonus: 1 });\n }\n result = result.filter((r) => r.text);\n if (!result.length)\n result.push({ text: text.substring(0, 80), scoreBonus: 0 });\n return result;\n}\nfunction escapeNodeName(node) {\n return node.nodeName.toLocaleLowerCase().replace(/[:\\.]/g, (char) => "\\\\" + char);\n}\nfunction escapeClassName(className) {\n let result = "";\n for (let i = 0; i < className.length; i++)\n result += cssEscapeCharacter(className, i);\n return result;\n}\nfunction cssEscapeCharacter(s, i) {\n const c = s.charCodeAt(i);\n if (c === 0)\n return "\\uFFFD";\n if (c >= 1 && c <= 31 || c >= 48 && c <= 57 && (i === 0 || i === 1 && s.charCodeAt(0) === 45))\n return "\\\\" + c.toString(16) + " ";\n if (i === 0 && c === 45 && s.length === 1)\n return "\\\\" + s.charAt(i);\n if (c >= 128 || c === 45 || c === 95 || c >= 48 && c <= 57 || c >= 65 && c <= 90 || c >= 97 && c <= 122)\n return s.charAt(i);\n return "\\\\" + s.charAt(i);\n}\n\n// packages/injected/src/xpathSelectorEngine.ts\nvar XPathEngine = {\n queryAll(root, selector) {\n if (selector.startsWith("/") && root.nodeType !== Node.DOCUMENT_NODE)\n selector = "." + selector;\n const result = [];\n const document = root.ownerDocument || root;\n if (!document)\n return result;\n const it = document.evaluate(selector, root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE);\n for (let node = it.iterateNext(); node; node = it.iterateNext()) {\n if (node.nodeType === Node.ELEMENT_NODE)\n result.push(node);\n }\n return result;\n }\n};\n\n// packages/injected/src/consoleApi.ts\nvar selectorSymbol = Symbol("selector");\nselectorSymbol;\nvar _Locator = class _Locator {\n constructor(injectedScript, selector, options) {\n if (options == null ? void 0 : options.hasText)\n selector += ` >> internal:has-text=${escapeForTextSelector(options.hasText, false)}`;\n if (options == null ? void 0 : options.hasNotText)\n selector += ` >> internal:has-not-text=${escapeForTextSelector(options.hasNotText, false)}`;\n if (options == null ? void 0 : options.has)\n selector += ` >> internal:has=` + JSON.stringify(options.has[selectorSymbol]);\n if (options == null ? void 0 : options.hasNot)\n selector += ` >> internal:has-not=` + JSON.stringify(options.hasNot[selectorSymbol]);\n if ((options == null ? void 0 : options.visible) !== void 0)\n selector += ` >> visible=${options.visible ? "true" : "false"}`;\n this[selectorSymbol] = selector;\n if (selector) {\n const parsed = injectedScript.parseSelector(selector);\n this.element = injectedScript.querySelector(parsed, injectedScript.document, false);\n this.elements = injectedScript.querySelectorAll(parsed, injectedScript.document);\n }\n const selectorBase = selector;\n const self = this;\n self.locator = (selector2, options2) => {\n return new _Locator(injectedScript, selectorBase ? selectorBase + " >> " + selector2 : selector2, options2);\n };\n self.getByTestId = (testId) => self.locator(getByTestIdSelector(injectedScript.testIdAttributeNameForStrictErrorAndConsoleCodegen(), testId));\n self.getByAltText = (text, options2) => self.locator(getByAltTextSelector(text, options2));\n self.getByLabel = (text, options2) => self.locator(getByLabelSelector(text, options2));\n self.getByPlaceholder = (text, options2) => self.locator(getByPlaceholderSelector(text, options2));\n self.getByText = (text, options2) => self.locator(getByTextSelector(text, options2));\n self.getByTitle = (text, options2) => self.locator(getByTitleSelector(text, options2));\n self.getByRole = (role, options2 = {}) => self.locator(getByRoleSelector(role, options2));\n self.filter = (options2) => new _Locator(injectedScript, selector, options2);\n self.first = () => self.locator("nth=0");\n self.last = () => self.locator("nth=-1");\n self.nth = (index) => self.locator(`nth=${index}`);\n self.and = (locator) => new _Locator(injectedScript, selectorBase + ` >> internal:and=` + JSON.stringify(locator[selectorSymbol]));\n self.or = (locator) => new _Locator(injectedScript, selectorBase + ` >> internal:or=` + JSON.stringify(locator[selectorSymbol]));\n }\n};\nvar Locator = _Locator;\nvar ConsoleAPI = class {\n constructor(injectedScript) {\n this._injectedScript = injectedScript;\n }\n install() {\n if (this._injectedScript.window.playwright)\n return;\n this._injectedScript.window.playwright = {\n $: (selector, strict) => this._querySelector(selector, !!strict),\n $$: (selector) => this._querySelectorAll(selector),\n inspect: (selector) => this._inspect(selector),\n selector: (element) => this._selector(element),\n generateLocator: (element, language) => this._generateLocator(element, language),\n ariaSnapshot: (element, options) => {\n return this._injectedScript.ariaSnapshot(element || this._injectedScript.document.body, options || { mode: "default" });\n },\n resume: () => this._resume(),\n ...new Locator(this._injectedScript, "")\n };\n delete this._injectedScript.window.playwright.filter;\n delete this._injectedScript.window.playwright.first;\n delete this._injectedScript.window.playwright.last;\n delete this._injectedScript.window.playwright.nth;\n delete this._injectedScript.window.playwright.and;\n delete this._injectedScript.window.playwright.or;\n }\n _querySelector(selector, strict) {\n if (typeof selector !== "string")\n throw new Error(`Usage: playwright.query(\'Playwright >> selector\').`);\n const parsed = this._injectedScript.parseSelector(selector);\n return this._injectedScript.querySelector(parsed, this._injectedScript.document, strict);\n }\n _querySelectorAll(selector) {\n if (typeof selector !== "string")\n throw new Error(`Usage: playwright.$$(\'Playwright >> selector\').`);\n const parsed = this._injectedScript.parseSelector(selector);\n return this._injectedScript.querySelectorAll(parsed, this._injectedScript.document);\n }\n _inspect(selector) {\n if (typeof selector !== "string")\n throw new Error(`Usage: playwright.inspect(\'Playwright >> selector\').`);\n this._injectedScript.window.inspect(this._querySelector(selector, false));\n }\n _selector(element) {\n if (!(element instanceof Element))\n throw new Error(`Usage: playwright.selector(element).`);\n return this._injectedScript.generateSelectorSimple(element);\n }\n _generateLocator(element, language) {\n if (!(element instanceof Element))\n throw new Error(`Usage: playwright.locator(element).`);\n const selector = this._injectedScript.generateSelectorSimple(element);\n return asLocator(language || "javascript", selector);\n }\n _resume() {\n if (!this._injectedScript.window.__pw_resume)\n return false;\n this._injectedScript.window.__pw_resume().catch(() => {\n });\n }\n};\n\n// packages/isomorphic/utilityScriptSerializers.ts\nfunction isRegExp2(obj) {\n try {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === "[object RegExp]";\n } catch (error) {\n return false;\n }\n}\nfunction isDate(obj) {\n try {\n return obj instanceof Date || Object.prototype.toString.call(obj) === "[object Date]";\n } catch (error) {\n return false;\n }\n}\nfunction isURL(obj) {\n try {\n return obj instanceof URL || Object.prototype.toString.call(obj) === "[object URL]";\n } catch (error) {\n return false;\n }\n}\nfunction isError(obj) {\n var _a;\n try {\n return obj instanceof Error || obj && ((_a = Object.getPrototypeOf(obj)) == null ? void 0 : _a.name) === "Error";\n } catch (error) {\n return false;\n }\n}\nfunction isTypedArray(obj, constructor) {\n try {\n return obj instanceof constructor || Object.prototype.toString.call(obj) === `[object ${constructor.name}]`;\n } catch (error) {\n return false;\n }\n}\nfunction isArrayBuffer(obj) {\n try {\n return obj instanceof ArrayBuffer || Object.prototype.toString.call(obj) === "[object ArrayBuffer]";\n } catch (error) {\n return false;\n }\n}\nvar typedArrayConstructors = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n // TODO: add Float16Array once it\'s in baseline\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array\n};\nfunction typedArrayToBase64(array) {\n if ("toBase64" in array)\n return array.toBase64();\n const binary = Array.from(new Uint8Array(array.buffer, array.byteOffset, array.byteLength)).map((b) => String.fromCharCode(b)).join("");\n return btoa(binary);\n}\nfunction base64ToTypedArray(base64, TypedArrayConstructor) {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++)\n bytes[i] = binary.charCodeAt(i);\n return new TypedArrayConstructor(bytes.buffer);\n}\nfunction parseEvaluationResultValue(value, handles = [], refs = /* @__PURE__ */ new Map()) {\n if (Object.is(value, void 0))\n return void 0;\n if (typeof value === "object" && value) {\n if ("ref" in value)\n return refs.get(value.ref);\n if ("v" in value) {\n if (value.v === "undefined")\n return void 0;\n if (value.v === "null")\n return null;\n if (value.v === "NaN")\n return NaN;\n if (value.v === "Infinity")\n return Infinity;\n if (value.v === "-Infinity")\n return -Infinity;\n if (value.v === "-0")\n return -0;\n return void 0;\n }\n if ("d" in value) {\n return new Date(value.d);\n }\n if ("u" in value)\n return new URL(value.u);\n if ("bi" in value)\n return BigInt(value.bi);\n if ("e" in value) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if ("r" in value)\n return new RegExp(value.r.p, value.r.f);\n if ("a" in value) {\n const result = [];\n refs.set(value.id, result);\n for (const a of value.a)\n result.push(parseEvaluationResultValue(a, handles, refs));\n return result;\n }\n if ("o" in value) {\n const result = {};\n refs.set(value.id, result);\n for (const { k, v } of value.o) {\n if (k === "__proto__")\n continue;\n result[k] = parseEvaluationResultValue(v, handles, refs);\n }\n return result;\n }\n if ("h" in value)\n return handles[value.h];\n if ("ta" in value)\n return base64ToTypedArray(value.ta.b, typedArrayConstructors[value.ta.k]);\n if ("ab" in value)\n return base64ToTypedArray(value.ab.b, Uint8Array).buffer;\n }\n return value;\n}\nfunction serializeAsCallArgument(value, handleSerializer) {\n return serialize(value, handleSerializer, { visited: /* @__PURE__ */ new Map(), lastId: 0 });\n}\nfunction serialize(value, handleSerializer, visitorInfo) {\n if (value && typeof value === "object") {\n if (typeof globalThis.Window === "function" && value instanceof globalThis.Window)\n return "ref: ";\n if (typeof globalThis.Document === "function" && value instanceof globalThis.Document)\n return "ref: ";\n if (typeof globalThis.Node === "function" && value instanceof globalThis.Node)\n return "ref: ";\n }\n return innerSerialize(value, handleSerializer, visitorInfo);\n}\nfunction innerSerialize(value, handleSerializer, visitorInfo) {\n var _a;\n const result = handleSerializer(value);\n if ("fallThrough" in result)\n value = result.fallThrough;\n else\n return result;\n if (typeof value === "symbol")\n return { v: "undefined" };\n if (Object.is(value, void 0))\n return { v: "undefined" };\n if (Object.is(value, null))\n return { v: "null" };\n if (Object.is(value, NaN))\n return { v: "NaN" };\n if (Object.is(value, Infinity))\n return { v: "Infinity" };\n if (Object.is(value, -Infinity))\n return { v: "-Infinity" };\n if (Object.is(value, -0))\n return { v: "-0" };\n if (typeof value === "boolean")\n return value;\n if (typeof value === "number")\n return value;\n if (typeof value === "string")\n return value;\n if (typeof value === "bigint")\n return { bi: value.toString() };\n if (isError(value)) {\n let stack;\n if ((_a = value.stack) == null ? void 0 : _a.startsWith(value.name + ": " + value.message)) {\n stack = value.stack;\n } else {\n stack = `${value.name}: ${value.message}\n${value.stack}`;\n }\n return { e: { n: value.name, m: value.message, s: stack } };\n }\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp2(value))\n return { r: { p: value.source, f: value.flags } };\n for (const [k, ctor] of Object.entries(typedArrayConstructors)) {\n if (isTypedArray(value, ctor))\n return { ta: { b: typedArrayToBase64(value), k } };\n }\n if (isArrayBuffer(value))\n return { ab: { b: typedArrayToBase64(new Uint8Array(value)) } };\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n if (Array.isArray(value)) {\n const a = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (let i = 0; i < value.length; ++i)\n a.push(serialize(value[i], handleSerializer, visitorInfo));\n return { a, id: id2 };\n }\n if (typeof value === "object") {\n const o = [];\n const id2 = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id2);\n for (const name of Object.keys(value)) {\n let item;\n try {\n item = value[name];\n } catch (e) {\n continue;\n }\n if (name === "toJSON" && typeof item === "function")\n o.push({ k: name, v: { o: [], id: 0 } });\n else\n o.push({ k: name, v: serialize(item, handleSerializer, visitorInfo) });\n }\n let jsonWrapper;\n try {\n if (o.length === 0 && value.toJSON && typeof value.toJSON === "function")\n jsonWrapper = { value: value.toJSON() };\n } catch (e) {\n }\n if (jsonWrapper)\n return innerSerialize(jsonWrapper.value, handleSerializer, visitorInfo);\n return { o, id: id2 };\n }\n}\n\n// packages/injected/src/utilityScript.ts\nvar UtilityScript = class {\n constructor(global, isUnderTest) {\n var _a, _b, _c, _d, _e, _f, _g, _h;\n this.global = global;\n this.isUnderTest = isUnderTest;\n if (global.__pwClock) {\n this.builtins = global.__pwClock.builtins;\n } else {\n this.builtins = {\n setTimeout: (_a = global.setTimeout) == null ? void 0 : _a.bind(global),\n clearTimeout: (_b = global.clearTimeout) == null ? void 0 : _b.bind(global),\n setInterval: (_c = global.setInterval) == null ? void 0 : _c.bind(global),\n clearInterval: (_d = global.clearInterval) == null ? void 0 : _d.bind(global),\n requestAnimationFrame: (_e = global.requestAnimationFrame) == null ? void 0 : _e.bind(global),\n cancelAnimationFrame: (_f = global.cancelAnimationFrame) == null ? void 0 : _f.bind(global),\n requestIdleCallback: (_g = global.requestIdleCallback) == null ? void 0 : _g.bind(global),\n cancelIdleCallback: (_h = global.cancelIdleCallback) == null ? void 0 : _h.bind(global),\n performance: global.performance,\n Intl: global.Intl,\n Date: global.Date,\n AbortSignal: global.AbortSignal\n };\n }\n if (this.isUnderTest)\n global.builtins = this.builtins;\n }\n evaluate(isFunction, returnByValue, expression, argCount, ...argsAndHandles) {\n const args = argsAndHandles.slice(0, argCount);\n const handles = argsAndHandles.slice(argCount);\n const parameters = [];\n for (let i = 0; i < args.length; i++)\n parameters[i] = parseEvaluationResultValue(args[i], handles);\n let result = this.global.eval(expression);\n if (isFunction === true) {\n result = result(...parameters);\n } else if (isFunction === false) {\n result = result;\n } else {\n if (typeof result === "function")\n result = result(...parameters);\n }\n return returnByValue ? this._promiseAwareJsonValueNoThrow(result) : result;\n }\n jsonValue(returnByValue, value) {\n if (value === void 0)\n return void 0;\n return serializeAsCallArgument(value, (value2) => ({ fallThrough: value2 }));\n }\n _promiseAwareJsonValueNoThrow(value) {\n const safeJson = (value2) => {\n try {\n return this.jsonValue(true, value2);\n } catch (e) {\n return void 0;\n }\n };\n if (value && typeof value === "object" && typeof value.then === "function") {\n return (async () => {\n const promiseValue = await value;\n return safeJson(promiseValue);\n })();\n }\n return safeJson(value);\n }\n};\n\n// packages/injected/src/injectedScript.ts\nvar InjectedScript = class {\n constructor(window, options) {\n this._testIdAttributeNameForStrictErrorAndConsoleCodegen = "data-testid";\n this._lastAriaSnapshotForTrack = /* @__PURE__ */ new Map();\n // Recorder must use any external dependencies through InjectedScript.\n // Otherwise it will end up with a copy of all modules it uses, and any\n // module-level globals will be duplicated, which leads to subtle bugs.\n this.utils = {\n asLocator,\n cacheNormalizedWhitespaces,\n elementText,\n getAriaRole,\n getElementAccessibleDescription,\n getElementAccessibleName,\n isElementVisible,\n isInsideScope,\n normalizeWhiteSpace,\n parseAriaSnapshot,\n generateAriaTree,\n findNewElement,\n // Builtins protect injected code from clock emulation.\n builtins: null\n };\n this.window = window;\n this.document = window.document;\n this.isUnderTest = options.isUnderTest;\n this.utils.builtins = new UtilityScript(window, options.isUnderTest).builtins;\n this._sdkLanguage = options.sdkLanguage;\n this._testIdAttributeNameForStrictErrorAndConsoleCodegen = options.testIdAttributeName;\n this._evaluator = new SelectorEvaluatorImpl();\n this.consoleApi = new ConsoleAPI(this);\n this.onGlobalListenersRemoved = /* @__PURE__ */ new Set();\n this._autoClosingTags = /* @__PURE__ */ new Set(["AREA", "BASE", "BR", "COL", "COMMAND", "EMBED", "HR", "IMG", "INPUT", "KEYGEN", "LINK", "MENUITEM", "META", "PARAM", "SOURCE", "TRACK", "WBR"]);\n this._booleanAttributes = /* @__PURE__ */ new Set(["checked", "selected", "disabled", "readonly", "multiple"]);\n this._eventTypes = /* @__PURE__ */ new Map([\n ["auxclick", "mouse"],\n ["click", "mouse"],\n ["dblclick", "mouse"],\n ["mousedown", "mouse"],\n ["mouseeenter", "mouse"],\n ["mouseleave", "mouse"],\n ["mousemove", "mouse"],\n ["mouseout", "mouse"],\n ["mouseover", "mouse"],\n ["mouseup", "mouse"],\n ["mouseleave", "mouse"],\n ["mousewheel", "mouse"],\n ["keydown", "keyboard"],\n ["keyup", "keyboard"],\n ["keypress", "keyboard"],\n ["textInput", "keyboard"],\n ["touchstart", "touch"],\n ["touchmove", "touch"],\n ["touchend", "touch"],\n ["touchcancel", "touch"],\n ["pointerover", "pointer"],\n ["pointerout", "pointer"],\n ["pointerenter", "pointer"],\n ["pointerleave", "pointer"],\n ["pointerdown", "pointer"],\n ["pointerup", "pointer"],\n ["pointermove", "pointer"],\n ["pointercancel", "pointer"],\n ["gotpointercapture", "pointer"],\n ["lostpointercapture", "pointer"],\n ["focus", "focus"],\n ["blur", "focus"],\n ["drag", "drag"],\n ["dragstart", "drag"],\n ["dragend", "drag"],\n ["dragover", "drag"],\n ["dragenter", "drag"],\n ["dragleave", "drag"],\n ["dragexit", "drag"],\n ["drop", "drag"],\n ["wheel", "wheel"],\n ["deviceorientation", "deviceorientation"],\n ["deviceorientationabsolute", "deviceorientation"],\n ["devicemotion", "devicemotion"]\n ]);\n this._hoverHitTargetInterceptorEvents = /* @__PURE__ */ new Set(["mousemove"]);\n this._tapHitTargetInterceptorEvents = /* @__PURE__ */ new Set(["pointerdown", "pointerup", "touchstart", "touchend", "touchcancel"]);\n this._mouseHitTargetInterceptorEvents = /* @__PURE__ */ new Set(["mousedown", "mouseup", "pointerdown", "pointerup", "click", "auxclick", "dblclick", "contextmenu"]);\n this._allHitTargetInterceptorEvents = /* @__PURE__ */ new Set([...this._hoverHitTargetInterceptorEvents, ...this._tapHitTargetInterceptorEvents, ...this._mouseHitTargetInterceptorEvents]);\n this._engines = /* @__PURE__ */ new Map();\n this._engines.set("xpath", XPathEngine);\n this._engines.set("xpath:light", XPathEngine);\n this._engines.set("role", createRoleEngine(false));\n this._engines.set("text", this._createTextEngine(true, false));\n this._engines.set("text:light", this._createTextEngine(false, false));\n this._engines.set("id", this._createAttributeEngine("id", true));\n this._engines.set("id:light", this._createAttributeEngine("id", false));\n this._engines.set("data-testid", this._createAttributeEngine("data-testid", true));\n this._engines.set("data-testid:light", this._createAttributeEngine("data-testid", false));\n this._engines.set("data-test-id", this._createAttributeEngine("data-test-id", true));\n this._engines.set("data-test-id:light", this._createAttributeEngine("data-test-id", false));\n this._engines.set("data-test", this._createAttributeEngine("data-test", true));\n this._engines.set("data-test:light", this._createAttributeEngine("data-test", false));\n this._engines.set("css", this._createCSSEngine());\n this._engines.set("nth", { queryAll: () => [] });\n this._engines.set("visible", this._createVisibleEngine());\n this._engines.set("internal:control", this._createControlEngine());\n this._engines.set("internal:has", this._createHasEngine());\n this._engines.set("internal:has-not", this._createHasNotEngine());\n this._engines.set("internal:and", { queryAll: () => [] });\n this._engines.set("internal:or", { queryAll: () => [] });\n this._engines.set("internal:chain", this._createInternalChainEngine());\n this._engines.set("internal:label", this._createInternalLabelEngine());\n this._engines.set("internal:text", this._createTextEngine(true, true));\n this._engines.set("internal:has-text", this._createInternalHasTextEngine());\n this._engines.set("internal:has-not-text", this._createInternalHasNotTextEngine());\n this._engines.set("internal:attr", this._createNamedAttributeEngine());\n this._engines.set("internal:testid", this._createTestIdEngine());\n this._engines.set("internal:role", createRoleEngine(true));\n this._engines.set("internal:describe", this._createDescribeEngine());\n this._engines.set("aria-ref", this._createAriaRefEngine());\n for (const { name, source } of options.customEngines)\n this._engines.set(name, this.eval(source));\n this._stableRafCount = options.stableRafCount;\n this._browserName = options.browserName;\n this._shouldPrependErrorPrefix = !!options.shouldPrependErrorPrefix;\n this._isUtilityWorld = !!options.isUtilityWorld;\n setGlobalOptions({ browserNameForWorkarounds: options.browserName });\n this._setupGlobalListenersRemovalDetection();\n this._setupHitTargetInterceptors();\n if (this.isUnderTest)\n this.window.__injectedScript = this;\n }\n eval(expression) {\n return this.window.eval(expression);\n }\n testIdAttributeNameForStrictErrorAndConsoleCodegen() {\n return this._testIdAttributeNameForStrictErrorAndConsoleCodegen;\n }\n parseSelector(selector) {\n const result = parseSelector(selector);\n visitAllSelectorParts(result, (part) => {\n if (!this._engines.has(part.name))\n throw this.createStacklessError(`Unknown engine "${part.name}" while parsing selector ${selector}`);\n });\n return result;\n }\n generateSelector(targetElement, options) {\n return generateSelector(this, targetElement, options);\n }\n generateSelectorSimple(targetElement, options) {\n return generateSelector(this, targetElement, { ...options, testIdAttributeName: this._testIdAttributeNameForStrictErrorAndConsoleCodegen }).selector;\n }\n querySelector(selector, root, strict) {\n const result = this.querySelectorAll(selector, root);\n if (strict && result.length > 1)\n throw this.strictModeViolationError(selector, result);\n this.checkDeprecatedSelectorUsage(selector, result);\n return result[0];\n }\n _queryNth(elements, part) {\n const list = [...elements];\n let nth = +part.body;\n if (nth === -1)\n nth = list.length - 1;\n return new Set(list.slice(nth, nth + 1));\n }\n _queryLayoutSelector(elements, part, originalRoot) {\n const name = part.name;\n const body = part.body;\n const result = [];\n const inner = this.querySelectorAll(body.parsed, originalRoot);\n for (const element of elements) {\n const score = layoutSelectorScore(name, element, inner, body.distance);\n if (score !== void 0)\n result.push({ element, score });\n }\n result.sort((a, b) => a.score - b.score);\n return new Set(result.map((r) => r.element));\n }\n ariaSnapshot(node, options) {\n return this.incrementalAriaSnapshot(node, options).full;\n }\n incrementalAriaSnapshot(node, options) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n throw this.createStacklessError("Can only capture aria snapshot of Element nodes.");\n const ariaSnapshot = generateAriaTree(node, options);\n const rendered = renderAriaTree(ariaSnapshot, options);\n let incremental;\n if (options.track) {\n const previousSnapshot = this._lastAriaSnapshotForTrack.get(options.track);\n if (previousSnapshot)\n incremental = renderAriaTree(ariaSnapshot, options, previousSnapshot).text;\n this._lastAriaSnapshotForTrack.set(options.track, ariaSnapshot);\n }\n this._lastAriaSnapshotForQuery = ariaSnapshot;\n return { full: rendered.text, incremental, iframeRefs: ariaSnapshot.iframeRefs, iframeDepths: rendered.iframeDepths };\n }\n ariaSnapshotForRecorder() {\n const tree = generateAriaTree(this.document.body, { mode: "ai" });\n const { text: ariaSnapshot } = renderAriaTree(tree, { mode: "ai" });\n return { ariaSnapshot, refs: tree.refs };\n }\n getAllElementsMatchingExpectAriaTemplate(document, template) {\n return getAllElementsMatchingExpectAriaTemplate(document.documentElement, template);\n }\n querySelectorAll(selector, root) {\n if (selector.capture !== void 0) {\n if (selector.parts.some((part) => part.name === "nth"))\n throw this.createStacklessError(`Can\'t query n-th element in a request with the capture.`);\n const withHas = { parts: selector.parts.slice(0, selector.capture + 1) };\n if (selector.capture < selector.parts.length - 1) {\n const parsed = { parts: selector.parts.slice(selector.capture + 1) };\n const has = { name: "internal:has", body: { parsed }, source: stringifySelector(parsed) };\n withHas.parts.push(has);\n }\n return this.querySelectorAll(withHas, root);\n }\n if (!root["querySelectorAll"])\n throw this.createStacklessError("Node is not queryable.");\n if (selector.capture !== void 0) {\n throw this.createStacklessError("Internal error: there should not be a capture in the selector.");\n }\n if (root.nodeType === 11 && selector.parts.length === 1 && selector.parts[0].name === "css" && selector.parts[0].source === ":scope")\n return [root];\n this._evaluator.begin();\n try {\n let roots = /* @__PURE__ */ new Set([root]);\n for (const part of selector.parts) {\n if (part.name === "nth") {\n roots = this._queryNth(roots, part);\n } else if (part.name === "internal:and") {\n const andElements = this.querySelectorAll(part.body.parsed, root);\n roots = new Set(andElements.filter((e) => roots.has(e)));\n } else if (part.name === "internal:or") {\n const orElements = this.querySelectorAll(part.body.parsed, root);\n roots = new Set(sortInDOMOrder(/* @__PURE__ */ new Set([...roots, ...orElements])));\n } else if (kLayoutSelectorNames.includes(part.name)) {\n roots = this._queryLayoutSelector(roots, part, root);\n } else {\n const next = /* @__PURE__ */ new Set();\n for (const root2 of roots) {\n const all = this._queryEngineAll(part, root2);\n for (const one of all)\n next.add(one);\n }\n roots = next;\n }\n }\n return [...roots];\n } finally {\n this._evaluator.end();\n }\n }\n _queryEngineAll(part, root) {\n const result = this._engines.get(part.name).queryAll(root, part.body);\n for (const element of result) {\n if (!("nodeName" in element))\n throw this.createStacklessError(`Expected a Node but got ${Object.prototype.toString.call(element)}`);\n }\n return result;\n }\n _createAttributeEngine(attribute, shadow) {\n const toCSS = (selector) => {\n const css = `[${attribute}=${JSON.stringify(selector)}]`;\n return [{ simples: [{ selector: { css, functions: [] }, combinator: "" }] }];\n };\n return {\n queryAll: (root, selector) => {\n return this._evaluator.query({ scope: root, pierceShadow: shadow }, toCSS(selector));\n }\n };\n }\n _createCSSEngine() {\n return {\n queryAll: (root, body) => {\n return this._evaluator.query({ scope: root, pierceShadow: true }, body);\n }\n };\n }\n _createTextEngine(shadow, internal) {\n const queryAll = (root, selector) => {\n const { matcher, kind } = createTextMatcher(selector, internal);\n const result = [];\n let lastDidNotMatchSelf = null;\n const appendElement = (element) => {\n if (kind === "lax" && lastDidNotMatchSelf && lastDidNotMatchSelf.contains(element))\n return false;\n const matches = elementMatchesText(this._evaluator._cacheText, element, matcher);\n if (matches === "none")\n lastDidNotMatchSelf = element;\n if (matches === "self" || matches === "selfAndChildren" && kind === "strict" && !internal)\n result.push(element);\n };\n if (root.nodeType === Node.ELEMENT_NODE)\n appendElement(root);\n const elements = this._evaluator._queryCSS({ scope: root, pierceShadow: shadow }, "*");\n for (const element of elements)\n appendElement(element);\n return result;\n };\n return { queryAll };\n }\n _createInternalHasTextEngine() {\n return {\n queryAll: (root, selector) => {\n if (root.nodeType !== 1)\n return [];\n const element = root;\n const text = elementText(this._evaluator._cacheText, element);\n const { matcher } = createTextMatcher(selector, true);\n return matcher(text) ? [element] : [];\n }\n };\n }\n _createInternalHasNotTextEngine() {\n return {\n queryAll: (root, selector) => {\n if (root.nodeType !== 1)\n return [];\n const element = root;\n const text = elementText(this._evaluator._cacheText, element);\n const { matcher } = createTextMatcher(selector, true);\n return matcher(text) ? [] : [element];\n }\n };\n }\n _createInternalLabelEngine() {\n return {\n queryAll: (root, selector) => {\n const { matcher } = createTextMatcher(selector, true);\n const allElements = this._evaluator._queryCSS({ scope: root, pierceShadow: true }, "*");\n return allElements.filter((element) => {\n return getElementLabels(this._evaluator._cacheText, element).some((label) => matcher(label));\n });\n }\n };\n }\n _createNamedAttributeEngine() {\n const queryAll = (root, selector) => {\n const parsed = parseAttributeSelector(selector, true);\n if (parsed.name || parsed.attributes.length !== 1)\n throw new Error("Malformed attribute selector: " + selector);\n const { name } = parsed.attributes[0];\n const matcher = createAttributeMatcher(parsed.attributes[0]);\n const elements = this._evaluator._queryCSS({ scope: root, pierceShadow: true }, `[${name}]`);\n return elements.filter((e) => matcher(e.getAttribute(name)));\n };\n return { queryAll };\n }\n _createTestIdEngine() {\n const queryAll = (root, selector) => {\n const parsed = parseAttributeSelector(selector, true);\n if (parsed.name || parsed.attributes.length !== 1)\n throw new Error("Malformed test id selector: " + selector);\n const names = splitTestIdAttributeNames(parsed.attributes[0].name);\n const matcher = createAttributeMatcher(parsed.attributes[0]);\n const cssQuery = names.map((n) => `[${n}]`).join(",");\n const elements = this._evaluator._queryCSS({ scope: root, pierceShadow: true }, cssQuery);\n return elements.filter((e) => names.some((n) => {\n const actual = e.getAttribute(n);\n return actual !== null && matcher(actual);\n }));\n };\n return { queryAll };\n }\n _createDescribeEngine() {\n const queryAll = (root) => {\n if (root.nodeType !== 1)\n return [];\n return [root];\n };\n return { queryAll };\n }\n _createControlEngine() {\n return {\n queryAll(root, body) {\n if (body === "enter-frame")\n return [];\n if (body === "return-empty")\n return [];\n if (body === "component") {\n if (root.nodeType !== 1)\n return [];\n return [root.childElementCount === 1 ? root.firstElementChild : root];\n }\n throw new Error(`Internal error, unknown internal:control selector ${body}`);\n }\n };\n }\n _createHasEngine() {\n const queryAll = (root, body) => {\n if (root.nodeType !== 1)\n return [];\n const has = !!this.querySelector(body.parsed, root, false);\n return has ? [root] : [];\n };\n return { queryAll };\n }\n _createHasNotEngine() {\n const queryAll = (root, body) => {\n if (root.nodeType !== 1)\n return [];\n const has = !!this.querySelector(body.parsed, root, false);\n return has ? [] : [root];\n };\n return { queryAll };\n }\n _createVisibleEngine() {\n const queryAll = (root, body) => {\n if (root.nodeType !== 1)\n return [];\n const visible = body === "true";\n return isElementVisible(root) === visible ? [root] : [];\n };\n return { queryAll };\n }\n _createInternalChainEngine() {\n const queryAll = (root, body) => {\n return this.querySelectorAll(body.parsed, root);\n };\n return { queryAll };\n }\n extend(source, params) {\n const constrFunction = this.window.eval(`\n (() => {\n const module = {};\n ${source}\n return module.exports.default();\n })()`);\n return new constrFunction(this, params);\n }\n async viewportRatio(element) {\n return await new Promise((resolve) => {\n const observer = new IntersectionObserver((entries) => {\n resolve(entries[0].intersectionRatio);\n observer.disconnect();\n });\n observer.observe(element);\n this.utils.builtins.requestAnimationFrame(() => {\n });\n });\n }\n getElementBorderWidth(node) {\n if (node.nodeType !== Node.ELEMENT_NODE || !node.ownerDocument || !node.ownerDocument.defaultView)\n return { left: 0, top: 0 };\n const style = node.ownerDocument.defaultView.getComputedStyle(node);\n return { left: parseInt(style.borderLeftWidth || "", 10), top: parseInt(style.borderTopWidth || "", 10) };\n }\n describeIFrameStyle(iframe) {\n if (!iframe.ownerDocument || !iframe.ownerDocument.defaultView)\n return "error:notconnected";\n const defaultView = iframe.ownerDocument.defaultView;\n for (let e = iframe; e; e = parentElementOrShadowHost(e)) {\n if (defaultView.getComputedStyle(e).transform !== "none")\n return "transformed";\n }\n const iframeStyle = defaultView.getComputedStyle(iframe);\n return {\n left: parseInt(iframeStyle.borderLeftWidth || "", 10) + parseInt(iframeStyle.paddingLeft || "", 10),\n top: parseInt(iframeStyle.borderTopWidth || "", 10) + parseInt(iframeStyle.paddingTop || "", 10)\n };\n }\n retarget(node, behavior) {\n let element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\n if (!element)\n return null;\n if (behavior === "none")\n return element;\n if (!element.matches("input, textarea, select") && !element.isContentEditable) {\n if (behavior === "button-link")\n element = element.closest("button, [role=button], a, [role=link]") || element;\n else\n element = element.closest("button, [role=button], [role=checkbox], [role=radio]") || element;\n }\n if (behavior === "follow-label") {\n if (!element.matches("a, input, textarea, button, select, [role=link], [role=button], [role=checkbox], [role=radio]") && !element.isContentEditable) {\n const enclosingLabel = element.closest("label");\n if (enclosingLabel && enclosingLabel.control)\n element = enclosingLabel.control;\n }\n }\n return element;\n }\n async checkElementStates(node, states) {\n if (states.includes("stable")) {\n const stableResult = await this._checkElementIsStable(node);\n if (stableResult === false)\n return { missingState: "stable" };\n if (stableResult === "error:notconnected")\n return "error:notconnected";\n }\n for (const state of states) {\n if (state !== "stable") {\n const result = this.elementState(node, state);\n if (result.received === "error:notconnected")\n return "error:notconnected";\n if (!result.matches)\n return { missingState: state };\n }\n }\n }\n async _checkElementIsStable(node) {\n const continuePolling = Symbol("continuePolling");\n let lastRect;\n let stableRafCounter = 0;\n let lastTime = 0;\n const check = () => {\n const element = this.retarget(node, "no-follow-label");\n if (!element)\n return "error:notconnected";\n const time = this.utils.builtins.performance.now();\n if (this._stableRafCount > 1 && time - lastTime < 15)\n return continuePolling;\n lastTime = time;\n const clientRect = element.getBoundingClientRect();\n const rect = { x: clientRect.top, y: clientRect.left, width: clientRect.width, height: clientRect.height };\n if (lastRect) {\n const samePosition = rect.x === lastRect.x && rect.y === lastRect.y && rect.width === lastRect.width && rect.height === lastRect.height;\n if (!samePosition)\n return false;\n if (++stableRafCounter >= this._stableRafCount)\n return true;\n }\n lastRect = rect;\n return continuePolling;\n };\n let fulfill;\n let reject;\n const result = new Promise((f, r) => {\n fulfill = f;\n reject = r;\n });\n const raf = () => {\n try {\n const success = check();\n if (success !== continuePolling)\n fulfill(success);\n else\n this.utils.builtins.requestAnimationFrame(raf);\n } catch (e) {\n reject(e);\n }\n };\n this.utils.builtins.requestAnimationFrame(raf);\n return result;\n }\n _createAriaRefEngine() {\n const queryAll = (root, selector) => {\n var _a, _b;\n const result = (_b = (_a = this._lastAriaSnapshotForQuery) == null ? void 0 : _a.elements) == null ? void 0 : _b.get(selector);\n return result && result.isConnected ? [result] : [];\n };\n return { queryAll };\n }\n elementState(node, state) {\n const element = this.retarget(node, ["visible", "hidden"].includes(state) ? "none" : "follow-label");\n if (!element || !element.isConnected) {\n if (state === "hidden")\n return { matches: true, received: "hidden" };\n return { matches: false, received: "error:notconnected" };\n }\n if (state === "visible" || state === "hidden") {\n const visible = isElementVisible(element);\n return {\n matches: state === "visible" ? visible : !visible,\n received: visible ? "visible" : "hidden"\n };\n }\n if (state === "disabled" || state === "enabled") {\n const disabled = getAriaDisabled(element);\n return {\n matches: state === "disabled" ? disabled : !disabled,\n received: disabled ? "disabled" : "enabled"\n };\n }\n if (state === "editable") {\n const disabled = getAriaDisabled(element);\n const readonly = getReadonly(element);\n if (readonly === "error")\n throw this.createStacklessError("Element is not an
${escapeHTML(options.description)}
` : ""; const styleSheet = ` @keyframes pw-chapter-fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes pw-chapter-fade-out { from { opacity: 1; } to { opacity: 0; } } #background { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(2px); animation: pw-chapter-fade-in ${fadeDuration}ms ease-out forwards; } #background.fade-out { animation: pw-chapter-fade-out ${fadeDuration}ms ease-in forwards; } #content { background: rgba(0, 0, 0, 0.7); border: 1px solid rgba(255, 255, 255, 0.15); border-radius: 16px; padding: 40px 56px; max-width: 560px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); } #title { color: white; font-family: system-ui, -apple-system, sans-serif; font-size: 28px; font-weight: 600; line-height: 1.3; text-align: center; letter-spacing: -0.01em; } #description { color: rgba(255, 255, 255, 0.7); font-family: system-ui, -apple-system, sans-serif; font-size: 15px; line-height: 1.5; margin-top: 12px; text-align: center; } `; const duration = options.duration ?? 2e3; const html = `
${escapeHTML(options.title)}
${descriptionHtml}
`; const id = await this.show(html); await new Promise((f) => setTimeout(f, duration)); const utility = await this._page.mainFrame().utilityContext(); await utility.evaluate(({ injected, id: id2, fadeDuration: fadeDuration2 }) => { const overlay = injected.getUserOverlay(id2); const bg = overlay?.querySelector("#background"); if (bg) bg.classList.add("fade-out"); return new Promise((f) => injected.utils.builtins.setTimeout(f, fadeDuration2)); }, { injected: await utility.injectedScript(), id, fadeDuration }).catch((e) => debugLogger.log("error", e)); await this.remove(id); } async setVisible(visible) { if (!this._overlays.size) return; const utility = await this._page.mainFrame().utilityContext(); await utility.evaluate(({ injected, visible: visible2 }) => { injected.setUserOverlaysVisible(visible2); }, { injected: await utility.injectedScript(), visible }).catch((e) => debugLogger.log("error", e)); } }; } }); // packages/playwright-core/src/server/screencast.ts var Screencast; var init_screencast = __esm({ "packages/playwright-core/src/server/screencast.ts"() { "use strict"; init_manualPromise(); init_protocolFormatter(); init_debugLogger(); init_progress(); init_dom(); Screencast = class { constructor(page) { this._clients = /* @__PURE__ */ new Map(); this.page = page; this.page.instrumentation.addListener(this, this.page.browserContext); } async handlePageOrContextClose() { const clients = [...this._clients.keys()]; this._clients.clear(); for (const client of clients) { if (client.gracefulClose) await client.gracefulClose(); } } dispose() { for (const client of this._clients.keys()) client.dispose(); this._clients.clear(); this.page.instrumentation.removeListener(this); } showActions(options) { this._actions = options; } hideActions() { this._actions = void 0; } addClient(client) { const isFirst = this._clients.size === 0; this._clients.set(client, new ManualPromise()); if (isFirst) { this._startScreencast(client.size, client.quality); } else if (this._lastFrame) { const frame = this._lastFrame; setTimeout(() => { if (this._clients.has(client)) void client.onFrame(frame); }, 0); } return { size: this._size }; } removeClient(client) { const disconnected = this._clients.get(client); if (!disconnected) return; this._clients.delete(client); disconnected.resolve(); if (!this._clients.size) this._stopScreencast(); } _startScreencast(size, quality) { this._size = size; if (!this._size) { const viewport = this.page.browserContext._options.viewport || { width: 800, height: 600 }; const scale = Math.min(1, 800 / Math.max(viewport.width, viewport.height)); this._size = { width: Math.floor(viewport.width * scale), height: Math.floor(viewport.height * scale) }; } this._size = { width: this._size.width & ~1, height: this._size.height & ~1 }; this.page.delegate.startScreencast({ width: this._size.width, height: this._size.height, quality: quality ?? 90 }); } _stopScreencast() { this._lastFrame = void 0; this.page.delegate.stopScreencast(); } onScreencastFrame(frame, ack) { this._lastFrame = frame; const asyncResults = []; for (const [client, disconnected] of this._clients) { const result2 = client.onFrame(frame); if (!result2) continue; asyncResults.push(Promise.race([result2.catch(() => { }), disconnected])); } if (ack) { if (!asyncResults.length) ack(); else Promise.race(asyncResults).then(ack); } } async onBeforeInputAction(sdkObject, metadata, point, box) { if (!this._actions) return; const page = sdkObject.attribution.page; if (page !== this.page) return; if (!box && sdkObject instanceof ElementHandle) box = await sdkObject.boundingBox(nullProgress) || void 0; const actionTitle2 = renderTitleForCall(metadata); const utility = await page.mainFrame().utilityContext(); await utility.evaluate(async (options) => { const { injected, duration } = options; injected.setScreencastAnnotation(options); await new Promise((f) => injected.utils.builtins.setTimeout(f, duration)); injected.setScreencastAnnotation(null); }, { injected: await utility.injectedScript(), duration: this._actions?.duration ?? 500, point, box, actionTitle: actionTitle2, position: this._actions?.position, fontSize: this._actions?.fontSize, cursor: this._actions?.cursor ?? "pointer" }).catch((e) => debugLogger.log("error", e)); } }; } }); // packages/playwright-core/src/server/page.ts async function ariaSnapshotForFrame(progress2, frame, options = {}) { const snapshot3 = await frame.retryWithProgressAndTimeouts(progress2, [1e3, 2e3, 4e3, 8e3], async (progress3, continuePolling) => { try { const context2 = await progress3.race(frame.utilityContext()); const injectedScript = await progress3.race(context2.injectedScript()); const snapshotOrRetry = await progress3.race(injectedScript.evaluate((injected, options2) => { if (options2.info) { const element2 = injected.querySelector(options2.info.parsed, injected.document, options2.info.strict); if (!element2) return false; return injected.incrementalAriaSnapshot(element2, options2); } const node = injected.document.body; if (!node) return true; return injected.incrementalAriaSnapshot(node, options2); }, { mode: options.mode ?? "default", refPrefix: frame.seq ? "f" + frame.seq : "", track: options.track, doNotRenderActive: options.doNotRenderActive, info: options.info, depth: options.depth, boxes: options.boxes })); if (snapshotOrRetry === true) return continuePolling; if (snapshotOrRetry === false) throw new NonRecoverableDOMError(`Selector "${stringifySelector(options.info.parsed)}" does not match any element`); return snapshotOrRetry; } catch (e) { if (frame.isNonRetriableError(e)) throw e; return continuePolling; } }); const renderedIframeRefs = snapshot3.iframeRefs.filter((ref) => ref in snapshot3.iframeDepths); progress2.setAllowConcurrentOrNestedRaces(true); const childSnapshotPromises = renderedIframeRefs.map((ref) => { const iframeDepth = snapshot3.iframeDepths[ref]; const childDepth = options.depth ? options.depth - iframeDepth - 1 : void 0; return ariaSnapshotFrameRef(progress2, frame, ref, { ...options, depth: childDepth }); }); const childSnapshots = await Promise.all(childSnapshotPromises); progress2.setAllowConcurrentOrNestedRaces(false); const full = []; let incremental; if (snapshot3.incremental !== void 0) { incremental = snapshot3.incremental.split("\n"); for (let i = 0; i < renderedIframeRefs.length; i++) { const childSnapshot = childSnapshots[i]; if (childSnapshot.incremental) incremental.push(...childSnapshot.incremental); else if (childSnapshot.full.length) incremental.push("- iframe [ref=" + renderedIframeRefs[i] + "]:", ...childSnapshot.full.map((l) => " " + l)); } } for (const line of snapshot3.full.split("\n")) { const match = line.match(/^(\s*)- iframe (?:\[active\] )?\[ref=([^\]]*)\]/); if (!match) { full.push(line); continue; } const leadingSpace = match[1]; const ref = match[2]; const childSnapshot = childSnapshots[renderedIframeRefs.indexOf(ref)] ?? { full: [] }; full.push(childSnapshot.full.length ? line + ":" : line); full.push(...childSnapshot.full.map((l) => leadingSpace + " " + l)); } return { full, incremental }; } async function ariaSnapshotFrameRef(progress2, parentFrame, frameRef, options) { const frameSelector = `aria-ref=${frameRef} >> internal:control=enter-frame`; const frameBodySelector = `${frameSelector} >> body`; const child = await progress2.race(parentFrame.selectors.resolveFrameForSelector(frameBodySelector, { strict: true })); if (!child) return { full: [] }; try { return await ariaSnapshotForFrame(progress2, child.frame, { ...options, info: void 0 }); } catch { return { full: [] }; } } function ensureArrayLimit(array, limit) { if (array.length > limit) return array.splice(0, limit / 10); return []; } var PageEvent, navigationMarkSymbol, Page, WorkerEvent, Worker, PageBinding, InitScript; var init_page = __esm({ "packages/playwright-core/src/server/page.ts"() { "use strict"; init_selectorParser(); init_manualPromise(); init_utilityScriptSerializers(); init_comparators(); init_debugLogger(); init_manualPromise(); init_assert(); init_stringUtils(); init_locatorGenerators(); init_browserContext(); init_disposable2(); init_console(); init_errors(); init_fileChooser(); init_frames(); init_helper(); init_input(); init_instrumentation(); init_javascript(); init_screenshotter(); init_callLog(); init_bindingsControllerSource(); init_overlay(); init_dom(); init_screencast(); init_javascript(); PageEvent = { Close: "close", Crash: "crash", Download: "download", EmulatedSizeChanged: "emulatedsizechanged", FileChooser: "filechooser", FrameAttached: "frameattached", FrameDetached: "framedetached", InternalFrameNavigatedToNewDocument: "internalframenavigatedtonewdocument", LocatorHandlerTriggered: "locatorhandlertriggered", WebSocket: "websocket", Worker: "worker" }; navigationMarkSymbol = Symbol("navigationMark"); Page = class _Page extends SdkObject { constructor(delegate, browserContext) { super(browserContext, "page"); this._closedState = "open"; this.closedPromise = new ManualPromise(); this._initializedPromise = new ManualPromise(); this._consoleMessages = []; this._pageErrors = []; this._crashed = false; this.openScope = new LongStandingScope(); this._emulatedMedia = {}; this._fileChooserInterceptedBy = /* @__PURE__ */ new Set(); this._pageBindings = /* @__PURE__ */ new Map(); this.initScripts = []; this._workers = /* @__PURE__ */ new Map(); this.requestInterceptors = []; this._locatorHandlers = /* @__PURE__ */ new Map(); this._lastLocatorHandlerUid = 0; this._locatorHandlerRunningCounter = 0; this._networkRequests = []; this.attribution.page = this; this.delegate = delegate; this.browserContext = browserContext; this.keyboard = new Keyboard(delegate.rawKeyboard, this); this.mouse = new Mouse(delegate.rawMouse, this); this.touchscreen = new Touchscreen(delegate.rawTouchscreen, this); this.screenshotter = new Screenshotter(this); this.frameManager = new FrameManager(this); this.overlay = new Overlay(this); this.screencast = new Screencast(this); if (delegate.pdf) this.pdf = delegate.pdf.bind(delegate); this.coverage = delegate.coverage ? delegate.coverage() : null; this.isStorageStatePage = browserContext.isCreatingStorageStatePage(); } static { this.Events = PageEvent; } async reportAsNew(opener, error) { if (this.delegate.noUtilityWorld?.()) { await this._addInitScript(saveGlobalsSnapshotSource); await this.safeNonStallingEvaluateInAllFrames(saveGlobalsSnapshotSource, "main"); } if (opener) { const openerPageOrError = await opener.waitForInitializedOrError(); if (openerPageOrError instanceof _Page && !openerPageOrError.isClosed()) this._opener = openerPageOrError; } this._markInitialized(error); } _markInitialized(error = void 0) { if (error) { if (this.browserContext.isClosingOrClosed()) return; this.frameManager.createDummyMainFrameIfNeeded(); } this._initialized = error || this; this.emitOnContext(BrowserContext.Events.Page, this); for (const pageError of this._pageErrors) this.emitOnContext(BrowserContext.Events.PageError, pageError, this); for (const message of this._consoleMessages) this.emitOnContext(BrowserContext.Events.Console, message); if (this.isClosed()) this.emit(_Page.Events.Close); else this.instrumentation.onPageOpen(this); this._initializedPromise.resolve(this._initialized); } initializedOrUndefined() { return this._initialized ? this : void 0; } waitForInitializedOrError() { return this._initializedPromise; } emitOnContext(event, ...args) { if (this.isStorageStatePage) return; this.browserContext.emit(event, ...args); } async resetForReuse(progress2) { await this.mainFrame().gotoImpl(progress2, "about:blank", {}); this._emulatedSize = void 0; this._emulatedMedia = {}; this._extraHTTPHeaders = void 0; await progress2.race(Promise.all([ this.delegate.updateEmulatedViewportSize(), this.delegate.updateEmulateMedia(), this.delegate.updateExtraHTTPHeaders() ])); await this.delegate.resetForReuse(progress2); } _didClose() { this.frameManager.dispose(); this.screencast.dispose(); this.overlay.dispose(); assert(this._closedState !== "closed", "Page closed twice"); this._closedState = "closed"; this.emit(_Page.Events.Close); this.browserContext.emit(BrowserContext.Events.PageClosed, this); this.closedPromise.resolve(); this.instrumentation.onPageClose(this); this.openScope.close(new TargetClosedError(this.closeReason())); } _didCrash() { this.frameManager.dispose(); this.screencast.dispose(); this.overlay.dispose(); this.emit(_Page.Events.Crash); this._crashed = true; this.instrumentation.onPageClose(this); this.openScope.close(new Error("Page crashed")); } async _onFileChooserOpened(handle) { let multiple; try { multiple = await handle.evaluate((element2) => !!element2.multiple); } catch (e) { return; } if (!this.listenerCount(_Page.Events.FileChooser)) { handle.dispose(); return; } const fileChooser = new FileChooser(handle, multiple); this.emit(_Page.Events.FileChooser, fileChooser); } opener() { return this._opener; } mainFrame() { return this.frameManager.mainFrame(); } frames() { return this.frameManager.frames(); } async exposeBinding(progress2, name, playwrightBinding) { if (this._pageBindings.has(name)) throw new Error(`Function "${name}" has been already registered`); if (this.browserContext._pageBindings.has(name)) throw new Error(`Function "${name}" has been already registered in the browser context`); await progress2.race(this.browserContext.exposePlaywrightBindingIfNeeded()); const binding = new PageBinding(this, name, playwrightBinding); this._pageBindings.set(name, binding); try { await progress2.race(this.delegate.addInitScript(binding.initScript)); await progress2.race(this.safeNonStallingEvaluateInAllFrames(binding.initScript.source, "main")); return binding; } catch (error) { this._pageBindings.delete(name); throw error; } } async removeExposedBinding(binding) { if (this._pageBindings.get(binding.name) !== binding) return; this._pageBindings.delete(binding.name); await this.delegate.removeInitScripts([binding.initScript]); const cleanup = `{ ${binding.cleanupScript} };`; await this.safeNonStallingEvaluateInAllFrames(cleanup, "main"); } async setExtraHTTPHeaders(progress2, headers) { const oldHeaders = this._extraHTTPHeaders; try { this._extraHTTPHeaders = headers; await progress2.race(this.delegate.updateExtraHTTPHeaders()); } catch (error) { this._extraHTTPHeaders = oldHeaders; this.delegate.updateExtraHTTPHeaders().catch(() => { }); throw error; } } extraHTTPHeaders() { return this._extraHTTPHeaders; } addNetworkRequest(request2) { this._networkRequests.push(request2); ensureArrayLimit(this._networkRequests, 100); } networkRequests() { return this._networkRequests; } async onBindingCalled(payload, context2) { if (this._closedState === "closed") return; await PageBinding.dispatch(this, payload, context2); } addConsoleMessage(worker, type3, args, location2, text2, timestamp) { const message = new ConsoleMessage(this, worker, type3, text2, args, location2, timestamp); const intercepted = this.frameManager.interceptConsoleMessage(message); if (intercepted) { args.forEach((arg) => arg.dispose()); return; } this._consoleMessages.push(message); ensureArrayLimit(this._consoleMessages, 200); if (this._initialized) this.emitOnContext(BrowserContext.Events.Console, message); } clearConsoleMessages() { this._consoleMessages.length = 0; } consoleMessages(filter) { if (filter === "all") return this._consoleMessages; const marked = this._consoleMessages.findLastIndex((m) => m[navigationMarkSymbol]); return marked === -1 ? this._consoleMessages : this._consoleMessages.slice(marked + 1); } addPageError(error, location2) { const pageError = { error, location: location2 }; this._pageErrors.push(pageError); ensureArrayLimit(this._pageErrors, 200); if (this._initialized) this.emitOnContext(BrowserContext.Events.PageError, pageError, this); } clearPageErrors() { this._pageErrors.length = 0; } pageErrors(filter) { if (filter === "all") return this._pageErrors.map((e) => e.error); const marked = this._pageErrors.findLastIndex((e) => e[navigationMarkSymbol]); return (marked === -1 ? this._pageErrors : this._pageErrors.slice(marked + 1)).map((e) => e.error); } async reload(progress2, options) { return this.mainFrame().raceNavigationAction(progress2, async () => { const [response2] = await Promise.all([ // Reload must be a new document, and should not be confused with a stray pushState. this.mainFrame().waitForNavigation(progress2, true, options), progress2.race(this.delegate.reload()) ]); return response2; }); } async goBack(progress2, options) { return this.mainFrame().raceNavigationAction(progress2, async () => { let error; const waitPromise = this.mainFrame().waitForNavigation(progress2, false, options).catch((e) => { error = e; return null; }); const result2 = await progress2.race(this.delegate.goBack()); if (!result2) { waitPromise.catch(() => { }); return null; } const response2 = await waitPromise; if (error) throw error; return response2; }); } async goForward(progress2, options) { return this.mainFrame().raceNavigationAction(progress2, async () => { let error; const waitPromise = this.mainFrame().waitForNavigation(progress2, false, options).catch((e) => { error = e; return null; }); const result2 = await progress2.race(this.delegate.goForward()); if (!result2) { waitPromise.catch(() => { }); return null; } const response2 = await waitPromise; if (error) throw error; return response2; }); } requestGC(progress2) { return progress2.race(this.delegate.requestGC()); } registerLocatorHandler(selector, noWaitAfter) { const uid = ++this._lastLocatorHandlerUid; this._locatorHandlers.set(uid, { selector, noWaitAfter }); return uid; } resolveLocatorHandler(uid, remove) { const handler = this._locatorHandlers.get(uid); if (remove) this._locatorHandlers.delete(uid); if (handler) { handler.resolved?.resolve(); handler.resolved = void 0; } } unregisterLocatorHandler(uid) { this._locatorHandlers.delete(uid); } async performActionPreChecks(progress2) { await this._performWaitForNavigationCheck(progress2); await this._performLocatorHandlersCheckpoint(progress2); await this._performWaitForNavigationCheck(progress2); } async _performWaitForNavigationCheck(progress2) { if (process.env.PLAYWRIGHT_SKIP_NAVIGATION_CHECK) return; const mainFrame = this.frameManager.mainFrame(); if (!mainFrame || !mainFrame.pendingDocument()) return; const url2 = mainFrame.pendingDocument()?.request?.url(); const toUrl = url2 ? `" ${trimStringWithEllipsis(url2, 200)}"` : ""; progress2.log(` waiting for${toUrl} navigation to finish...`); await helper.waitForEvent(progress2, mainFrame, Frame.Events.InternalNavigation, (e) => { if (!e.isPublic) return false; if (!e.error) progress2.log(` navigated to "${trimStringWithEllipsis(mainFrame.url(), 200)}"`); return true; }).promise; } async _performLocatorHandlersCheckpoint(progress2) { if (this._locatorHandlerRunningCounter) return; for (const [uid, handler] of this._locatorHandlers) { if (!handler.resolved) { if (await this.mainFrame().isVisibleInternal(progress2, handler.selector, { strict: true })) { handler.resolved = new ManualPromise(); this.emit(_Page.Events.LocatorHandlerTriggered, uid); } } if (handler.resolved) { ++this._locatorHandlerRunningCounter; progress2.log(` found ${asLocator(this.browserContext._browser.sdkLanguage(), handler.selector)}, intercepting action to run the handler`); const promise = handler.resolved.then(async () => { if (!handler.noWaitAfter) { progress2.log(` locator handler has finished, waiting for ${asLocator(this.browserContext._browser.sdkLanguage(), handler.selector)} to be hidden`); await this.mainFrame().waitForSelector(progress2, handler.selector, false, { state: "hidden" }); } else { progress2.log(` locator handler has finished`); } }); try { progress2.setAllowConcurrentOrNestedRaces(true); await progress2.race(this.openScope.race(promise)); } finally { progress2.setAllowConcurrentOrNestedRaces(false); --this._locatorHandlerRunningCounter; } progress2.log(` interception handler has finished, continuing`); } } } async emulateMedia(progress2, options) { const oldEmulatedMedia = { ...this._emulatedMedia }; if (options.media !== void 0) this._emulatedMedia.media = options.media; if (options.colorScheme !== void 0) this._emulatedMedia.colorScheme = options.colorScheme; if (options.reducedMotion !== void 0) this._emulatedMedia.reducedMotion = options.reducedMotion; if (options.forcedColors !== void 0) this._emulatedMedia.forcedColors = options.forcedColors; if (options.contrast !== void 0) this._emulatedMedia.contrast = options.contrast; try { await progress2.race(this.delegate.updateEmulateMedia()); } catch (error) { this._emulatedMedia = oldEmulatedMedia; this.delegate.updateEmulateMedia().catch(() => { }); throw error; } } emulatedMedia() { const contextOptions = this.browserContext._options; return { media: this._emulatedMedia.media || "no-override", colorScheme: this._emulatedMedia.colorScheme !== void 0 ? this._emulatedMedia.colorScheme : contextOptions.colorScheme ?? "light", reducedMotion: this._emulatedMedia.reducedMotion !== void 0 ? this._emulatedMedia.reducedMotion : contextOptions.reducedMotion ?? "no-preference", forcedColors: this._emulatedMedia.forcedColors !== void 0 ? this._emulatedMedia.forcedColors : contextOptions.forcedColors ?? "none", contrast: this._emulatedMedia.contrast !== void 0 ? this._emulatedMedia.contrast : contextOptions.contrast ?? "no-preference" }; } async setViewportSize(progress2, viewportSize) { const oldEmulatedSize = this._emulatedSize; try { this._setEmulatedSize({ viewport: { ...viewportSize }, screen: { ...viewportSize } }); await progress2.race(this.delegate.updateEmulatedViewportSize()); } catch (error) { this._emulatedSize = oldEmulatedSize; this.delegate.updateEmulatedViewportSize().catch(() => { }); throw error; } } setEmulatedSizeFromWindowOpen(emulatedSize) { this._setEmulatedSize(emulatedSize); } _setEmulatedSize(emulatedSize) { this._emulatedSize = emulatedSize; this.emit(_Page.Events.EmulatedSizeChanged); } emulatedSize() { if (this._emulatedSize) return this._emulatedSize; const contextOptions = this.browserContext._options; return contextOptions.viewport ? { viewport: contextOptions.viewport, screen: contextOptions.screen || contextOptions.viewport } : void 0; } async bringToFront(progress2) { await progress2.race(this.delegate.bringToFront()); } async addInitScript(progress2, source11) { return await progress2.race(this._addInitScript(source11)); } async _addInitScript(source11) { const initScript = new InitScript(this, source11); this.initScripts.push(initScript); try { await this.delegate.addInitScript(initScript); } catch (error) { initScript.dispose().catch(() => { }); throw error; } return initScript; } async removeInitScript(initScript) { this.initScripts = this.initScripts.filter((script) => initScript !== script); await this.delegate.removeInitScripts([initScript]); } needsRequestInterception() { return this.requestInterceptors.length > 0 || this.browserContext.requestInterceptors.length > 0; } async addRequestInterceptor(progress2, handler, prepend) { if (prepend) this.requestInterceptors.unshift(handler); else this.requestInterceptors.push(handler); await progress2.race(this.delegate.updateRequestInterception()); } async removeRequestInterceptor(handler) { const index = this.requestInterceptors.indexOf(handler); if (index === -1) return; this.requestInterceptors.splice(index, 1); await this.browserContext.notifyRoutesInFlightAboutRemovedHandler(handler); await this.delegate.updateRequestInterception(); } async expectScreenshot(progress2, options) { const locator2 = options.locator; const rafrafScreenshot = locator2 ? async (progress3, timeout) => { return await locator2.frame.rafrafTimeoutScreenshotElementWithProgress(progress3, locator2.selector, timeout, options || {}); } : async (progress3, timeout) => { await this.performActionPreChecks(progress3); await this.mainFrame().rafrafTimeout(progress3, timeout); return await this.screenshotter.screenshotPage(progress3, options || {}); }; const comparator = getComparator("image/png"); let intermediateResult; const areEqualScreenshots = (actual, expected, previous) => { const comparatorResult = actual && expected ? comparator(actual, expected, options) : void 0; if (comparatorResult !== void 0 && !!comparatorResult === !!options.isNot) return true; if (comparatorResult) intermediateResult = { errorMessage: comparatorResult.errorMessage, diff: comparatorResult.diff, actual, previous }; return false; }; try { if (!options.expected && options.isNot) throw new Error('"not" matcher requires expected result'); const format2 = validateScreenshotOptions(options || {}); if (format2 !== "png") throw new Error("Only PNG screenshots are supported"); let actual; let previous; const pollIntervals = [0, 100, 250, 500]; if (options.expected) progress2.log(` verifying given screenshot expectation`); else progress2.log(` generating new stable screenshot expectation`); let isFirstIteration = true; while (true) { if (this.isClosed()) throw new Error("The page has closed"); const screenshotTimeout = pollIntervals.shift() ?? 1e3; if (screenshotTimeout) progress2.log(`waiting ${screenshotTimeout}ms before taking screenshot`); previous = actual; actual = await rafrafScreenshot(progress2, screenshotTimeout).catch((e) => { if (this.mainFrame().isNonRetriableError(e)) throw e; progress2.log(`failed to take screenshot - ` + e.message); return void 0; }); if (!actual) continue; const expectation = options.expected && isFirstIteration ? options.expected : previous; if (areEqualScreenshots(actual, expectation, previous)) break; if (intermediateResult) progress2.log(intermediateResult.errorMessage); isFirstIteration = false; } if (!isFirstIteration) progress2.log(`captured a stable screenshot`); if (!options.expected) return { actual }; if (isFirstIteration) { progress2.log(`screenshot matched expectation`); return {}; } if (areEqualScreenshots(actual, options.expected, void 0)) { progress2.log(`screenshot matched expectation`); return {}; } throw new Error(intermediateResult.errorMessage); } catch (e) { if (isJavaScriptErrorInEvaluate(e) || isInvalidSelectorError(e)) throw e; let errorMessage = e.message; if (e instanceof TimeoutError && intermediateResult?.previous) errorMessage = `Failed to take two consecutive stable screenshots.`; const details = { log: compressCallLog(e.message ? [...progress2.metadata.log, e.message] : progress2.metadata.log), actual: intermediateResult?.actual, previous: intermediateResult?.previous, diff: intermediateResult?.diff, timedOut: e instanceof TimeoutError, customErrorMessage: errorMessage }; const error = new Error("Expect failed"); error.details = details; throw error; } } async screenshot(progress2, options) { return await this.screenshotter.screenshotPage(progress2, options); } async close(progress2, options = {}) { await progress2.race(this._close(options)); } async _close(options = {}) { if (this._closedState === "closed") return; if (options.reason) this._closeReason = options.reason; await this.screencast.handlePageOrContextClose(); if (this._closedState !== "closing") { this._closedState = "closing"; await this.delegate.closePage(false).catch((e) => debugLogger.log("error", e)); } await this.closedPromise; } async runBeforeUnload(progress2) { await progress2.race(this._runBeforeUnload()); } async _runBeforeUnload() { await this.delegate.closePage(true).catch((e) => debugLogger.log("error", e)); } isClosed() { return this._closedState === "closed"; } hasCrashed() { return this._crashed; } isClosedOrClosingOrCrashed() { return this._closedState !== "open" || this._crashed; } addWorker(workerId, worker) { this._workers.set(workerId, worker); this.emit(_Page.Events.Worker, worker); } removeWorker(workerId) { const worker = this._workers.get(workerId); if (!worker) return; worker.didClose(); this._workers.delete(workerId); } clearWorkers() { for (const [workerId, worker] of this._workers) { worker.didClose(); this._workers.delete(workerId); } } async setFileChooserInterceptedBy(progress2, enabled, by) { await progress2.race(this._setFileChooserInterceptedBy(enabled, by)); } async _setFileChooserInterceptedBy(enabled, by) { const wasIntercepted = this.fileChooserIntercepted(); if (enabled) this._fileChooserInterceptedBy.add(by); else this._fileChooserInterceptedBy.delete(by); if (wasIntercepted !== this.fileChooserIntercepted()) await this.delegate.updateFileChooserInterception(); } fileChooserIntercepted() { return this._fileChooserInterceptedBy.size > 0; } frameNavigatedToNewDocument(frame) { this.emit(_Page.Events.InternalFrameNavigatedToNewDocument, frame); this.browserContext.emit(BrowserContext.Events.InternalFrameNavigatedToNewDocument, frame); const origin = frame.origin(); if (origin) this.browserContext.addVisitedOrigin(origin); if (frame === this.mainFrame()) { if (this._consoleMessages.length > 0) this._consoleMessages[this._consoleMessages.length - 1][navigationMarkSymbol] = true; if (this._pageErrors.length > 0) this._pageErrors[this._pageErrors.length - 1][navigationMarkSymbol] = true; } } allInitScripts() { const bindings = [...this.browserContext._pageBindings.values(), ...this._pageBindings.values()].map((binding) => binding.initScript); if (this.browserContext.bindingsInitScript) bindings.unshift(this.browserContext.bindingsInitScript); return [...bindings, ...this.browserContext.initScripts, ...this.initScripts]; } getBinding(name) { return this._pageBindings.get(name) || this.browserContext._pageBindings.get(name); } async safeNonStallingEvaluateInAllFrames(expression2, world, options = {}) { await Promise.all(this.frames().map(async (frame) => { try { await frame.nonStallingEvaluateInExistingContext(expression2, world); } catch (e) { if (options.throwOnJSErrors && isJavaScriptErrorInEvaluate(e)) throw e; } })); } async hideHighlight() { await Promise.all(this.frames().map((frame) => frame.hideHighlight().catch(() => { }))); } async setDockTile(image) { await this.delegate.setDockTile(image); } async webStorageItems(progress2, kind) { const storage = `${kind}Storage`; return await this.mainFrame().evaluateExpression(progress2, `(() => { const result = []; for (let i = 0; i < ${storage}.length; i++) { const name = ${storage}.key(i); if (name !== null) result.push({ name, value: ${storage}.getItem(name) ?? '' }); } return result; })()`, { world: "utility" }); } async webStorageGetItem(progress2, kind, name) { const value2 = await this.mainFrame().evaluateExpression(progress2, `${kind}Storage.getItem(${JSON.stringify(name)})`, { world: "utility" }); return value2 === null ? void 0 : value2; } async webStorageSetItem(progress2, kind, name, value2) { await this.mainFrame().evaluateExpression(progress2, `${kind}Storage.setItem(${JSON.stringify(name)}, ${JSON.stringify(value2)})`, { world: "utility" }); } async webStorageRemoveItem(progress2, kind, name) { await this.mainFrame().evaluateExpression(progress2, `${kind}Storage.removeItem(${JSON.stringify(name)})`, { world: "utility" }); } async webStorageClear(progress2, kind) { await this.mainFrame().evaluateExpression(progress2, `${kind}Storage.clear()`, { world: "utility" }); } }; WorkerEvent = { Console: "console", Close: "close" }; Worker = class _Worker extends SdkObject { constructor(parent, url2, onDisconnect) { super(parent, "worker"); this._executionContextPromise = new ManualPromise(); this._workerScriptLoaded = false; this.existingExecutionContext = null; this.openScope = new LongStandingScope(); this.attribution.worker = this; this.url = url2; this._onDisconnect = onDisconnect; } static { this.Events = WorkerEvent; } createExecutionContext(delegate) { this.existingExecutionContext = new ExecutionContext(this, delegate, "worker"); if (this._workerScriptLoaded) this._executionContextPromise.resolve(this.existingExecutionContext); return this.existingExecutionContext; } destroyExecutionContext(errorMessage) { if (this.existingExecutionContext) this.existingExecutionContext.contextDestroyed(errorMessage); this.existingExecutionContext = null; this._workerScriptLoaded = false; this._executionContextPromise = new ManualPromise(); } workerScriptLoaded() { this._workerScriptLoaded = true; if (this.existingExecutionContext) this._executionContextPromise.resolve(this.existingExecutionContext); } didClose() { if (this.existingExecutionContext) this.existingExecutionContext.contextDestroyed("Worker was closed"); this.emit(_Worker.Events.Close, this); this.openScope.close(new Error("Worker closed")); } async evaluateExpression(progress2, expression2, isFunction2, arg) { return progress2.race(evaluateExpression(await this._executionContextPromise, expression2, { returnByValue: true, isFunction: isFunction2 }, arg)); } async evaluateExpressionHandle(progress2, expression2, isFunction2, arg) { return progress2.race(evaluateExpression(await this._executionContextPromise, expression2, { returnByValue: false, isFunction: isFunction2 }, arg)); } async disconnect(progress2, options = {}) { if (!this._onDisconnect) throw new Error("Cannot disconnect from this worker"); this._closeReason = options.reason; await progress2.race(this._onDisconnect()); } }; PageBinding = class _PageBinding extends DisposableObject { static { this.kController = "__playwright__binding__controller__"; } static { this.kBindingName = "__playwright__binding__"; } static createInitScript(browserContext) { return new InitScript(browserContext, ` (() => { const module = {}; ${source5} const property = '${_PageBinding.kController}'; if (!globalThis[property]) globalThis[property] = new (module.exports.BindingsController())(globalThis, '${_PageBinding.kBindingName}'); })(); `); } constructor(parent, name, playwrightFunction) { super(parent); this.name = name; this.playwrightFunction = playwrightFunction; this.initScript = new InitScript(parent, `globalThis['${_PageBinding.kController}'].addBinding(${JSON.stringify(name)})`); this.cleanupScript = `globalThis['${_PageBinding.kController}'].removeBinding(${JSON.stringify(name)})`; } static async dispatch(page, payload, context2) { const { name, seq, serializedArgs } = JSON.parse(payload); try { assert(context2.world); const binding = page.getBinding(name); if (!binding) throw new Error(`Function "${name}" is not exposed`); if (!Array.isArray(serializedArgs)) throw new Error(`serializedArgs is not an array. This can happen when Array.prototype.toJSON is defined incorrectly`); const args = serializedArgs.map((a) => parseEvaluationResultValue(a)); const result2 = await binding.playwrightFunction({ frame: context2.frame, page, context: page.browserContext }, ...args); context2.evaluateExpressionHandle(`arg => globalThis['${_PageBinding.kController}'].deliverBindingResult(arg)`, { isFunction: true }, { name, seq, result: result2 }).catch((e) => debugLogger.log("error", e)); } catch (error) { context2.evaluateExpressionHandle(`arg => globalThis['${_PageBinding.kController}'].deliverBindingResult(arg)`, { isFunction: true }, { name, seq, error }).catch((e) => debugLogger.log("error", e)); } } async dispose() { await this.parent.removeExposedBinding(this); } }; InitScript = class extends DisposableObject { constructor(owner, source11) { super(owner); this.source = `(() => { ${source11} })();`; } async dispose() { await this.parent.removeInitScript(this); } }; } }); // packages/playwright-core/src/server/types.ts var kLifecycleEvents; var init_types = __esm({ "packages/playwright-core/src/server/types.ts"() { "use strict"; kLifecycleEvents = /* @__PURE__ */ new Set(["load", "domcontentloaded", "networkidle", "commit"]); } }); // packages/playwright-core/src/server/frames.ts function verifyLifecycle(name, waitUntil) { if (waitUntil === "networkidle0") waitUntil = "networkidle"; if (!kLifecycleEvents.has(waitUntil)) throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle|commit)`); return waitUntil; } function renderUnexpectedValue(expression2, received) { if (expression2 === "to.match.aria") return received ? received.raw : received; return received; } var yaml, NavigationAbortedError, ExpectError, kDummyFrameId, FrameManager, FrameEvent, Frame, SignalBarrier; var init_frames = __esm({ "packages/playwright-core/src/server/frames.ts"() { "use strict"; init_ariaSnapshot(); init_selectorParser(); init_manualPromise(); init_eventsHelper(); init_manualPromise(); init_locatorGenerators(); init_assert(); init_urlMatch(); init_task(); init_crypto(); init_browserContext(); init_dom(); init_errors(); init_fileUploadUtils(); init_frameSelectors(); init_helper(); init_instrumentation(); init_javascript(); init_network2(); init_page(); init_progress(); init_types(); init_protocolError(); yaml = require("./utilsBundle").yaml; NavigationAbortedError = class extends Error { constructor(documentId, message) { super(message); this.documentId = documentId; } }; ExpectError = class extends Error { constructor(details) { super("Expect failed"); this.name = "ExpectError"; this.details = details; } }; kDummyFrameId = ""; FrameManager = class { constructor(page) { this._frames = /* @__PURE__ */ new Map(); this._consoleMessageTags = /* @__PURE__ */ new Map(); this._signalBarriers = /* @__PURE__ */ new Set(); this._webSockets = /* @__PURE__ */ new Map(); this._nextFrameSeq = 0; this._page = page; this._mainFrame = void 0; } _allocateFrameSeq() { return this._nextFrameSeq++; } createDummyMainFrameIfNeeded() { if (!this._mainFrame) this.frameAttached(kDummyFrameId, null); } dispose() { for (const frame of this._frames.values()) { frame._stopNetworkIdleTimer(); frame.invalidateNonStallingEvaluations("Target crashed"); } } mainFrame() { return this._mainFrame; } frames() { const frames = []; collect(this._mainFrame); return frames; function collect(frame) { frames.push(frame); for (const subframe of frame._getChildFrames()) collect(subframe); } } frame(frameId) { return this._frames.get(frameId) || null; } frameAttached(frameId, parentFrameId) { const parentFrame = parentFrameId ? this._frames.get(parentFrameId) : null; if (!parentFrame) { if (this._mainFrame) { this._frames.delete(this._mainFrame._id); this._mainFrame._id = frameId; } else { assert(!this._frames.has(frameId)); this._mainFrame = new Frame(this._page, frameId, parentFrame); } this._frames.set(frameId, this._mainFrame); return this._mainFrame; } else { assert(!this._frames.has(frameId)); const frame = new Frame(this._page, frameId, parentFrame); this._frames.set(frameId, frame); this._page.emit(Page.Events.FrameAttached, frame); this._page.browserContext.emit(BrowserContext.Events.FrameAttached, frame); return frame; } } async waitForSignalsCreatedBy(progress2, waitAfter, action) { if (!waitAfter) return action(progress2); const barrier = new SignalBarrier(progress2); this._signalBarriers.add(barrier); try { const result2 = await action(progress2); await progress2.race(this._page.delegate.inputActionEpilogue()); await barrier.waitFor(progress2); await new Promise(makeWaitForNextTask()); return result2; } finally { this._signalBarriers.delete(barrier); } } frameWillPotentiallyRequestNavigation() { for (const barrier of this._signalBarriers) barrier.retain(); } frameDidPotentiallyRequestNavigation() { for (const barrier of this._signalBarriers) barrier.release(); } frameRequestedNavigation(frameId, documentId) { const frame = this._frames.get(frameId); if (!frame) return; for (const barrier of this._signalBarriers) barrier.addFrameNavigation(frame); if (frame.pendingDocument() && frame.pendingDocument().documentId === documentId) { return; } const request2 = documentId ? Array.from(frame._inflightRequests).find((request3) => request3._documentId === documentId) : void 0; frame._setPendingDocument({ documentId, request: request2 }); } frameCommittedNewDocumentNavigation(frameId, url2, name, documentId, initial) { const frame = this._frames.get(frameId); this.removeChildFramesRecursively(frame); this._clearWebSockets(frame); frame._url = url2; frame._name = name; let keepPending; const pendingDocument = frame.pendingDocument(); if (pendingDocument) { if (pendingDocument.documentId === void 0) { pendingDocument.documentId = documentId; } if (pendingDocument.documentId === documentId) { frame._currentDocument = pendingDocument; } else { keepPending = pendingDocument; frame._currentDocument = { documentId, request: void 0 }; } frame._setPendingDocument(void 0); } else { frame._currentDocument = { documentId, request: void 0 }; } frame._onClearLifecycle(); const navigationEvent = { url: url2, name, newDocument: frame._currentDocument, isPublic: true }; this._fireInternalFrameNavigation(frame, navigationEvent); if (!initial) { frame.apiLog(` navigated to "${url2}"`); this._page.frameNavigatedToNewDocument(frame); } frame._setPendingDocument(keepPending); } frameCommittedSameDocumentNavigation(frameId, url2) { const frame = this._frames.get(frameId); if (!frame) return; const pending = frame.pendingDocument(); if (pending && pending.documentId === void 0 && pending.request === void 0) { frame._setPendingDocument(void 0); } frame._url = url2; const navigationEvent = { url: url2, name: frame._name, isPublic: true }; this._fireInternalFrameNavigation(frame, navigationEvent); frame.apiLog(` navigated to "${url2}"`); } frameAbortedNavigation(frameId, errorText, documentId) { const frame = this._frames.get(frameId); if (!frame || !frame.pendingDocument()) return; if (documentId !== void 0 && frame.pendingDocument().documentId !== documentId) return; const navigationEvent = { url: frame._url, name: frame._name, newDocument: frame.pendingDocument(), error: new NavigationAbortedError(documentId, errorText), isPublic: !(documentId && frame._redirectedNavigations.has(documentId)) }; frame._setPendingDocument(void 0); this._fireInternalFrameNavigation(frame, navigationEvent); } frameDetached(frameId) { const frame = this._frames.get(frameId); if (frame) { this._removeFramesRecursively(frame); this._page.mainFrame()._recalculateNetworkIdle(); } } frameLifecycleEvent(frameId, event) { const frame = this._frames.get(frameId); if (frame) frame.onLifecycleEvent(event); } requestStarted(request2, route2) { const frame = request2.frame(); this._inflightRequestStarted(request2); if (request2._documentId) frame._setPendingDocument({ documentId: request2._documentId, request: request2 }); if (request2._isFavicon) { route2?.abort("aborted").catch(() => { }); return; } this._page.addNetworkRequest(request2); this._page.emitOnContext(BrowserContext.Events.Request, request2); if (route2) new Route(request2, route2).handle([...this._page.requestInterceptors, ...this._page.browserContext.requestInterceptors]); } requestReceivedResponse(response2) { if (response2.request()._isFavicon) return; this._page.emitOnContext(BrowserContext.Events.Response, response2); } reportRequestFinished(request2, response2) { this._inflightRequestFinished(request2); if (request2._isFavicon) return; this._page.emitOnContext(BrowserContext.Events.RequestFinished, { request: request2, response: response2 }); } requestFailed(request2, canceled) { const frame = request2.frame(); this._inflightRequestFinished(request2); if (frame.pendingDocument() && frame.pendingDocument().request === request2) { let errorText = request2.failure().errorText; if (canceled) errorText += "; maybe frame was detached?"; this.frameAbortedNavigation(frame._id, errorText, frame.pendingDocument().documentId); } if (request2._isFavicon) return; this._page.emitOnContext(BrowserContext.Events.RequestFailed, request2); } removeChildFramesRecursively(frame) { for (const child of frame._getChildFrames()) this._removeFramesRecursively(child); } _removeFramesRecursively(frame) { this.removeChildFramesRecursively(frame); frame._onDetached(); this._frames.delete(frame._id); if (!this._page.isClosed()) this._page.emit(Page.Events.FrameDetached, frame); } _inflightRequestFinished(request2) { const frame = request2.frame(); if (request2._isFavicon) return; if (!frame._inflightRequests.has(request2)) return; frame._inflightRequests.delete(request2); if (frame._inflightRequests.size === 0) frame._startNetworkIdleTimer(); } _inflightRequestStarted(request2) { const frame = request2.frame(); if (request2._isFavicon) return; frame._inflightRequests.add(request2); if (frame._inflightRequests.size === 1) frame._stopNetworkIdleTimer(); } interceptConsoleMessage(message) { if (message.type() !== "debug") return false; const tag = message.text(); const handler = this._consoleMessageTags.get(tag); if (!handler) return false; this._consoleMessageTags.delete(tag); handler(); return true; } _clearWebSockets(frame) { if (frame.parentFrame()) return; this._webSockets.clear(); } onWebSocketCreated(requestId, url2) { const ws4 = new WebSocket(this._page, url2); this._webSockets.set(requestId, ws4); } onWebSocketRequest(requestId, headers, wallTimeMs) { const ws4 = this._webSockets.get(requestId); if (!ws4) return; ws4.setWallTimeMs(wallTimeMs); if (ws4.markAsNotified()) { this._page.emit(Page.Events.WebSocket, ws4); this._page.browserContext.emit(BrowserContext.Events.WebSocket, ws4, this._page); } ws4.requestSent(headers); } onWebSocketResponse(requestId, status, statusText2, headers) { const ws4 = this._webSockets.get(requestId); if (!ws4) return; ws4.responseReceived(status, statusText2, headers); if (status >= 400) ws4.error(`${statusText2}: ${status}`); } onWebSocketFrameSent(requestId, opcode, data, wallTimeMs) { const ws4 = this._webSockets.get(requestId); if (ws4) ws4.frameSent(opcode, data, wallTimeMs); } webSocketFrameReceived(requestId, opcode, data, wallTimeMs) { const ws4 = this._webSockets.get(requestId); if (ws4) ws4.frameReceived(opcode, data, wallTimeMs); } webSocketClosed(requestId) { const ws4 = this._webSockets.get(requestId); if (ws4) { if (ws4.markAsNotified()) { this._page.emit(Page.Events.WebSocket, ws4); this._page.browserContext.emit(BrowserContext.Events.WebSocket, ws4, this._page); } ws4.closed(); } this._webSockets.delete(requestId); } webSocketError(requestId, errorMessage) { const ws4 = this._webSockets.get(requestId); if (ws4) { if (ws4.markAsNotified()) { this._page.emit(Page.Events.WebSocket, ws4); this._page.browserContext.emit(BrowserContext.Events.WebSocket, ws4, this._page); } ws4.error(errorMessage); } } _fireInternalFrameNavigation(frame, event) { frame.emit(Frame.Events.InternalNavigation, event); } }; FrameEvent = { InternalNavigation: "internalnavigation", AddLifecycle: "addlifecycle", RemoveLifecycle: "removelifecycle" }; Frame = class _Frame extends SdkObject { constructor(page, id, parentFrame) { super(page, "frame"); this._firedLifecycleEvents = /* @__PURE__ */ new Set(); this._firedNetworkIdleSelf = false; this._url = ""; this._contextData = /* @__PURE__ */ new Map(); this._childFrames = /* @__PURE__ */ new Set(); this._name = ""; this._inflightRequests = /* @__PURE__ */ new Set(); this._detachedScope = new LongStandingScope(); this._raceAgainstEvaluationStallingEventsPromises = /* @__PURE__ */ new Set(); this._redirectedNavigations = /* @__PURE__ */ new Map(); this.attribution.frame = this; this.seq = page.frameManager._allocateFrameSeq(); this._id = id; this._page = page; this._parentFrame = parentFrame; this._currentDocument = { documentId: void 0, request: void 0 }; this.selectors = new FrameSelectors(this); this._contextData.set("main", { contextPromise: new ManualPromise(), context: null }); this._contextData.set("utility", { contextPromise: new ManualPromise(), context: null }); this._setContext("main", null); this._setContext("utility", null); if (this._parentFrame) this._parentFrame._childFrames.add(this); this._firedLifecycleEvents.add("commit"); if (id !== kDummyFrameId) this._startNetworkIdleTimer(); } static { this.Events = FrameEvent; } _isDetached() { return this._detachedScope.isClosed(); } onLifecycleEvent(event) { if (this._firedLifecycleEvents.has(event)) return; this._firedLifecycleEvents.add(event); this.emit(_Frame.Events.AddLifecycle, event); if (this === this._page.mainFrame() && this._url !== "about:blank") this.apiLog(` "${event}" event fired`); this._page.mainFrame()._recalculateNetworkIdle(); } _onClearLifecycle() { for (const event of this._firedLifecycleEvents) this.emit(_Frame.Events.RemoveLifecycle, event); this._firedLifecycleEvents.clear(); this._inflightRequests = new Set(Array.from(this._inflightRequests).filter((request2) => request2 === this._currentDocument.request)); this._stopNetworkIdleTimer(); if (this._inflightRequests.size === 0) this._startNetworkIdleTimer(); this._page.mainFrame()._recalculateNetworkIdle(this); this.onLifecycleEvent("commit"); } _setPendingDocument(documentInfo) { this._pendingDocument = documentInfo; if (documentInfo) this.invalidateNonStallingEvaluations("Navigation interrupted the evaluation"); } pendingDocument() { return this._pendingDocument; } invalidateNonStallingEvaluations(message) { if (!this._raceAgainstEvaluationStallingEventsPromises.size) return; const error = new Error(message); for (const promise of this._raceAgainstEvaluationStallingEventsPromises) promise.reject(error); } async raceAgainstEvaluationStallingEvents(cb) { if (this._pendingDocument) throw new Error("Frame is currently attempting a navigation"); if (this._page.browserContext.dialogManager.hasOpenDialogsForPage(this._page)) throw new Error("Open JavaScript dialog prevents evaluation"); const promise = new ManualPromise(); this._raceAgainstEvaluationStallingEventsPromises.add(promise); try { return await Promise.race([ cb(), promise ]); } finally { this._raceAgainstEvaluationStallingEventsPromises.delete(promise); } } nonStallingRawEvaluateInExistingMainContext(expression2) { return this.raceAgainstEvaluationStallingEvents(() => { const context2 = this._existingMainContext(); if (!context2) throw new Error("Frame does not yet have a main execution context"); return context2.rawEvaluateJSON(expression2); }); } nonStallingEvaluateInExistingContext(expression2, world) { return this.raceAgainstEvaluationStallingEvents(() => { const context2 = this._contextData.get(world)?.context; if (!context2) throw new Error("Frame does not yet have the execution context"); return context2.evaluateExpression(expression2, { isFunction: false }); }); } _recalculateNetworkIdle(frameThatAllowsRemovingNetworkIdle) { let isNetworkIdle = this._firedNetworkIdleSelf; for (const child of this._childFrames) { child._recalculateNetworkIdle(frameThatAllowsRemovingNetworkIdle); if (!child._firedLifecycleEvents.has("networkidle")) isNetworkIdle = false; } if (isNetworkIdle && !this._firedLifecycleEvents.has("networkidle")) { this._firedLifecycleEvents.add("networkidle"); this.emit(_Frame.Events.AddLifecycle, "networkidle"); if (this === this._page.mainFrame() && this._url !== "about:blank") this.apiLog(` "networkidle" event fired`); } if (frameThatAllowsRemovingNetworkIdle !== this && this._firedLifecycleEvents.has("networkidle") && !isNetworkIdle) { this._firedLifecycleEvents.delete("networkidle"); this.emit(_Frame.Events.RemoveLifecycle, "networkidle"); } } async raceNavigationAction(progress2, action) { progress2.setAllowConcurrentOrNestedRaces(true); const result2 = await progress2.race(LongStandingScope.raceMultiple([ this._detachedScope, this._page.openScope ], action().catch((e) => { if (e instanceof NavigationAbortedError && e.documentId) { const data = this._redirectedNavigations.get(e.documentId); if (data) { progress2.log(`waiting for redirected navigation to "${data.url}"`); return progress2.race(data.gotoPromise); } } throw e; }))); progress2.setAllowConcurrentOrNestedRaces(false); return result2; } redirectNavigation(url2, documentId, referer) { const controller = new ProgressController(); const data = { url: url2, gotoPromise: controller.run((progress2) => this.gotoImpl(progress2, url2, { referer }), 0) }; this._redirectedNavigations.set(documentId, data); data.gotoPromise.finally(() => this._redirectedNavigations.delete(documentId)); } async goto(progress2, url2, options = {}) { const constructedNavigationURL = constructURLBasedOnBaseURL(this._page.browserContext._options.baseURL, url2); return this.raceNavigationAction(progress2, async () => this.gotoImpl(progress2, constructedNavigationURL, options)); } async gotoImpl(progress2, url2, options) { const waitUntil = verifyLifecycle("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil); progress2.log(`navigating to "${url2}", waiting until "${waitUntil}"`); const headers = this._page.extraHTTPHeaders() || []; const refererHeader = headers.find((h) => h.name.toLowerCase() === "referer"); let referer = refererHeader ? refererHeader.value : void 0; if (options.referer !== void 0) { if (referer !== void 0 && referer !== options.referer) throw new Error('"referer" is already specified as extra HTTP header'); referer = options.referer; } url2 = helper.completeUserURL(url2); const navigationEvents = []; const collectNavigations = (arg) => navigationEvents.push(arg); this.on(_Frame.Events.InternalNavigation, collectNavigations); let navigateResult; try { navigateResult = await progress2.race(this._page.delegate.navigateFrame(this, url2, referer)); } finally { this.off(_Frame.Events.InternalNavigation, collectNavigations); } let event; if (navigateResult.newDocumentId) { const predicate = (event2) => { return event2.newDocument && (event2.newDocument.documentId === navigateResult.newDocumentId || !event2.error); }; const events = navigationEvents.filter(predicate); if (events.length) event = events[0]; else event = await helper.waitForEvent(progress2, this, _Frame.Events.InternalNavigation, predicate).promise; if (event.newDocument.documentId !== navigateResult.newDocumentId) { throw new NavigationAbortedError(navigateResult.newDocumentId, `Navigation to "${url2}" is interrupted by another navigation to "${event.url}"`); } if (event.error) throw event.error; } else { const predicate = (e) => !e.newDocument; const events = navigationEvents.filter(predicate); if (events.length) event = events[0]; else event = await helper.waitForEvent(progress2, this, _Frame.Events.InternalNavigation, predicate).promise; } if (!this._firedLifecycleEvents.has(waitUntil)) await helper.waitForEvent(progress2, this, _Frame.Events.AddLifecycle, (e) => e === waitUntil).promise; const request2 = event.newDocument ? event.newDocument.request : void 0; const response2 = request2 ? await request2._finalRequest().response(progress2) : null; return response2; } async waitForNavigation(progress2, requiresNewDocument, options) { const waitUntil = verifyLifecycle("waitUntil", options.waitUntil === void 0 ? "load" : options.waitUntil); progress2.log(`waiting for navigation until "${waitUntil}"`); const navigationEvent = await helper.waitForEvent(progress2, this, _Frame.Events.InternalNavigation, (event) => { if (event.error) return true; if (requiresNewDocument && !event.newDocument) return false; progress2.log(` navigated to "${this._url}"`); return true; }).promise; if (navigationEvent.error) throw navigationEvent.error; if (!this._firedLifecycleEvents.has(waitUntil)) await helper.waitForEvent(progress2, this, _Frame.Events.AddLifecycle, (e) => e === waitUntil).promise; const request2 = navigationEvent.newDocument ? navigationEvent.newDocument.request : void 0; return request2 ? request2._finalRequest().response(progress2) : null; } async waitForLoadState(progress2, state) { const waitUntil = verifyLifecycle("state", state); if (!this._firedLifecycleEvents.has(waitUntil)) await helper.waitForEvent(progress2, this, _Frame.Events.AddLifecycle, (e) => e === waitUntil).promise; } async frameElement(progress2) { return await progress2.race(this._page.delegate.getFrameElement(this)); } context(world) { if (this._page.delegate.noUtilityWorld?.()) world = "main"; return this._contextData.get(world).contextPromise.then((contextOrDestroyedReason) => { if (contextOrDestroyedReason instanceof ExecutionContext) return contextOrDestroyedReason; throw new Error(contextOrDestroyedReason.destroyedReason); }); } mainContext() { return this.context("main"); } _existingMainContext() { return this._contextData.get("main")?.context || null; } utilityContext() { return this.context("utility"); } async evaluateExpression(progress2, expression2, options = {}, arg) { return await progress2.race(this._evaluateExpression(expression2, options, arg)); } async _evaluateExpression(expression2, options = {}, arg) { const context2 = await this.context(options.world ?? "main"); const value2 = await context2.evaluateExpression(expression2, options, arg); return value2; } async evaluateExpressionHandle(progress2, expression2, options = {}, arg) { return await progress2.race(this._evaluateExpressionHandle(expression2, options, arg)); } async _evaluateExpressionHandle(expression2, options = {}, arg) { const context2 = await this.context(options.world ?? "main"); const value2 = await context2.evaluateExpressionHandle(expression2, options, arg); return value2; } async querySelector(progress2, selector, options) { this.apiLog(` finding element using the selector "${selector}"`); return progress2.race(this.selectors.query(selector, options)); } async waitForSelector(progress2, selector, performActionPreChecksAndLog, options, scope) { if (options.visibility) throw new Error("options.visibility is not supported, did you mean options.state?"); if (options.waitFor && options.waitFor !== "visible") throw new Error("options.waitFor is not supported, did you mean options.state?"); const { state = "visible" } = options; if (!["attached", "detached", "visible", "hidden"].includes(state)) throw new Error(`state: expected one of (attached|detached|visible|hidden)`); if (performActionPreChecksAndLog) progress2.log(`waiting for ${this._asLocator(selector)}${state === "attached" ? "" : " to be " + state}`); const promise = this.retryWithProgressAndBackoff(progress2, async (progress3, continuePolling) => { if (performActionPreChecksAndLog) await this._page.performActionPreChecks(progress3); const resolved = await progress3.race(this.selectors.resolveInjectedForSelector(selector, options, scope)); if (!resolved) { if (state === "hidden" || state === "detached") return null; return continuePolling; } const result2 = await progress3.race(resolved.injected.evaluateHandle((injected, { info, root }) => { if (root && !root.isConnected) throw injected.createStacklessError("Element is not attached to the DOM"); const elements = injected.querySelectorAll(info.parsed, root || document); const element3 = elements[0]; const visible2 = element3 ? injected.utils.isElementVisible(element3) : false; let log3 = ""; if (elements.length > 1) { if (info.strict) throw injected.strictModeViolationError(info.parsed, elements); log3 = ` locator resolved to ${elements.length} elements. Proceeding with the first one: ${injected.previewNode(elements[0])}`; } else if (element3) { log3 = ` locator resolved to ${visible2 ? "visible" : "hidden"} ${injected.previewNode(element3)}`; } injected.checkDeprecatedSelectorUsage(info.parsed, elements); return { log: log3, element: element3, visible: visible2, attached: !!element3 }; }, { info: resolved.info, root: resolved.frame === this ? scope : void 0 })); const { log: log2, visible, attached } = await progress3.race(result2.evaluate((r) => ({ log: r.log, visible: r.visible, attached: r.attached }))); if (log2) progress3.log(log2); const success = { attached, detached: !attached, visible, hidden: !visible }[state]; if (!success) { result2.dispose(); return continuePolling; } if (options.omitReturnValue) { result2.dispose(); return null; } const element2 = state === "attached" || state === "visible" ? await progress3.race(result2.evaluateHandle((r) => r.element)) : null; result2.dispose(); if (!element2) return null; if (options.__testHookBeforeAdoptNode) await progress3.race(options.__testHookBeforeAdoptNode()); try { const mainContext = await progress3.race(resolved.frame.mainContext()); return await progress3.race(element2._adoptTo(mainContext)); } catch (e) { return continuePolling; } }); return scope ? scope._context.raceAgainstContextDestroyed(promise) : promise; } async dispatchEvent(progress2, selector, type3, eventInit = {}, options, scope) { await this._callOnElementOnceMatches(progress2, selector, (injectedScript, element2, data) => { injectedScript.dispatchEvent(element2, data.type, data.eventInit); }, { type: type3, eventInit }, { mainWorld: true, ...options }, scope); } async evalOnSelector(progress2, selector, strict, expression2, isFunction2, arg, scope) { return progress2.race(this._evalOnSelector(selector, strict, expression2, isFunction2, arg, scope)); } async _evalOnSelector(selector, strict, expression2, isFunction2, arg, scope) { const handle = await this.selectors.query(selector, { strict }, scope); if (!handle) throw new Error(`Failed to find element matching selector "${selector}"`); const result2 = await handle.internalEvaluateExpression(expression2, { isFunction: isFunction2 }, arg); handle.dispose(); return result2; } async evalOnSelectorAll(progress2, selector, expression2, isFunction2, arg, scope) { return progress2.race(this._evalOnSelectorAll(selector, expression2, isFunction2, arg, scope)); } async _evalOnSelectorAll(selector, expression2, isFunction2, arg, scope) { const arrayHandle = await this.selectors.queryArrayInMainWorld(selector, scope); const result2 = await arrayHandle.internalEvaluateExpression(expression2, { isFunction: isFunction2 }, arg); arrayHandle.dispose(); return result2; } async maskSelectors(selectors, color) { const context2 = await this.utilityContext(); const injectedScript = await context2.injectedScript(); await injectedScript.evaluate((injected, { parsed, color: color2 }) => { injected.maskSelectors(parsed, color2); }, { parsed: selectors, color }); } async querySelectorAll(progress2, selector) { return progress2.race(this.selectors.queryAll(selector)); } async queryCount(progress2, selector, options) { try { return await progress2.race(this.selectors.queryCount(selector, options)); } catch (e) { if (this.isNonRetriableError(e)) throw e; return 0; } } async content(progress2) { return progress2.race(this._content()); } async _content() { try { const context2 = await this.utilityContext(); return await context2.evaluate(() => { let retVal = ""; if (document.doctype) retVal = new XMLSerializer().serializeToString(document.doctype); if (document.documentElement) retVal += document.documentElement.outerHTML; return retVal; }); } catch (e) { if (this.isNonRetriableError(e)) throw e; throw new Error(`Unable to retrieve content because the page is navigating and changing the content.`); } } async setContent(progress2, html, options) { const tag = `--playwright--set--content--${createGuid()}--`; await this.raceNavigationAction(progress2, async () => { const waitUntil = options.waitUntil === void 0 ? "load" : options.waitUntil; progress2.log(`setting frame content, waiting until "${waitUntil}"`); const context2 = await progress2.race(this.utilityContext()); const tagPromise = new ManualPromise(); this._page.frameManager._consoleMessageTags.set(tag, () => { this._onClearLifecycle(); tagPromise.resolve(); }); progress2.setAllowConcurrentOrNestedRaces(true); const lifecyclePromise = progress2.race(tagPromise).then(() => this.waitForLoadState(progress2, waitUntil)); const contentPromise = progress2.race(context2.evaluate(({ html: html2, tag: tag2 }) => { document.open(); console.debug(tag2); document.write(html2); document.close(); }, { html, tag })); await Promise.all([contentPromise, lifecyclePromise]); progress2.setAllowConcurrentOrNestedRaces(false); return null; }).finally(() => { this._page.frameManager._consoleMessageTags.delete(tag); }); } name() { return this._name || ""; } url() { return this._url; } origin() { if (!this._url.startsWith("http")) return; return parseURL2(this._url)?.origin; } parentFrame() { return this._parentFrame; } _getChildFrames() { return Array.from(this._childFrames); } async addScriptTag(progress2, params2) { return await progress2.race(this._addScriptTag(params2)); } async _addScriptTag(params2) { const { url: url2 = null, content = null, type: type3 = "" } = params2; if (!url2 && !content) throw new Error("Provide an object with a `url`, `path` or `content` property"); const context2 = await this.mainContext(); return this._raceWithCSPError(async () => { if (url2 !== null) return (await context2.evaluateHandle(addScriptUrl, { url: url2, type: type3 })).asElement(); const result2 = (await context2.evaluateHandle(addScriptContent, { content, type: type3 })).asElement(); if (this._page.delegate.cspErrorsAsynchronousForInlineScripts) await context2.evaluate(() => true); return result2; }); async function addScriptUrl(params3) { const script = document.createElement("script"); script.src = params3.url; if (params3.type) script.type = params3.type; const promise = new Promise((res, rej) => { script.onload = res; script.onerror = (e) => rej(typeof e === "string" ? new Error(e) : new Error(`Failed to load script at ${script.src}`)); }); document.head.appendChild(script); await promise; return script; } function addScriptContent(params3) { const script = document.createElement("script"); script.type = params3.type || "text/javascript"; script.text = params3.content; let error = null; script.onerror = (e) => error = e; document.head.appendChild(script); if (error) throw error; return script; } } async addStyleTag(progress2, params2) { return await progress2.race(this._addStyleTag(params2)); } async _addStyleTag(params2) { const { url: url2 = null, content = null } = params2; if (!url2 && !content) throw new Error("Provide an object with a `url`, `path` or `content` property"); const context2 = await this.mainContext(); return this._raceWithCSPError(async () => { if (url2 !== null) return (await context2.evaluateHandle(addStyleUrl, url2)).asElement(); return (await context2.evaluateHandle(addStyleContent, content)).asElement(); }); async function addStyleUrl(url3) { const link = document.createElement("link"); link.rel = "stylesheet"; link.href = url3; const promise = new Promise((res, rej) => { link.onload = res; link.onerror = rej; }); document.head.appendChild(link); await promise; return link; } async function addStyleContent(content2) { const style = document.createElement("style"); style.type = "text/css"; style.appendChild(document.createTextNode(content2)); const promise = new Promise((res, rej) => { style.onload = res; style.onerror = rej; }); document.head.appendChild(style); await promise; return style; } } async _raceWithCSPError(func) { const listeners = []; let result2; let error; let cspMessage; const actionPromise = func().then((r) => result2 = r).catch((e) => error = e); const errorPromise = new Promise((resolve) => { listeners.push(eventsHelper.addEventListener(this._page.browserContext, BrowserContext.Events.Console, (message) => { if (message.page() !== this._page || message.type() !== "error") return; if (message.text().includes("Content-Security-Policy") || message.text().includes("Content Security Policy")) { cspMessage = message; resolve(); } })); }); await Promise.race([actionPromise, errorPromise]); eventsHelper.removeEventListeners(listeners); if (cspMessage) throw new Error(cspMessage.text()); if (error) throw error; return result2; } async retryWithProgressAndBackoff(progress2, action) { const backoffScale = [20, 50, 100, 100, 500]; if (progress2.timeout) { while (backoffScale.length && backoffScale[backoffScale.length - 1] > progress2.timeout / 5) backoffScale.pop(); } return await this.retryWithProgressAndTimeouts(progress2, backoffScale, action); } async retryWithProgressAndTimeouts(progress2, timeouts, action) { const continuePolling = Symbol("continuePolling"); timeouts = [0, ...timeouts]; let timeoutIndex = 0; while (true) { const timeout = timeouts[Math.min(timeoutIndex++, timeouts.length - 1)]; if (timeout) { const actionPromise = new Promise((f) => setTimeout(f, timeout)); await progress2.race(LongStandingScope.raceMultiple([ this._page.openScope, this._detachedScope ], actionPromise)); } try { const result2 = await action(progress2, continuePolling); if (result2 === continuePolling) continue; return result2; } catch (e) { if (this.isNonRetriableError(e)) throw e; continue; } } } isNonRetriableError(e) { if (isAbortError(e)) return true; if (isJavaScriptErrorInEvaluate(e) || isSessionClosedError(e)) return true; if (isNonRecoverableDOMError(e) || isInvalidSelectorError(e)) return true; if (this._isDetached()) return true; return false; } async _retryWithProgressIfNotConnected(progress2, selector, options, action) { progress2.log(`waiting for ${this._asLocator(selector)}`); const noAutoWaiting = options.__testHookNoAutoWaiting ?? options.noAutoWaiting; const performActionPreChecks = (options.performActionPreChecks ?? !options.force) && !noAutoWaiting; return this.retryWithProgressAndBackoff(progress2, async (progress3, continuePolling) => { if (performActionPreChecks) await this._page.performActionPreChecks(progress3); const resolved = await progress3.race(this.selectors.resolveInjectedForSelector(selector, { strict: options.strict })); if (!resolved) { if (noAutoWaiting) throw new NonRecoverableDOMError("Element(s) not found"); return continuePolling; } const result2 = await progress3.race(resolved.injected.evaluateHandle((injected, { info }) => { const elements = injected.querySelectorAll(info.parsed, document); injected.markTargetElements(new Set(elements)); const element3 = elements[0]; let log3 = ""; if (elements.length > 1) { if (info.strict) throw injected.strictModeViolationError(info.parsed, elements); log3 = ` locator resolved to ${elements.length} elements. Proceeding with the first one: ${injected.previewNode(elements[0])}`; } else if (element3) { log3 = ` locator resolved to ${injected.previewNode(element3)}`; } injected.checkDeprecatedSelectorUsage(info.parsed, elements); return { log: log3, success: !!element3, element: element3 }; }, { info: resolved.info })); const { log: log2, success } = await progress3.race(result2.evaluate((r) => ({ log: r.log, success: r.success }))); if (log2) progress3.log(log2); if (!success) { if (noAutoWaiting) throw new NonRecoverableDOMError("Element(s) not found"); result2.dispose(); return continuePolling; } const element2 = await progress3.race(result2.evaluateHandle((r) => r.element)); result2.dispose(); try { const result3 = await action(progress3, element2); if (result3 === "error:notconnected") { if (noAutoWaiting) throw new NonRecoverableDOMError("Element is not attached to the DOM"); progress3.log("element was detached from the DOM, retrying"); return continuePolling; } return result3; } finally { element2?.dispose(); } }); } async rafrafTimeoutScreenshotElementWithProgress(progress2, selector, timeout, options) { return await this._retryWithProgressIfNotConnected(progress2, selector, { strict: true, performActionPreChecks: true }, async (progress3, handle) => { await handle._frame.rafrafTimeout(progress3, timeout); return await this._page.screenshotter.screenshotElement(progress3, handle, options); }); } async click(progress2, selector, options) { return assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._click(progress3, { ...options, waitAfter: !options.noWaitAfter }))); } async dblclick(progress2, selector, options) { return assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._dblclick(progress3, options))); } async dragAndDrop(progress2, source11, target, options) { assertDone(await this._retryWithProgressIfNotConnected(progress2, source11, options, async (progress3, handle) => { return handle._retryPointerAction(progress3, "move and down", false, async (progress4, point) => { await this._page.mouse.move(progress4, point.x, point.y); await this._page.mouse.down(progress4); }, { ...options, waitAfter: "disabled", position: options.sourcePosition }); })); assertDone(await this._retryWithProgressIfNotConnected(progress2, target, { ...options, performActionPreChecks: false }, async (progress3, handle) => { return handle._retryPointerAction(progress3, "move and up", false, async (progress4, point) => { await this._page.mouse.move(progress4, point.x, point.y, { steps: options.steps }); await this._page.mouse.up(progress4); }, { ...options, waitAfter: "disabled", position: options.targetPosition }); })); } async tap(progress2, selector, options) { if (!this._page.browserContext._options.hasTouch) throw new Error("The page does not support tap. Use hasTouch context option to enable touch support."); return assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._tap(progress3, options))); } async fill(progress2, selector, value2, options) { return assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._fill(progress3, value2, options))); } async focus(progress2, selector, options) { assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._focus(progress3))); } async blur(progress2, selector, options) { assertDone(await this._retryWithProgressIfNotConnected(progress2, selector, options, (progress3, handle) => handle._blur(progress3))); } async resolveSelector(progress2, selector, options = {}) { const element2 = await progress2.race(this.selectors.query(selector, options)); if (!element2) throw new Error(`No element matching ${selector}`); const generated = await progress2.race(element2.evaluateInUtility(async ([injected, node]) => { return injected.generateSelectorSimple(node); }, {})); if (!generated) throw new Error(`Unable to generate locator for ${selector}`); let frame = element2._frame; const result2 = [generated]; while (frame?.parentFrame()) { const frameElement = await frame.frameElement(progress2); if (frameElement) { const generated2 = await progress2.race(frameElement.evaluateInUtility(async ([injected, node]) => { return injected.generateSelectorSimple(node); }, {})); frameElement.dispose(); if (generated2 === "error:notconnected" || !generated2) throw new Error(`Unable to generate locator for ${selector}`); result2.push(generated2); } frame = frame.parentFrame(); } const resolvedSelector = result2.reverse().join(" >> internal:control=enter-frame >> "); return { resolvedSelector }; } async textContent(progress2, selector, options, scope) { return this._callOnElementOnceMatches(progress2, selector, (injected, element2) => element2.textContent, void 0, options, scope); } async innerText(progress2, selector, options, scope) { return this._callOnElementOnceMatches(progress2, selector, (injectedScript, element2) => { if (element2.namespaceURI !== "http://www.w3.org/1999/xhtml") throw injectedScript.createStacklessError("Node is not an HTMLElement"); return element2.innerText; }, void 0, options, scope); } async innerHTML(progress2, selector, options, scope) { return this._callOnElementOnceMatches(progress2, selector, (injected, element2) => element2.innerHTML, void 0, options, scope); } async getAttribute(progress2, selector, name, options, scope) { return this._callOnElementOnceMatches(progress2, selector, (injected, element2, data) => element2.getAttribute(data.name), { name }, options, scope); } async inputValue(progress2, selector, options, scope) { return this._callOnElementOnceMatches(progress2, selector, (injectedScript, node) => { const element2 = injectedScript.retarget(node, "follow-label"); if (!element2 || element2.nodeName !== "INPUT" && element2.nodeName !== "TEXTAREA" && element2.nodeName !== "SELECT") throw injectedScript.createStacklessError("Node is not an ,