"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var injectedScriptSource_exports = {}; __export(injectedScriptSource_exports, { source: () => source }); module.exports = __toCommonJS(injectedScriptSource_exports); const 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/injectedScript.ts\nvar injectedScript_exports = {};\n__export(injectedScript_exports, {\n InjectedScript: () => InjectedScript\n});\nmodule.exports = __toCommonJS(injectedScript_exports);\n\n// packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts\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: valueOrRegex(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)] = valueOrRegex(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: valueOrRegex(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 valueOrRegex(value) {\n return value.startsWith("/") && value.endsWith("/") && value.length > 1 ? { pattern: value.slice(1, -1) } : normalizeWhitespace(value);\n}\nvar KeyParser = class _KeyParser {\n static parse(text, options, errors) {\n try {\n return new _KeyParser(text.value, options)._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, options) {\n this._input = input;\n this._pos = 0;\n this._length = input.length;\n this._options = options;\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 === "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};\n\n// packages/playwright-core/src/utils/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), c2 = next(2), 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/playwright-core/src/utils/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/playwright-core/src/utils/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/playwright-core/src/utils/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}\n\n// packages/playwright-core/src/utils/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 options.exact = attr.caseSensitive;\n options.name = 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 (options.exact)\n attrs.push(`exact: true`);\n }\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 (options.exact)\n attrs.push(`exact=True`);\n }\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 (options.exact)\n attrs.push(`.setExact(true)`);\n }\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 (options.exact)\n attrs.push(`Exact = true`);\n }\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/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 return element.ownerDocument && element.ownerDocument.defaultView ? element.ownerDocument.defaultView.getComputedStyle(element, pseudo) : void 0;\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 box(element) {\n const style = getElementComputedStyle(element);\n if (!style)\n return { visible: true };\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, style };\n if (child.nodeType === 3 && isVisibleTextNode(child))\n return { visible: true, style };\n }\n return { visible: false, style };\n }\n if (!isElementStyleVisibilityVisible(element, style))\n return { style, visible: false };\n const rect = element.getBoundingClientRect();\n return { rect, style, visible: rect.width > 0 && rect.height > 0 };\n}\nfunction isElementVisible(element) {\n return box(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 if (element instanceof HTMLFormElement)\n return "FORM";\n return element.tagName.toUpperCase();\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 if (e.getAttribute("scope") === "col")\n return "columnheader";\n if (e.getAttribute("scope") === "row")\n return "rowheader";\n const table = closestCrossShadow(e, "table");\n const role = table ? getExplicitAriaRole(table) : "";\n return role === "grid" || role === "treegrid" ? "gridcell" : "cell";\n },\n "THEAD": () => "rowgroup",\n "TIME": () => "time",\n "TR": () => "row",\n "UL": () => "list"\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 belongsToDisplayNoneOrAriaHiddenOrNonSlottedOrInert(element);\n}\nfunction belongsToDisplayNoneOrAriaHiddenOrNonSlottedOrInert(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 || element.getAttribute("inert") !== null;\n }\n if (!hidden) {\n const parent = parentElementOrShadowHost(element);\n if (parent)\n hidden = belongsToDisplayNoneOrAriaHiddenOrNonSlottedOrInert(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 && style.display !== "none" && style.visibility !== "hidden") {\n content = parseCSSContentPropertyAsString(element, style.content, !!pseudo);\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}\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 cachesCounter = 0;\nfunction beginAriaCaches() {\n ++cachesCounter;\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 (!--cachesCounter) {\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}\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/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/ariaSnapshot.ts\nvar lastRef = 0;\nfunction toInternalOptions(options) {\n if (options.mode === "ai") {\n return {\n visibility: "ariaOrVisible",\n refs: "interactable",\n refPrefix: options.refPrefix,\n includeGenericRole: true,\n renderActive: true,\n renderCursorPointer: true\n };\n }\n if (options.mode === "autoexpect") {\n return { visibility: "ariaAndVisible", refs: "none" };\n }\n if (options.mode === "codegen") {\n return { visibility: "aria", refs: "none", renderStringsAsRegex: true };\n }\n return { visibility: "aria", refs: "none" };\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: [], element: rootElement, props: {}, box: box(rootElement), receivesPointerEvents: true },\n elements: /* @__PURE__ */ new Map(),\n refs: /* @__PURE__ */ new Map()\n };\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 }\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 }\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 let ariaRef;\n ariaRef = ariaNode.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 ariaNode.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 element,\n box: box(element),\n receivesPointerEvents: true,\n active\n };\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 result = {\n role,\n name,\n children: [],\n props: {},\n element,\n box: box(element),\n receivesPointerEvents: receivesPointerEvents2,\n active\n };\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 (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" && 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 matchesText(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 matchesTextNode(text, template) {\n return matchesText(text, template.text);\n}\nfunction matchesName(text, template) {\n return matchesText(text, template.name);\n}\nfunction matchesExpectAriaTemplate(rootElement, template) {\n const snapshot = generateAriaTree(rootElement, { mode: "expect" });\n const matches = matchesNodeDeep(snapshot.root, template, false, false);\n return {\n matches,\n received: {\n raw: renderAriaTree(snapshot, { mode: "expect" }),\n regex: renderAriaTree(snapshot, { mode: "codegen" })\n }\n };\n}\nfunction getAllElementsMatchingExpectAriaTemplate(rootElement, template) {\n const root = generateAriaTree(rootElement, { mode: "expect" }).root;\n const matches = matchesNodeDeep(root, template, true, false);\n return matches.map((n) => n.element);\n}\nfunction matchesNode(node, template, isDeepEqual) {\n var _a;\n if (typeof node === "string" && template.kind === "text")\n return matchesTextNode(node, template);\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.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 (!matchesName(node.name, template))\n return false;\n if (!matchesText(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 renderAriaTree(ariaSnapshot, publicOptions) {\n const options = toInternalOptions(publicOptions);\n const lines = [];\n const includeText = options.renderStringsAsRegex ? textContributesInfo : () => true;\n const renderString = options.renderStringsAsRegex ? convertToBestGuessRegex : (str) => str;\n const visit = (ariaNode2, parentAriaNode, indent) => {\n if (typeof ariaNode2 === "string") {\n if (parentAriaNode && !includeText(parentAriaNode, ariaNode2))\n return;\n const text = yamlEscapeValueIfNeeded(renderString(ariaNode2));\n if (text)\n lines.push(indent + "- text: " + text);\n return;\n }\n let key = ariaNode2.role;\n if (ariaNode2.name && ariaNode2.name.length <= 900) {\n const name = renderString(ariaNode2.name);\n if (name) {\n const stringifiedName = name.startsWith("/") && name.endsWith("/") ? name : JSON.stringify(name);\n key += " " + stringifiedName;\n }\n }\n if (ariaNode2.checked === "mixed")\n key += ` [checked=mixed]`;\n if (ariaNode2.checked === true)\n key += ` [checked]`;\n if (ariaNode2.disabled)\n key += ` [disabled]`;\n if (ariaNode2.expanded)\n key += ` [expanded]`;\n if (ariaNode2.active && options.renderActive)\n key += ` [active]`;\n if (ariaNode2.level)\n key += ` [level=${ariaNode2.level}]`;\n if (ariaNode2.pressed === "mixed")\n key += ` [pressed=mixed]`;\n if (ariaNode2.pressed === true)\n key += ` [pressed]`;\n if (ariaNode2.selected === true)\n key += ` [selected]`;\n if (ariaNode2.ref) {\n key += ` [ref=${ariaNode2.ref}]`;\n if (options.renderCursorPointer && hasPointerCursor(ariaNode2))\n key += " [cursor=pointer]";\n }\n const escapedKey = indent + "- " + yamlEscapeKeyIfNeeded(key);\n const hasProps = !!Object.keys(ariaNode2.props).length;\n if (!ariaNode2.children.length && !hasProps) {\n lines.push(escapedKey);\n } else if (ariaNode2.children.length === 1 && typeof ariaNode2.children[0] === "string" && !hasProps) {\n const text = includeText(ariaNode2, ariaNode2.children[0]) ? renderString(ariaNode2.children[0]) : null;\n if (text)\n lines.push(escapedKey + ": " + yamlEscapeValueIfNeeded(text));\n else\n lines.push(escapedKey);\n } else {\n lines.push(escapedKey + ":");\n for (const [name, value] of Object.entries(ariaNode2.props))\n lines.push(indent + " - /" + name + ": " + yamlEscapeValueIfNeeded(value));\n for (const child of ariaNode2.children || [])\n visit(child, ariaNode2, indent + " ");\n }\n };\n const ariaNode = ariaSnapshot.root;\n if (ariaNode.role === "fragment") {\n for (const child of ariaNode.children || [])\n visit(child, ariaNode, "");\n } else {\n visit(ariaNode, null, "");\n }\n return lines.join("\\n");\n}\nfunction convertToBestGuessRegex(text) {\n const dynamicContent = [\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 if (node.name.length > text.length)\n return false;\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}\nfunction hasPointerCursor(ariaNode) {\n var _a;\n return ((_a = ariaNode.box.style) == null ? void 0 : _a.cursor) === "pointer";\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}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-line.selectable:hover{background-color:#f2f2f2;overflow:hidden}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;width:400px;height:150px;z-index:10;font-size:13px}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-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.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}\\n";\n\n// packages/injected/src/highlight.ts\nvar Highlight = class {\n constructor(injectedScript) {\n this._renderedEntries = [];\n this._language = "javascript";\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.style.position = "fixed";\n this._glassPaneElement.style.top = "0";\n this._glassPaneElement.style.right = "0";\n this._glassPaneElement.style.bottom = "0";\n this._glassPaneElement.style.left = "0";\n this._glassPaneElement.style.zIndex = "2147483647";\n this._glassPaneElement.style.pointerEvents = "none";\n this._glassPaneElement.style.display = "flex";\n this._glassPaneElement.style.backgroundColor = "transparent";\n for (const eventName of ["click", "auxclick", "dragstart", "input", "keydown", "keyup", "pointerdown", "pointerup", "mousedown", "mouseup", "mouseleave", "focus", "scroll"]) {\n this._glassPaneElement.addEventListener(eventName, (e) => {\n e.stopPropagation();\n e.stopImmediatePropagation();\n });\n }\n this._actionPointElement = document.createElement("x-pw-action-point");\n this._actionPointElement.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 }\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 }\n setLanguage(language) {\n this._language = language;\n }\n runHighlightOnRaf(selector) {\n if (this._rafRequest)\n this._injectedScript.utils.builtins.cancelAnimationFrame(this._rafRequest);\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 this.updateHighlight(elements.map((element, index) => {\n const suffix = elements.length > 1 ? ` [${index + 1} of ${elements.length}]` : "";\n return { element, color, tooltipText: locator + suffix };\n }));\n this._rafRequest = this._injectedScript.utils.builtins.requestAnimationFrame(() => this.runHighlightOnRaf(selector));\n }\n uninstall() {\n if (this._rafRequest)\n this._injectedScript.utils.builtins.cancelAnimationFrame(this._rafRequest);\n this._glassPaneElement.remove();\n }\n showActionPoint(x, y) {\n this._actionPointElement.style.top = y + "px";\n this._actionPointElement.style.left = x + "px";\n this._actionPointElement.hidden = false;\n }\n hideActionPoint() {\n this._actionPointElement.hidden = true;\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, color: entry.color, tooltipElement, highlightElement });\n }\n for (const entry of this._renderedEntries) {\n 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 box2 = entry.box;\n entry.highlightElement.style.backgroundColor = entry.color;\n entry.highlightElement.style.left = box2.x + "px";\n entry.highlightElement.style.top = box2.y + "px";\n entry.highlightElement.style.width = box2.width + "px";\n entry.highlightElement.style.height = box2.height + "px";\n entry.highlightElement.style.display = "block";\n if (this._isUnderTest)\n console.error("Highlight box for test: " + JSON.stringify({ x: box2.x, y: box2.y, width: box2.width, height: box2.height }));\n }\n }\n firstBox() {\n var _a;\n return (_a = this._renderedEntries[0]) == null ? void 0 : _a.box;\n }\n tooltipPosition(box2, 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 = box2.left;\n if (anchorLeft + tooltipWidth > totalWidth - 5)\n anchorLeft = totalWidth - tooltipWidth - 5;\n let anchorTop = box2.bottom + 5;\n if (anchorTop + tooltipHeight > totalHeight - 5) {\n if (box2.top > tooltipHeight + 5) {\n anchorTop = box2.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 const oldBox = this._renderedEntries[i].box;\n if (!oldBox)\n return false;\n const box2 = entries[i].element.getBoundingClientRect();\n if (box2.top !== oldBox.top || box2.right !== oldBox.right || box2.bottom !== oldBox.bottom || box2.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};\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 box2 = 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(box2, 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 matchesComponentAttribute(obj, attr) {\n for (const token of attr.jsonPath) {\n if (obj !== void 0 && obj !== null)\n obj = obj[token];\n }\n return matchesAttributePart(obj, attr);\n}\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/reactSelectorEngine.ts\nfunction getFunctionComponentName(component) {\n return component.displayName || component.name || "Anonymous";\n}\nfunction getComponentName(reactElement) {\n if (reactElement.type) {\n switch (typeof reactElement.type) {\n case "function":\n return getFunctionComponentName(reactElement.type);\n case "string":\n return reactElement.type;\n case "object":\n return reactElement.type.displayName || (reactElement.type.render ? getFunctionComponentName(reactElement.type.render) : "");\n }\n }\n if (reactElement._currentElement) {\n const elementType = reactElement._currentElement.type;\n if (typeof elementType === "string")\n return elementType;\n if (typeof elementType === "function")\n return elementType.displayName || elementType.name || "Anonymous";\n }\n return "";\n}\nfunction getComponentKey(reactElement) {\n var _a, _b;\n return (_b = reactElement.key) != null ? _b : (_a = reactElement._currentElement) == null ? void 0 : _a.key;\n}\nfunction getChildren(reactElement) {\n if (reactElement.child) {\n const children = [];\n for (let child = reactElement.child; child; child = child.sibling)\n children.push(child);\n return children;\n }\n if (!reactElement._currentElement)\n return [];\n const isKnownElement = (reactElement2) => {\n var _a;\n const elementType = (_a = reactElement2._currentElement) == null ? void 0 : _a.type;\n return typeof elementType === "function" || typeof elementType === "string";\n };\n if (reactElement._renderedComponent) {\n const child = reactElement._renderedComponent;\n return isKnownElement(child) ? [child] : [];\n }\n if (reactElement._renderedChildren)\n return [...Object.values(reactElement._renderedChildren)].filter(isKnownElement);\n return [];\n}\nfunction getProps(reactElement) {\n var _a;\n const props = (\n // React 16+\n reactElement.memoizedProps || // React 15\n ((_a = reactElement._currentElement) == null ? void 0 : _a.props)\n );\n if (!props || typeof props === "string")\n return props;\n const result = { ...props };\n delete result.children;\n return result;\n}\nfunction buildComponentsTree(reactElement) {\n var _a;\n const treeNode = {\n key: getComponentKey(reactElement),\n name: getComponentName(reactElement),\n children: getChildren(reactElement).map(buildComponentsTree),\n rootElements: [],\n props: getProps(reactElement)\n };\n const rootElement = (\n // React 16+\n // @see https://github.com/baruchvlz/resq/blob/5c15a5e04d3f7174087248f5a158c3d6dcc1ec72/src/utils.js#L29\n reactElement.stateNode || // React 15\n reactElement._hostNode || ((_a = reactElement._renderedComponent) == null ? void 0 : _a._hostNode)\n );\n if (rootElement instanceof Element) {\n treeNode.rootElements.push(rootElement);\n } else {\n for (const child of treeNode.children)\n treeNode.rootElements.push(...child.rootElements);\n }\n return treeNode;\n}\nfunction filterComponentsTree(treeNode, searchFn, result = []) {\n if (searchFn(treeNode))\n result.push(treeNode);\n for (const child of treeNode.children)\n filterComponentsTree(child, searchFn, result);\n return result;\n}\nfunction findReactRoots(root, roots = []) {\n const document = root.ownerDocument || root;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);\n do {\n const node = walker.currentNode;\n const reactNode = node;\n const rootKey = Object.keys(reactNode).find((key) => key.startsWith("__reactContainer") && reactNode[key] !== null);\n if (rootKey) {\n roots.push(reactNode[rootKey].stateNode.current);\n } else {\n const legacyRootKey = "_reactRootContainer";\n if (reactNode.hasOwnProperty(legacyRootKey) && reactNode[legacyRootKey] !== null) {\n roots.push(reactNode[legacyRootKey]._internalRoot.current);\n }\n }\n if (node instanceof Element && node.hasAttribute("data-reactroot")) {\n for (const key of Object.keys(node)) {\n if (key.startsWith("__reactInternalInstance") || key.startsWith("__reactFiber"))\n roots.push(node[key]);\n }\n }\n const shadowRoot = node instanceof Element ? node.shadowRoot : null;\n if (shadowRoot)\n findReactRoots(shadowRoot, roots);\n } while (walker.nextNode());\n return roots;\n}\nvar createReactEngine = () => ({\n queryAll(scope, selector) {\n const { name, attributes } = parseAttributeSelector(selector, false);\n const reactRoots = findReactRoots(scope.ownerDocument || scope);\n const trees = reactRoots.map((reactRoot) => buildComponentsTree(reactRoot));\n const treeNodes = trees.map((tree) => filterComponentsTree(tree, (treeNode) => {\n var _a;\n const props = (_a = treeNode.props) != null ? _a : {};\n if (treeNode.key !== void 0)\n props.key = treeNode.key;\n if (name && treeNode.name !== name)\n return false;\n if (treeNode.rootElements.some((domNode) => !isInsideScope(scope, domNode)))\n return false;\n for (const attr of attributes) {\n if (!matchesComponentAttribute(props, attr))\n return false;\n }\n return true;\n })).flat();\n const allRootElements = /* @__PURE__ */ new Set();\n for (const treeNode of treeNodes) {\n for (const domNode of treeNode.rootElements)\n allRootElements.add(domNode);\n }\n return [...allRootElements];\n }\n});\n\n// packages/injected/src/roleSelectorEngine.ts\nvar kSupportedAttributes = ["selected", "checked", "pressed", "expanded", "level", "disabled", "name", "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.exact = 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.exact && options.nameOp === "=")\n options.nameOp = "*=";\n if (!matchesAttributePart(accessibleName, { name: "", jsonPath: [], op: options.nameOp || "=", value: options.name, caseSensitive: !!options.exact }))\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 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 endAriaCaches();\n injectedScript._evaluator.end();\n }\n}\nfunction filterRegexTokens(textCandidates) {\n return textCandidates.filter((c) => c[0].selector[0] !== "/");\n}\nfunction generateSelectorFor(cache, injectedScript, targetElement, options) {\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 const calculate = (element, allowText) => {\n var _a;\n const allowNthMatch = element === targetElement;\n let textCandidates = allowText ? buildTextCandidates(injectedScript, element, element === targetElement) : [];\n if (element !== targetElement) {\n textCandidates = filterRegexTokens(textCandidates);\n }\n const noTextCandidates = buildNoTextCandidates(injectedScript, element, options).filter((token) => !options.omitInternalEngines || !token.engine.startsWith("internal:")).map((token) => [token]);\n let result = chooseFirstSelector(injectedScript, (_a = options.root) != null ? _a : targetElement.ownerDocument, element, [...textCandidates, ...noTextCandidates], allowNthMatch);\n textCandidates = filterRegexTokens(textCandidates);\n const checkWithText = (textCandidatesToUse) => {\n const allowParentText = allowText && !textCandidatesToUse.length;\n const candidates = [...textCandidatesToUse, ...noTextCandidates].filter((c) => {\n if (!result)\n return true;\n return combineScores(c) < combineScores(result);\n });\n let bestPossibleInParent = candidates[0];\n if (!bestPossibleInParent)\n return;\n for (let parent = parentElementOrShadowHost(element); parent && parent !== options.root; parent = parentElementOrShadowHost(parent)) {\n const parentTokens = calculateCached(parent, allowParentText);\n if (!parentTokens)\n continue;\n if (result && combineScores([...parentTokens, ...bestPossibleInParent]) >= combineScores(result))\n continue;\n bestPossibleInParent = chooseFirstSelector(injectedScript, parent, element, candidates, allowNthMatch);\n if (!bestPossibleInParent)\n return;\n const combined = [...parentTokens, ...bestPossibleInParent];\n if (!result || combineScores(combined) < combineScores(result))\n result = combined;\n }\n };\n checkWithText(textCandidates);\n if (element === targetElement && textCandidates.length)\n checkWithText([]);\n return result;\n };\n const calculateCached = (element, allowText) => {\n const map = allowText ? cache.allowText : cache.disallowText;\n let value = map.get(element);\n if (value === void 0) {\n value = calculate(element, allowText);\n map.set(element, value);\n }\n return value;\n };\n return calculate(targetElement, !options.noText);\n}\nfunction buildNoTextCandidates(injectedScript, element, options) {\n const candidates = [];\n {\n for (const attr of ["data-testid", "data-test-id", "data-test"]) {\n if (attr !== options.testIdAttributeName && 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 if (element.getAttribute(options.testIdAttributeName))\n candidates.push({ engine: "css", selector: `[${options.testIdAttributeName}=${quoteCSSAttributeValue(element.getAttribute(options.testIdAttributeName))}]`, score: kTestIdScore });\n penalizeScoreForLength([candidates]);\n return candidates;\n }\n if (element.getAttribute(options.testIdAttributeName))\n candidates.push({ engine: "internal:testid", selector: `[${options.testIdAttributeName}=${escapeForAttributeSelector(element.getAttribute(options.testIdAttributeName), true)}]`, score: kTestIdScore });\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 (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) {\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 } else {\n const roleToken = { engine: "internal:role", selector: `${ariaRole}`, score: kRoleWithoutNameScore };\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 (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 chooseFirstSelector(injectedScript, scope, targetElement, selectors, allowNthMatch) {\n const joined = selectors.map((tokens) => ({ tokens, score: combineScores(tokens) }));\n joined.sort((a, b) => a.score - b.score);\n let bestWithIndex = null;\n for (const { tokens } of joined) {\n const parsedSelector = injectedScript.parseSelector(joinTokens(tokens));\n const result = injectedScript.querySelectorAll(parsedSelector, scope);\n if (result[0] === targetElement && result.length === 1) {\n return tokens;\n }\n const index = result.indexOf(targetElement);\n if (!allowNthMatch || bestWithIndex || index === -1 || result.length > 5)\n continue;\n const nth = { engine: "nth", selector: String(index), score: kNthScore };\n bestWithIndex = [...tokens, nth];\n }\n return bestWithIndex;\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/vueSelectorEngine.ts\nfunction basename(filename, ext) {\n const normalized = filename.replace(/^[a-zA-Z]:/, "").replace(/\\\\/g, "/");\n let result = normalized.substring(normalized.lastIndexOf("/") + 1);\n if (ext && result.endsWith(ext))\n result = result.substring(0, result.length - ext.length);\n return result;\n}\nfunction toUpper(_, c) {\n return c ? c.toUpperCase() : "";\n}\nvar classifyRE = /(?:^|[-_/])(\\w)/g;\nvar classify = (str) => {\n return str && str.replace(classifyRE, toUpper);\n};\nfunction buildComponentsTreeVue3(instance) {\n function getComponentTypeName(options) {\n const name = options.name || options._componentTag || options.__playwright_guessedName;\n if (name)\n return name;\n const file = options.__file;\n if (file)\n return classify(basename(file, ".vue"));\n }\n function saveComponentName(instance2, key) {\n instance2.type.__playwright_guessedName = key;\n return key;\n }\n function getInstanceName(instance2) {\n var _a, _b, _c, _d;\n const name = getComponentTypeName(instance2.type || {});\n if (name)\n return name;\n if (instance2.root === instance2)\n return "Root";\n for (const key in (_b = (_a = instance2.parent) == null ? void 0 : _a.type) == null ? void 0 : _b.components) {\n if (((_c = instance2.parent) == null ? void 0 : _c.type.components[key]) === instance2.type)\n return saveComponentName(instance2, key);\n }\n for (const key in (_d = instance2.appContext) == null ? void 0 : _d.components) {\n if (instance2.appContext.components[key] === instance2.type)\n return saveComponentName(instance2, key);\n }\n return "Anonymous Component";\n }\n function isBeingDestroyed(instance2) {\n return instance2._isBeingDestroyed || instance2.isUnmounted;\n }\n function isFragment(instance2) {\n return instance2.subTree.type.toString() === "Symbol(Fragment)";\n }\n function getInternalInstanceChildren(subTree) {\n const list = [];\n if (subTree.component)\n list.push(subTree.component);\n if (subTree.suspense)\n list.push(...getInternalInstanceChildren(subTree.suspense.activeBranch));\n if (Array.isArray(subTree.children)) {\n subTree.children.forEach((childSubTree) => {\n if (childSubTree.component)\n list.push(childSubTree.component);\n else\n list.push(...getInternalInstanceChildren(childSubTree));\n });\n }\n return list.filter((child) => {\n var _a;\n return !isBeingDestroyed(child) && !((_a = child.type.devtools) == null ? void 0 : _a.hide);\n });\n }\n function getRootElementsFromComponentInstance(instance2) {\n if (isFragment(instance2))\n return getFragmentRootElements(instance2.subTree);\n return [instance2.subTree.el];\n }\n function getFragmentRootElements(vnode) {\n if (!vnode.children)\n return [];\n const list = [];\n for (let i = 0, l = vnode.children.length; i < l; i++) {\n const childVnode = vnode.children[i];\n if (childVnode.component)\n list.push(...getRootElementsFromComponentInstance(childVnode.component));\n else if (childVnode.el)\n list.push(childVnode.el);\n }\n return list;\n }\n function buildComponentsTree2(instance2) {\n return {\n name: getInstanceName(instance2),\n children: getInternalInstanceChildren(instance2.subTree).map(buildComponentsTree2),\n rootElements: getRootElementsFromComponentInstance(instance2),\n props: instance2.props\n };\n }\n return buildComponentsTree2(instance);\n}\nfunction buildComponentsTreeVue2(instance) {\n function getComponentName2(options) {\n const name = options.displayName || options.name || options._componentTag;\n if (name)\n return name;\n const file = options.__file;\n if (file)\n return classify(basename(file, ".vue"));\n }\n function getInstanceName(instance2) {\n const name = getComponentName2(instance2.$options || instance2.fnOptions || {});\n if (name)\n return name;\n return instance2.$root === instance2 ? "Root" : "Anonymous Component";\n }\n function getInternalInstanceChildren(instance2) {\n if (instance2.$children)\n return instance2.$children;\n if (Array.isArray(instance2.subTree.children))\n return instance2.subTree.children.filter((vnode) => !!vnode.component).map((vnode) => vnode.component);\n return [];\n }\n function buildComponentsTree2(instance2) {\n return {\n name: getInstanceName(instance2),\n children: getInternalInstanceChildren(instance2).map(buildComponentsTree2),\n rootElements: [instance2.$el],\n props: instance2._props\n };\n }\n return buildComponentsTree2(instance);\n}\nfunction filterComponentsTree2(treeNode, searchFn, result = []) {\n if (searchFn(treeNode))\n result.push(treeNode);\n for (const child of treeNode.children)\n filterComponentsTree2(child, searchFn, result);\n return result;\n}\nfunction findVueRoots(root, roots = []) {\n const document = root.ownerDocument || root;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);\n const vue2Roots = /* @__PURE__ */ new Set();\n do {\n const node = walker.currentNode;\n if (node.__vue__)\n vue2Roots.add(node.__vue__.$root);\n if (node.__vue_app__ && node._vnode && node._vnode.component)\n roots.push({ root: node._vnode.component, version: 3 });\n const shadowRoot = node instanceof Element ? node.shadowRoot : null;\n if (shadowRoot)\n findVueRoots(shadowRoot, roots);\n } while (walker.nextNode());\n for (const vue2root of vue2Roots) {\n roots.push({\n version: 2,\n root: vue2root\n });\n }\n return roots;\n}\nvar createVueEngine = () => ({\n queryAll(scope, selector) {\n const document = scope.ownerDocument || scope;\n const { name, attributes } = parseAttributeSelector(selector, false);\n const vueRoots = findVueRoots(document);\n const trees = vueRoots.map((vueRoot) => vueRoot.version === 3 ? buildComponentsTreeVue3(vueRoot.root) : buildComponentsTreeVue2(vueRoot.root));\n const treeNodes = trees.map((tree) => filterComponentsTree2(tree, (treeNode) => {\n if (name && treeNode.name !== name)\n return false;\n if (treeNode.rootElements.some((rootElement) => !isInsideScope(scope, rootElement)))\n return false;\n for (const attr of attributes) {\n if (!matchesComponentAttribute(treeNode.props, attr))\n return false;\n }\n return true;\n })).flat();\n const allRootElements = /* @__PURE__ */ new Set();\n for (const treeNode of treeNodes) {\n for (const rootElement of treeNode.rootElements)\n allRootElements.add(rootElement);\n }\n return [...allRootElements];\n }\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/playwright-core/src/utils/isomorphic/locatorUtils.ts\nfunction getByAttributeTextSelector(attrName, text, options) {\n return `internal:attr=[${attrName}=${escapeForAttributeSelector(text, (options == null ? void 0 : options.exact) || false)}]`;\n}\nfunction getByTestIdSelector(testIdAttributeName, testId) {\n return `internal:testid=[${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.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/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) => {\n return this._injectedScript.ariaSnapshot(element || this._injectedScript.document.body, { mode: "expect" });\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/playwright-core/src/utils/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}\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 }\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 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 // eslint-disable-next-line no-restricted-globals\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 };\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 // eslint-disable-next-line no-restricted-globals\n constructor(window, options) {\n this._testIdAttributeNameForStrictErrorAndConsoleCodegen = "data-testid";\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 // 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("_react", createReactEngine());\n this._engines.set("_vue", createVueEngine());\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._createNamedAttributeEngine());\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 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 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 if (node.nodeType !== Node.ELEMENT_NODE)\n throw this.createStacklessError("Can only capture aria snapshot of Element nodes.");\n this._lastAriaSnapshot = generateAriaTree(node, options);\n return renderAriaTree(this._lastAriaSnapshot, options);\n }\n ariaSnapshotForRecorder() {\n const tree = generateAriaTree(this.document.body, { mode: "ai" });\n const 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, value, caseSensitive } = parsed.attributes[0];\n const lowerCaseValue = caseSensitive ? null : value.toLowerCase();\n let matcher;\n if (value instanceof RegExp)\n matcher = (s) => !!s.match(value);\n else if (caseSensitive)\n matcher = (s) => s === value;\n else\n matcher = (s) => s.toLowerCase().includes(lowerCaseValue);\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 _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._lastAriaSnapshot) == 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