Socket
Socket
Sign inDemoInstall

playwright-core

Package Overview
Dependencies
Maintainers
2
Versions
4547
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

playwright-core - npm Package Compare versions

Comparing version 0.14.0-next.1587678100542 to 0.14.0-next.1587678340966

2

lib/generated/selectorEvaluatorSource.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.source = "(/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = \"./src/injected/selectorEvaluator.ts\");\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ \"./src/injected/attributeSelectorEngine.ts\":\n/*!*************************************************!*\\\n !*** ./src/injected/attributeSelectorEngine.ts ***!\n \\*************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction createAttributeEngine(attribute, shadow) {\n const engine = {\n create(root, target) {\n const value = target.getAttribute(attribute);\n if (!value)\n return;\n if (engine.query(root, value) === target)\n return value;\n },\n query(root, selector) {\n if (!shadow)\n return root.querySelector(`[${attribute}=${JSON.stringify(selector)}]`) || undefined;\n return queryShadowInternal(root, attribute, selector);\n },\n queryAll(root, selector) {\n if (!shadow)\n return Array.from(root.querySelectorAll(`[${attribute}=${JSON.stringify(selector)}]`));\n const result = [];\n queryShadowAllInternal(root, attribute, selector, result);\n return result;\n }\n };\n return engine;\n}\nexports.createAttributeEngine = createAttributeEngine;\nfunction queryShadowInternal(root, attribute, value) {\n const single = root.querySelector(`[${attribute}=${JSON.stringify(value)}]`);\n if (single)\n return single;\n const all = root.querySelectorAll('*');\n for (let i = 0; i < all.length; i++) {\n const shadowRoot = all[i].shadowRoot;\n if (shadowRoot) {\n const single = queryShadowInternal(shadowRoot, attribute, value);\n if (single)\n return single;\n }\n }\n}\nfunction queryShadowAllInternal(root, attribute, value, result) {\n const document = root instanceof Document ? root : root.ownerDocument;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);\n const shadowRoots = [];\n while (walker.nextNode()) {\n const element = walker.currentNode;\n if (element.getAttribute(attribute) === value)\n result.push(element);\n if (element.shadowRoot)\n shadowRoots.push(element.shadowRoot);\n }\n for (const shadowRoot of shadowRoots)\n queryShadowAllInternal(shadowRoot, attribute, value, result);\n}\n\n\n/***/ }),\n\n/***/ \"./src/injected/cssSelectorEngine.ts\":\n/*!*******************************************!*\\\n !*** ./src/injected/cssSelectorEngine.ts ***!\n \\*******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction createCSSEngine(shadow) {\n const engine = {\n create(root, targetElement) {\n if (shadow)\n return;\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 nodes = Array.from(root.querySelectorAll(selector));\n return nodes[0] === targetElement ? selector : undefined;\n }\n for (let element = targetElement; element && element !== root; element = element.parentElement) {\n const nodeName = element.nodeName.toLowerCase();\n // Element ID is the strongest signal, use it.\n let bestTokenForLevel = '';\n if (element.id) {\n const token = /^[a-zA-Z][a-zA-Z0-9\\-\\_]+$/.test(element.id) ? '#' + element.id : `[id=\"${element.id}\"]`;\n const selector = uniqueCSSSelector(token);\n if (selector)\n return selector;\n bestTokenForLevel = token;\n }\n const parent = element.parentElement;\n // Combine class names until unique.\n const classes = Array.from(element.classList);\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 selector;\n // Even if not unique, does this subset of classes uniquely identify node as a child?\n if (!bestTokenForLevel && parent) {\n const sameClassSiblings = parent.querySelectorAll(token);\n if (sameClassSiblings.length === 1)\n bestTokenForLevel = token;\n }\n }\n // Ordinal is the weakest signal.\n if (parent) {\n const siblings = Array.from(parent.children);\n const sameTagSiblings = siblings.filter(sibling => (sibling).nodeName.toLowerCase() === nodeName);\n const token = sameTagSiblings.length === 1 ? nodeName : `${nodeName}:nth-child(${1 + siblings.indexOf(element)})`;\n const selector = uniqueCSSSelector(token);\n if (selector)\n return selector;\n if (!bestTokenForLevel)\n bestTokenForLevel = token;\n }\n else if (!bestTokenForLevel) {\n bestTokenForLevel = nodeName;\n }\n tokens.unshift(bestTokenForLevel);\n }\n return uniqueCSSSelector();\n },\n query(root, selector) {\n const simple = root.querySelector(selector);\n if (simple)\n return simple;\n if (!shadow)\n return;\n const parts = split(selector);\n if (!parts.length)\n return;\n parts.reverse();\n return queryShadowInternal(root, root, parts);\n },\n queryAll(root, selector) {\n if (!shadow)\n return Array.from(root.querySelectorAll(selector));\n const result = [];\n const parts = split(selector);\n if (parts.length) {\n parts.reverse();\n queryShadowAllInternal(root, root, parts, result);\n }\n return result;\n }\n };\n engine._test = () => test(engine);\n return engine;\n}\nexports.createCSSEngine = createCSSEngine;\nfunction queryShadowInternal(boundary, root, parts) {\n const matching = root.querySelectorAll(parts[0]);\n for (let i = 0; i < matching.length; i++) {\n const element = matching[i];\n if (parts.length === 1 || matches(element, parts, boundary))\n return element;\n }\n if (root.shadowRoot) {\n const child = queryShadowInternal(boundary, root.shadowRoot, parts);\n if (child)\n return child;\n }\n const elements = root.querySelectorAll('*');\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n if (element.shadowRoot) {\n const child = queryShadowInternal(boundary, element.shadowRoot, parts);\n if (child)\n return child;\n }\n }\n}\nfunction queryShadowAllInternal(boundary, root, parts, result) {\n const matching = root.querySelectorAll(parts[0]);\n for (let i = 0; i < matching.length; i++) {\n const element = matching[i];\n if (parts.length === 1 || matches(element, parts, boundary))\n result.push(element);\n }\n if (root.shadowRoot)\n queryShadowAllInternal(boundary, root.shadowRoot, parts, result);\n const elements = root.querySelectorAll('*');\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n if (element.shadowRoot)\n queryShadowAllInternal(boundary, element.shadowRoot, parts, result);\n }\n}\nfunction matches(element, parts, boundary) {\n let i = 1;\n while (i < parts.length && (element = parentElementOrShadowHost(element)) && element !== boundary) {\n if (element.matches(parts[i]))\n i++;\n }\n return i === parts.length;\n}\nfunction parentElementOrShadowHost(element) {\n if (element.parentElement)\n return element.parentElement;\n if (!element.parentNode)\n return;\n if (element.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE && element.parentNode.host)\n return element.parentNode.host;\n}\nfunction split(selector) {\n let index = 0;\n let quote;\n let start = 0;\n let space = 'none';\n const result = [];\n const append = () => {\n const part = selector.substring(start, index).trim();\n if (part.length)\n result.push(part);\n };\n while (index < selector.length) {\n const c = selector[index];\n if (!quote && c === ' ') {\n if (space === 'none' || space === 'before')\n space = 'before';\n index++;\n }\n else {\n if (space === 'before') {\n if (c === '>' || c === '+' || c === '~') {\n space = 'after';\n }\n else {\n append();\n start = index;\n space = 'none';\n }\n }\n else {\n space = 'none';\n }\n if (c === '\\\\' && index + 1 < selector.length) {\n index += 2;\n }\n else if (c === quote) {\n quote = undefined;\n index++;\n }\n else {\n index++;\n }\n }\n }\n append();\n return result;\n}\nfunction test(engine) {\n let id = 0;\n function createShadow(level) {\n const root = document.createElement('div');\n root.id = 'id' + id;\n root.textContent = 'root #id' + id;\n id++;\n const shadow = root.attachShadow({ mode: 'open' });\n for (let i = 0; i < 9; i++) {\n const div = document.createElement('div');\n div.id = 'id' + id;\n div.textContent = '#id' + id;\n id++;\n shadow.appendChild(div);\n }\n if (level) {\n shadow.appendChild(createShadow(level - 1));\n shadow.appendChild(createShadow(level - 1));\n }\n return root;\n }\n const { query, queryAll } = engine;\n document.body.textContent = '';\n document.body.appendChild(createShadow(10));\n console.time('found');\n for (let i = 0; i < id; i += 17) {\n const e = query(document, `div #id${i}`);\n if (!e || e.id !== 'id' + i)\n console.log(`div #id${i}`); // eslint-disable-line no-console\n }\n console.timeEnd('found');\n console.time('not found');\n for (let i = 0; i < id; i += 17) {\n const e = query(document, `div div div div div #d${i}`);\n if (e)\n console.log(`div div div div div #d${i}`); // eslint-disable-line no-console\n }\n console.timeEnd('not found');\n console.log(query(document, '#id543 + #id544')); // eslint-disable-line no-console\n console.log(query(document, '#id542 ~ #id545')); // eslint-disable-line no-console\n console.time('all');\n queryAll(document, 'div div div + div');\n console.timeEnd('all');\n}\n\n\n/***/ }),\n\n/***/ \"./src/injected/injected.ts\":\n/*!**********************************!*\\\n !*** ./src/injected/injected.ts ***!\n \\**********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nclass Injected {\n isVisible(element) {\n if (!element.ownerDocument || !element.ownerDocument.defaultView)\n return true;\n const style = element.ownerDocument.defaultView.getComputedStyle(element);\n if (!style || style.visibility === 'hidden')\n return false;\n const rect = element.getBoundingClientRect();\n return !!(rect.top || rect.bottom || rect.width || rect.height);\n }\n _pollMutation(predicate, timeout) {\n let timedOut = false;\n if (timeout)\n setTimeout(() => timedOut = true, timeout);\n const success = predicate();\n if (success)\n return Promise.resolve(success);\n let fulfill;\n const result = new Promise(x => fulfill = x);\n const observer = new MutationObserver(() => {\n if (timedOut) {\n observer.disconnect();\n fulfill();\n return;\n }\n const success = predicate();\n if (success) {\n observer.disconnect();\n fulfill(success);\n }\n });\n observer.observe(document, {\n childList: true,\n subtree: true,\n attributes: true\n });\n return result;\n }\n _pollRaf(predicate, timeout) {\n let timedOut = false;\n if (timeout)\n setTimeout(() => timedOut = true, timeout);\n let fulfill;\n const result = new Promise(x => fulfill = x);\n const onRaf = () => {\n if (timedOut) {\n fulfill();\n return;\n }\n const success = predicate();\n if (success)\n fulfill(success);\n else\n requestAnimationFrame(onRaf);\n };\n onRaf();\n return result;\n }\n _pollInterval(pollInterval, predicate, timeout) {\n let timedOut = false;\n if (timeout)\n setTimeout(() => timedOut = true, timeout);\n let fulfill;\n const result = new Promise(x => fulfill = x);\n const onTimeout = () => {\n if (timedOut) {\n fulfill();\n return;\n }\n const success = predicate();\n if (success)\n fulfill(success);\n else\n setTimeout(onTimeout, pollInterval);\n };\n onTimeout();\n return result;\n }\n poll(polling, timeout, predicate) {\n if (polling === 'raf')\n return this._pollRaf(predicate, timeout);\n if (polling === 'mutation')\n return this._pollMutation(predicate, timeout);\n return this._pollInterval(polling, predicate, timeout);\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 selectOptions(node, optionsToSelect) {\n if (node.nodeName.toLowerCase() !== 'select')\n return { status: 'error', error: 'Element is not a <select> element.' };\n if (!node.isConnected)\n return { status: 'notconnected' };\n const element = node;\n const options = Array.from(element.options);\n element.value = undefined;\n for (let index = 0; index < options.length; index++) {\n const option = options[index];\n option.selected = optionsToSelect.some(optionToSelect => {\n if (optionToSelect instanceof Node)\n return option === optionToSelect;\n let matches = true;\n if (optionToSelect.value !== undefined)\n matches = matches && optionToSelect.value === option.value;\n if (optionToSelect.label !== undefined)\n matches = matches && optionToSelect.label === option.label;\n if (optionToSelect.index !== undefined)\n matches = matches && optionToSelect.index === index;\n return matches;\n });\n if (option.selected && !element.multiple)\n break;\n }\n element.dispatchEvent(new Event('input', { 'bubbles': true }));\n element.dispatchEvent(new Event('change', { 'bubbles': true }));\n return { status: 'success', value: options.filter(option => option.selected).map(option => option.value) };\n }\n fill(node, value) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n return { status: 'error', error: 'Node is not of type HTMLElement' };\n const element = node;\n if (!element.isConnected)\n return { status: 'notconnected' };\n if (!this.isVisible(element))\n return { status: 'error', error: 'Element is not visible' };\n if (element.nodeName.toLowerCase() === 'input') {\n const input = element;\n const type = (input.getAttribute('type') || '').toLowerCase();\n const kDateTypes = new Set(['date', 'time', 'datetime', 'datetime-local']);\n const kTextInputTypes = new Set(['', 'email', 'number', 'password', 'search', 'tel', 'text', 'url']);\n if (!kTextInputTypes.has(type) && !kDateTypes.has(type))\n return { status: 'error', error: 'Cannot fill input of type \"' + type + '\".' };\n if (type === 'number') {\n value = value.trim();\n if (!value || isNaN(Number(value)))\n return { status: 'error', error: 'Cannot type text into input[type=number].' };\n }\n if (input.disabled)\n return { status: 'error', error: 'Cannot fill a disabled input.' };\n if (input.readOnly)\n return { status: 'error', error: 'Cannot fill a readonly input.' };\n if (kDateTypes.has(type)) {\n value = value.trim();\n input.focus();\n input.value = value;\n if (input.value !== value)\n return { status: 'error', error: `Malformed ${type} \"${value}\"` };\n element.dispatchEvent(new Event('input', { 'bubbles': true }));\n element.dispatchEvent(new Event('change', { 'bubbles': true }));\n return { status: 'success', value: false }; // We have already changed the value, no need to input it.\n }\n }\n else if (element.nodeName.toLowerCase() === 'textarea') {\n const textarea = element;\n if (textarea.disabled)\n return { status: 'error', error: 'Cannot fill a disabled textarea.' };\n if (textarea.readOnly)\n return { status: 'error', error: 'Cannot fill a readonly textarea.' };\n }\n else if (!element.isContentEditable) {\n return { status: 'error', error: 'Element is not an <input>, <textarea> or [contenteditable] element.' };\n }\n const result = this.selectText(node);\n if (result.status === 'success')\n return { status: 'success', value: true }; // Still need to input the value.\n return result;\n }\n selectText(node) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n return { status: 'error', error: 'Node is not of type HTMLElement' };\n if (!node.isConnected)\n return { status: 'notconnected' };\n const element = node;\n if (!this.isVisible(element))\n return { status: 'error', error: 'Element is not visible' };\n if (element.nodeName.toLowerCase() === 'input') {\n const input = element;\n input.select();\n input.focus();\n return { status: 'success' };\n }\n if (element.nodeName.toLowerCase() === 'textarea') {\n const textarea = element;\n textarea.selectionStart = 0;\n textarea.selectionEnd = textarea.value.length;\n textarea.focus();\n return { status: 'success' };\n }\n const range = element.ownerDocument.createRange();\n range.selectNodeContents(element);\n const selection = element.ownerDocument.defaultView.getSelection();\n if (!selection)\n return { status: 'error', error: 'Element belongs to invisible iframe.' };\n selection.removeAllRanges();\n selection.addRange(range);\n element.focus();\n return { status: 'success' };\n }\n focusNode(node) {\n if (!node.isConnected)\n return { status: 'notconnected' };\n if (!node['focus'])\n return { status: 'error', error: 'Node is not an HTML or SVG element.' };\n node.focus();\n return { status: 'success' };\n }\n isCheckboxChecked(node) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n throw new Error('Not a checkbox or radio button');\n let element = node;\n if (element.getAttribute('role') === 'checkbox')\n return element.getAttribute('aria-checked') === 'true';\n if (element.nodeName === 'LABEL') {\n const forId = element.getAttribute('for');\n if (forId && element.ownerDocument)\n element = element.ownerDocument.querySelector(`input[id=\"${forId}\"]`) || undefined;\n else\n element = element.querySelector('input[type=checkbox],input[type=radio]') || undefined;\n }\n if (element && element.nodeName === 'INPUT') {\n const type = element.getAttribute('type');\n if (type && (type.toLowerCase() === 'checkbox' || type.toLowerCase() === 'radio'))\n return element.checked;\n }\n throw new Error('Not a checkbox');\n }\n async setInputFiles(node, payloads) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n return 'Node is not of type HTMLElement';\n const element = node;\n if (element.nodeName !== 'INPUT')\n return 'Not an <input> element';\n const input = element;\n const type = (input.getAttribute('type') || '').toLowerCase();\n if (type !== 'file')\n return 'Not an input[type=file] element';\n const files = await Promise.all(payloads.map(async (file) => {\n const result = await fetch(`data:${file.type};base64,${file.data}`);\n return new File([await result.blob()], file.name, { type: file.type });\n }));\n const dt = new DataTransfer();\n for (const file of files)\n dt.items.add(file);\n input.files = dt.files;\n input.dispatchEvent(new Event('input', { 'bubbles': true }));\n input.dispatchEvent(new Event('change', { 'bubbles': true }));\n }\n async waitForDisplayedAtStablePosition(node, timeout) {\n if (!node.isConnected)\n return { status: 'notconnected' };\n const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\n if (!element)\n return { status: 'notconnected' };\n let lastRect;\n let counter = 0;\n const result = await this.poll('raf', timeout, () => {\n // First raf happens in the same animation frame as evaluation, so it does not produce\n // any client rect difference compared to synchronous call. We skip the synchronous call\n // and only force layout during actual rafs as a small optimisation.\n if (++counter === 1)\n return false;\n if (!node.isConnected)\n return 'notconnected';\n const clientRect = element.getBoundingClientRect();\n const rect = { x: clientRect.top, y: clientRect.left, width: clientRect.width, height: clientRect.height };\n const isDisplayedAndStable = lastRect && rect.x === lastRect.x && rect.y === lastRect.y && rect.width === lastRect.width && rect.height === lastRect.height && rect.width > 0 && rect.height > 0;\n lastRect = rect;\n return !!isDisplayedAndStable;\n });\n return { status: result === 'notconnected' ? 'notconnected' : (result ? 'success' : 'timeout') };\n }\n async waitForHitTargetAt(node, timeout, point) {\n let element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\n while (element && window.getComputedStyle(element).pointerEvents === 'none')\n element = element.parentElement;\n if (!element)\n return { status: 'notconnected' };\n const result = await this.poll('raf', timeout, () => {\n if (!element.isConnected)\n return 'notconnected';\n let hitElement = this._deepElementFromPoint(document, point.x, point.y);\n while (hitElement && hitElement !== element)\n hitElement = this._parentElementOrShadowHost(hitElement);\n return hitElement === element;\n });\n return { status: result === 'notconnected' ? 'notconnected' : (result ? 'success' : 'timeout') };\n }\n _parentElementOrShadowHost(element) {\n if (element.parentElement)\n return element.parentElement;\n if (!element.parentNode)\n return;\n if (element.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE && element.parentNode.host)\n return element.parentNode.host;\n }\n _deepElementFromPoint(document, x, y) {\n let container = document;\n let element;\n while (container) {\n const innerElement = container.elementFromPoint(x, y);\n if (!innerElement || element === innerElement)\n break;\n element = innerElement;\n container = element.shadowRoot;\n }\n return element;\n }\n}\nexports.Injected = Injected;\n\n\n/***/ }),\n\n/***/ \"./src/injected/selectorEvaluator.ts\":\n/*!*******************************************!*\\\n !*** ./src/injected/selectorEvaluator.ts ***!\n \\*******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst attributeSelectorEngine_1 = __webpack_require__(/*! ./attributeSelectorEngine */ \"./src/injected/attributeSelectorEngine.ts\");\nconst cssSelectorEngine_1 = __webpack_require__(/*! ./cssSelectorEngine */ \"./src/injected/cssSelectorEngine.ts\");\nconst injected_1 = __webpack_require__(/*! ./injected */ \"./src/injected/injected.ts\");\nconst textSelectorEngine_1 = __webpack_require__(/*! ./textSelectorEngine */ \"./src/injected/textSelectorEngine.ts\");\nconst xpathSelectorEngine_1 = __webpack_require__(/*! ./xpathSelectorEngine */ \"./src/injected/xpathSelectorEngine.ts\");\nclass SelectorEvaluator {\n constructor(customEngines) {\n this.injected = new injected_1.Injected();\n this.engines = new Map();\n // Note: keep predefined names in sync with Selectors class.\n this.engines.set('css', cssSelectorEngine_1.createCSSEngine(true));\n this.engines.set('css:light', cssSelectorEngine_1.createCSSEngine(false));\n this.engines.set('xpath', xpathSelectorEngine_1.XPathEngine);\n this.engines.set('xpath:light', xpathSelectorEngine_1.XPathEngine);\n this.engines.set('text', textSelectorEngine_1.createTextSelector(true));\n this.engines.set('text:light', textSelectorEngine_1.createTextSelector(false));\n this.engines.set('id', attributeSelectorEngine_1.createAttributeEngine('id', true));\n this.engines.set('id:light', attributeSelectorEngine_1.createAttributeEngine('id', false));\n this.engines.set('data-testid', attributeSelectorEngine_1.createAttributeEngine('data-testid', true));\n this.engines.set('data-testid:light', attributeSelectorEngine_1.createAttributeEngine('data-testid', false));\n this.engines.set('data-test-id', attributeSelectorEngine_1.createAttributeEngine('data-test-id', true));\n this.engines.set('data-test-id:light', attributeSelectorEngine_1.createAttributeEngine('data-test-id', false));\n this.engines.set('data-test', attributeSelectorEngine_1.createAttributeEngine('data-test', true));\n this.engines.set('data-test:light', attributeSelectorEngine_1.createAttributeEngine('data-test', false));\n for (const { name, engine } of customEngines)\n this.engines.set(name, engine);\n }\n querySelector(selector, root) {\n if (!root['querySelector'])\n throw new Error('Node is not queryable.');\n return this._querySelectorRecursively(root, selector, 0);\n }\n _querySelectorRecursively(root, selector, index) {\n const current = selector[index];\n if (index === selector.length - 1)\n return this.engines.get(current.name).query(root, current.body);\n const all = this.engines.get(current.name).queryAll(root, current.body);\n for (const next of all) {\n const result = this._querySelectorRecursively(next, selector, index + 1);\n if (result)\n return result;\n }\n }\n querySelectorAll(selector, root) {\n if (!root['querySelectorAll'])\n throw new Error('Node is not queryable.');\n let set = new Set([root]);\n for (const { name, body } of selector) {\n const newSet = new Set();\n for (const prev of set) {\n for (const next of this.engines.get(name).queryAll(prev, body)) {\n if (newSet.has(next))\n continue;\n newSet.add(next);\n }\n }\n set = newSet;\n }\n return Array.from(set);\n }\n}\nexports.default = SelectorEvaluator;\n\n\n/***/ }),\n\n/***/ \"./src/injected/textSelectorEngine.ts\":\n/*!********************************************!*\\\n !*** ./src/injected/textSelectorEngine.ts ***!\n \\********************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction createTextSelector(shadow) {\n const engine = {\n create(root, targetElement, type) {\n const document = root instanceof Document ? root : root.ownerDocument;\n if (!document)\n return;\n for (let child = targetElement.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === 3 /* Node.TEXT_NODE */) {\n const text = child.nodeValue;\n if (!text)\n continue;\n if (text.match(/^\\s*[a-zA-Z0-9]+\\s*$/) && engine.query(root, text.trim()) === targetElement)\n return text.trim();\n if (queryInternal(root, createMatcher(JSON.stringify(text)), shadow) === targetElement)\n return JSON.stringify(text);\n }\n }\n },\n query(root, selector) {\n return queryInternal(root, createMatcher(selector), shadow);\n },\n queryAll(root, selector) {\n const result = [];\n queryAllInternal(root, createMatcher(selector), shadow, result);\n return result;\n }\n };\n return engine;\n}\nexports.createTextSelector = createTextSelector;\nfunction createMatcher(selector) {\n if (selector[0] === '\"' && selector[selector.length - 1] === '\"') {\n const parsed = JSON.parse(selector);\n return text => text === parsed;\n }\n if (selector[0] === '/' && selector.lastIndexOf('/') > 0) {\n const lastSlash = selector.lastIndexOf('/');\n const re = new RegExp(selector.substring(1, lastSlash), selector.substring(lastSlash + 1));\n return text => re.test(text);\n }\n selector = selector.trim().toLowerCase();\n return text => text.toLowerCase().includes(selector);\n}\nfunction queryInternal(root, matcher, shadow) {\n const document = root instanceof Document ? root : root.ownerDocument;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT);\n const shadowRoots = [];\n if (shadow && root.shadowRoot)\n shadowRoots.push(root.shadowRoot);\n while (walker.nextNode()) {\n const node = walker.currentNode;\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node;\n if ((element instanceof HTMLInputElement) && (element.type === 'submit' || element.type === 'button') && matcher(element.value))\n return element;\n if (shadow && element.shadowRoot)\n shadowRoots.push(element.shadowRoot);\n }\n else {\n const element = node.parentElement;\n const text = node.nodeValue;\n if (element && element.nodeName !== 'SCRIPT' && element.nodeName !== 'STYLE' && text && matcher(text))\n return element;\n }\n }\n for (const shadowRoot of shadowRoots) {\n const element = queryInternal(shadowRoot, matcher, shadow);\n if (element)\n return element;\n }\n}\nfunction queryAllInternal(root, matcher, shadow, result) {\n const document = root instanceof Document ? root : root.ownerDocument;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT);\n const shadowRoots = [];\n if (shadow && root.shadowRoot)\n shadowRoots.push(root.shadowRoot);\n while (walker.nextNode()) {\n const node = walker.currentNode;\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node;\n if ((element instanceof HTMLInputElement) && (element.type === 'submit' || element.type === 'button') && matcher(element.value))\n result.push(element);\n if (shadow && element.shadowRoot)\n shadowRoots.push(element.shadowRoot);\n }\n else {\n const element = node.parentElement;\n const text = node.nodeValue;\n if (element && element.nodeName !== 'SCRIPT' && element.nodeName !== 'STYLE' && text && matcher(text))\n result.push(element);\n }\n }\n for (const shadowRoot of shadowRoots)\n queryAllInternal(shadowRoot, matcher, shadow, result);\n}\n\n\n/***/ }),\n\n/***/ \"./src/injected/xpathSelectorEngine.ts\":\n/*!*********************************************!*\\\n !*** ./src/injected/xpathSelectorEngine.ts ***!\n \\*********************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst maxTextLength = 80;\nconst minMeaningfulSelectorLegth = 100;\nexports.XPathEngine = {\n create(root, targetElement, type) {\n const maybeDocument = root instanceof Document ? root : root.ownerDocument;\n if (!maybeDocument)\n return;\n const document = maybeDocument;\n const xpathCache = new Map();\n if (type === 'notext')\n return createNoText(root, targetElement);\n const tokens = [];\n function evaluateXPath(expression) {\n let nodes = xpathCache.get(expression);\n if (!nodes) {\n nodes = [];\n try {\n const result = document.evaluate(expression, root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE);\n for (let node = result.iterateNext(); node; node = result.iterateNext()) {\n if (node.nodeType === Node.ELEMENT_NODE)\n nodes.push(node);\n }\n }\n catch (e) {\n }\n xpathCache.set(expression, nodes);\n }\n return nodes;\n }\n function uniqueXPathSelector(prefix) {\n const path = tokens.slice();\n if (prefix)\n path.unshift(prefix);\n let selector = '//' + path.join('/');\n while (selector.includes('///'))\n selector = selector.replace('///', '//');\n if (selector.endsWith('/'))\n selector = selector.substring(0, selector.length - 1);\n const nodes = evaluateXPath(selector);\n if (nodes[nodes.length - 1] === targetElement)\n return selector;\n // If we are looking at a small set of elements with long selector, fall back to ordinal.\n if (nodes.length < 5 && selector.length > minMeaningfulSelectorLegth) {\n const index = nodes.indexOf(targetElement);\n if (index !== -1)\n return `(${selector})[${index + 1}]`;\n }\n return undefined;\n }\n function escapeAndCap(text) {\n text = text.substring(0, maxTextLength);\n // XPath 1.0 does not support quote escaping.\n // 1. If there are no single quotes - use them.\n if (text.indexOf(`'`) === -1)\n return `'${text}'`;\n // 2. If there are no double quotes - use them to enclose text.\n if (text.indexOf(`\"`) === -1)\n return `\"${text}\"`;\n // 3. Otherwise, use popular |concat| trick.\n const Q = `'`;\n return `concat(${text.split(Q).map(token => Q + token + Q).join(`, \"'\", `)})`;\n }\n const defaultAttributes = new Set(['title', 'aria-label', 'disabled', 'role']);\n const importantAttributes = new Map([\n ['form', ['action']],\n ['img', ['alt']],\n ['input', ['placeholder', 'type', 'name', 'value']],\n ]);\n let usedTextConditions = false;\n for (let element = targetElement; element && element !== root; element = element.parentElement) {\n const nodeName = element.nodeName.toLowerCase();\n const tag = nodeName === 'svg' ? '*' : nodeName;\n const tagConditions = [];\n if (nodeName === 'svg')\n tagConditions.push('local-name()=\"svg\"');\n const attrConditions = [];\n const importantAttrs = [...defaultAttributes, ...(importantAttributes.get(tag) || [])];\n for (const attr of importantAttrs) {\n const value = element.getAttribute(attr);\n if (value && value.length < maxTextLength)\n attrConditions.push(`normalize-space(@${attr})=${escapeAndCap(value)}`);\n else if (value)\n attrConditions.push(`starts-with(normalize-space(@${attr}), ${escapeAndCap(value)})`);\n }\n const text = document.evaluate('normalize-space(.)', element).stringValue;\n const textConditions = [];\n if (tag !== 'select' && text.length && !usedTextConditions) {\n if (text.length < maxTextLength)\n textConditions.push(`normalize-space(.)=${escapeAndCap(text)}`);\n else\n textConditions.push(`starts-with(normalize-space(.), ${escapeAndCap(text)})`);\n usedTextConditions = true;\n }\n // Always retain the last tag.\n const conditions = [...tagConditions, ...textConditions, ...attrConditions];\n const token = conditions.length ? `${tag}[${conditions.join(' and ')}]` : (tokens.length ? '' : tag);\n const selector = uniqueXPathSelector(token);\n if (selector)\n return selector;\n // Ordinal is the weakest signal.\n const parent = element.parentElement;\n let tagWithOrdinal = tag;\n if (parent) {\n const siblings = Array.from(parent.children);\n const sameTagSiblings = siblings.filter(sibling => (sibling).nodeName.toLowerCase() === nodeName);\n if (sameTagSiblings.length > 1)\n tagWithOrdinal += `[${1 + siblings.indexOf(element)}]`;\n }\n // Do not include text into this token, only tag / attributes.\n // Topmost node will get all the text.\n const nonTextConditions = [...tagConditions, ...attrConditions];\n const levelToken = nonTextConditions.length ? `${tagWithOrdinal}[${nonTextConditions.join(' and ')}]` : tokens.length ? '' : tagWithOrdinal;\n tokens.unshift(levelToken);\n }\n return uniqueXPathSelector();\n },\n query(root, selector) {\n const document = root instanceof Document ? root : root.ownerDocument;\n if (!document)\n return;\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 return node;\n }\n },\n queryAll(root, selector) {\n const result = [];\n const document = root instanceof Document ? root : root.ownerDocument;\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};\nfunction createNoText(root, targetElement) {\n const steps = [];\n for (let element = targetElement; element && element !== root; element = element.parentElement) {\n if (element.getAttribute('id')) {\n steps.unshift(`//*[@id=\"${element.getAttribute('id')}\"]`);\n return steps.join('/');\n }\n const siblings = element.parentElement ? Array.from(element.parentElement.children) : [];\n const similarElements = siblings.filter(sibling => element.nodeName === sibling.nodeName);\n const index = similarElements.length === 1 ? 0 : similarElements.indexOf(element) + 1;\n steps.unshift(index ? `${element.nodeName}[${index}]` : element.nodeName);\n }\n return '/' + steps.join('/');\n}\n\n\n/***/ })\n\n/******/ })).default";
exports.source = "(/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = \"./src/injected/selectorEvaluator.ts\");\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ \"./src/injected/attributeSelectorEngine.ts\":\n/*!*************************************************!*\\\n !*** ./src/injected/attributeSelectorEngine.ts ***!\n \\*************************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction createAttributeEngine(attribute, shadow) {\n const engine = {\n create(root, target) {\n const value = target.getAttribute(attribute);\n if (!value)\n return;\n if (engine.query(root, value) === target)\n return value;\n },\n query(root, selector) {\n if (!shadow)\n return root.querySelector(`[${attribute}=${JSON.stringify(selector)}]`) || undefined;\n return queryShadowInternal(root, attribute, selector);\n },\n queryAll(root, selector) {\n if (!shadow)\n return Array.from(root.querySelectorAll(`[${attribute}=${JSON.stringify(selector)}]`));\n const result = [];\n queryShadowAllInternal(root, attribute, selector, result);\n return result;\n }\n };\n return engine;\n}\nexports.createAttributeEngine = createAttributeEngine;\nfunction queryShadowInternal(root, attribute, value) {\n const single = root.querySelector(`[${attribute}=${JSON.stringify(value)}]`);\n if (single)\n return single;\n const all = root.querySelectorAll('*');\n for (let i = 0; i < all.length; i++) {\n const shadowRoot = all[i].shadowRoot;\n if (shadowRoot) {\n const single = queryShadowInternal(shadowRoot, attribute, value);\n if (single)\n return single;\n }\n }\n}\nfunction queryShadowAllInternal(root, attribute, value, result) {\n const document = root instanceof Document ? root : root.ownerDocument;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);\n const shadowRoots = [];\n while (walker.nextNode()) {\n const element = walker.currentNode;\n if (element.getAttribute(attribute) === value)\n result.push(element);\n if (element.shadowRoot)\n shadowRoots.push(element.shadowRoot);\n }\n for (const shadowRoot of shadowRoots)\n queryShadowAllInternal(shadowRoot, attribute, value, result);\n}\n\n\n/***/ }),\n\n/***/ \"./src/injected/cssSelectorEngine.ts\":\n/*!*******************************************!*\\\n !*** ./src/injected/cssSelectorEngine.ts ***!\n \\*******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction createCSSEngine(shadow) {\n const engine = {\n create(root, targetElement) {\n if (shadow)\n return;\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 nodes = Array.from(root.querySelectorAll(selector));\n return nodes[0] === targetElement ? selector : undefined;\n }\n for (let element = targetElement; element && element !== root; element = element.parentElement) {\n const nodeName = element.nodeName.toLowerCase();\n // Element ID is the strongest signal, use it.\n let bestTokenForLevel = '';\n if (element.id) {\n const token = /^[a-zA-Z][a-zA-Z0-9\\-\\_]+$/.test(element.id) ? '#' + element.id : `[id=\"${element.id}\"]`;\n const selector = uniqueCSSSelector(token);\n if (selector)\n return selector;\n bestTokenForLevel = token;\n }\n const parent = element.parentElement;\n // Combine class names until unique.\n const classes = Array.from(element.classList);\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 selector;\n // Even if not unique, does this subset of classes uniquely identify node as a child?\n if (!bestTokenForLevel && parent) {\n const sameClassSiblings = parent.querySelectorAll(token);\n if (sameClassSiblings.length === 1)\n bestTokenForLevel = token;\n }\n }\n // Ordinal is the weakest signal.\n if (parent) {\n const siblings = Array.from(parent.children);\n const sameTagSiblings = siblings.filter(sibling => (sibling).nodeName.toLowerCase() === nodeName);\n const token = sameTagSiblings.length === 1 ? nodeName : `${nodeName}:nth-child(${1 + siblings.indexOf(element)})`;\n const selector = uniqueCSSSelector(token);\n if (selector)\n return selector;\n if (!bestTokenForLevel)\n bestTokenForLevel = token;\n }\n else if (!bestTokenForLevel) {\n bestTokenForLevel = nodeName;\n }\n tokens.unshift(bestTokenForLevel);\n }\n return uniqueCSSSelector();\n },\n query(root, selector) {\n const simple = root.querySelector(selector);\n if (simple)\n return simple;\n if (!shadow)\n return;\n const parts = split(selector);\n if (!parts.length)\n return;\n parts.reverse();\n return queryShadowInternal(root, root, parts);\n },\n queryAll(root, selector) {\n if (!shadow)\n return Array.from(root.querySelectorAll(selector));\n const result = [];\n const parts = split(selector);\n if (parts.length) {\n parts.reverse();\n queryShadowAllInternal(root, root, parts, result);\n }\n return result;\n }\n };\n engine._test = () => test(engine);\n return engine;\n}\nexports.createCSSEngine = createCSSEngine;\nfunction queryShadowInternal(boundary, root, parts) {\n const matching = root.querySelectorAll(parts[0]);\n for (let i = 0; i < matching.length; i++) {\n const element = matching[i];\n if (parts.length === 1 || matches(element, parts, boundary))\n return element;\n }\n if (root.shadowRoot) {\n const child = queryShadowInternal(boundary, root.shadowRoot, parts);\n if (child)\n return child;\n }\n const elements = root.querySelectorAll('*');\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n if (element.shadowRoot) {\n const child = queryShadowInternal(boundary, element.shadowRoot, parts);\n if (child)\n return child;\n }\n }\n}\nfunction queryShadowAllInternal(boundary, root, parts, result) {\n const matching = root.querySelectorAll(parts[0]);\n for (let i = 0; i < matching.length; i++) {\n const element = matching[i];\n if (parts.length === 1 || matches(element, parts, boundary))\n result.push(element);\n }\n if (root.shadowRoot)\n queryShadowAllInternal(boundary, root.shadowRoot, parts, result);\n const elements = root.querySelectorAll('*');\n for (let i = 0; i < elements.length; i++) {\n const element = elements[i];\n if (element.shadowRoot)\n queryShadowAllInternal(boundary, element.shadowRoot, parts, result);\n }\n}\nfunction matches(element, parts, boundary) {\n let i = 1;\n while (i < parts.length && (element = parentElementOrShadowHost(element)) && element !== boundary) {\n if (element.matches(parts[i]))\n i++;\n }\n return i === parts.length;\n}\nfunction parentElementOrShadowHost(element) {\n if (element.parentElement)\n return element.parentElement;\n if (!element.parentNode)\n return;\n if (element.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE && element.parentNode.host)\n return element.parentNode.host;\n}\nfunction split(selector) {\n let index = 0;\n let quote;\n let start = 0;\n let space = 'none';\n const result = [];\n const append = () => {\n const part = selector.substring(start, index).trim();\n if (part.length)\n result.push(part);\n };\n while (index < selector.length) {\n const c = selector[index];\n if (!quote && c === ' ') {\n if (space === 'none' || space === 'before')\n space = 'before';\n index++;\n }\n else {\n if (space === 'before') {\n if (c === '>' || c === '+' || c === '~') {\n space = 'after';\n }\n else {\n append();\n start = index;\n space = 'none';\n }\n }\n else {\n space = 'none';\n }\n if (c === '\\\\' && index + 1 < selector.length) {\n index += 2;\n }\n else if (c === quote) {\n quote = undefined;\n index++;\n }\n else {\n index++;\n }\n }\n }\n append();\n return result;\n}\nfunction test(engine) {\n let id = 0;\n function createShadow(level) {\n const root = document.createElement('div');\n root.id = 'id' + id;\n root.textContent = 'root #id' + id;\n id++;\n const shadow = root.attachShadow({ mode: 'open' });\n for (let i = 0; i < 9; i++) {\n const div = document.createElement('div');\n div.id = 'id' + id;\n div.textContent = '#id' + id;\n id++;\n shadow.appendChild(div);\n }\n if (level) {\n shadow.appendChild(createShadow(level - 1));\n shadow.appendChild(createShadow(level - 1));\n }\n return root;\n }\n const { query, queryAll } = engine;\n document.body.textContent = '';\n document.body.appendChild(createShadow(10));\n console.time('found');\n for (let i = 0; i < id; i += 17) {\n const e = query(document, `div #id${i}`);\n if (!e || e.id !== 'id' + i)\n console.log(`div #id${i}`); // eslint-disable-line no-console\n }\n console.timeEnd('found');\n console.time('not found');\n for (let i = 0; i < id; i += 17) {\n const e = query(document, `div div div div div #d${i}`);\n if (e)\n console.log(`div div div div div #d${i}`); // eslint-disable-line no-console\n }\n console.timeEnd('not found');\n console.log(query(document, '#id543 + #id544')); // eslint-disable-line no-console\n console.log(query(document, '#id542 ~ #id545')); // eslint-disable-line no-console\n console.time('all');\n queryAll(document, 'div div div + div');\n console.timeEnd('all');\n}\n\n\n/***/ }),\n\n/***/ \"./src/injected/injected.ts\":\n/*!**********************************!*\\\n !*** ./src/injected/injected.ts ***!\n \\**********************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nclass Injected {\n isVisible(element) {\n if (!element.ownerDocument || !element.ownerDocument.defaultView)\n return true;\n const style = element.ownerDocument.defaultView.getComputedStyle(element);\n if (!style || style.visibility === 'hidden')\n return false;\n const rect = element.getBoundingClientRect();\n return !!(rect.top || rect.bottom || rect.width || rect.height);\n }\n _pollMutation(predicate, timeout) {\n let timedOut = false;\n if (timeout)\n setTimeout(() => timedOut = true, timeout);\n const success = predicate();\n if (success)\n return Promise.resolve(success);\n let fulfill;\n const result = new Promise(x => fulfill = x);\n const observer = new MutationObserver(() => {\n if (timedOut) {\n observer.disconnect();\n fulfill();\n return;\n }\n const success = predicate();\n if (success) {\n observer.disconnect();\n fulfill(success);\n }\n });\n observer.observe(document, {\n childList: true,\n subtree: true,\n attributes: true\n });\n return result;\n }\n _pollRaf(predicate, timeout) {\n let timedOut = false;\n if (timeout)\n setTimeout(() => timedOut = true, timeout);\n let fulfill;\n const result = new Promise(x => fulfill = x);\n const onRaf = () => {\n if (timedOut) {\n fulfill();\n return;\n }\n const success = predicate();\n if (success)\n fulfill(success);\n else\n requestAnimationFrame(onRaf);\n };\n onRaf();\n return result;\n }\n _pollInterval(pollInterval, predicate, timeout) {\n let timedOut = false;\n if (timeout)\n setTimeout(() => timedOut = true, timeout);\n let fulfill;\n const result = new Promise(x => fulfill = x);\n const onTimeout = () => {\n if (timedOut) {\n fulfill();\n return;\n }\n const success = predicate();\n if (success)\n fulfill(success);\n else\n setTimeout(onTimeout, pollInterval);\n };\n onTimeout();\n return result;\n }\n poll(polling, timeout, predicate) {\n if (polling === 'raf')\n return this._pollRaf(predicate, timeout);\n if (polling === 'mutation')\n return this._pollMutation(predicate, timeout);\n return this._pollInterval(polling, predicate, timeout);\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 selectOptions(node, optionsToSelect) {\n if (node.nodeName.toLowerCase() !== 'select')\n return { status: 'error', error: 'Element is not a <select> element.' };\n if (!node.isConnected)\n return { status: 'notconnected' };\n const element = node;\n const options = Array.from(element.options);\n element.value = undefined;\n for (let index = 0; index < options.length; index++) {\n const option = options[index];\n option.selected = optionsToSelect.some(optionToSelect => {\n if (optionToSelect instanceof Node)\n return option === optionToSelect;\n let matches = true;\n if (optionToSelect.value !== undefined)\n matches = matches && optionToSelect.value === option.value;\n if (optionToSelect.label !== undefined)\n matches = matches && optionToSelect.label === option.label;\n if (optionToSelect.index !== undefined)\n matches = matches && optionToSelect.index === index;\n return matches;\n });\n if (option.selected && !element.multiple)\n break;\n }\n element.dispatchEvent(new Event('input', { 'bubbles': true }));\n element.dispatchEvent(new Event('change', { 'bubbles': true }));\n return { status: 'success', value: options.filter(option => option.selected).map(option => option.value) };\n }\n fill(node, value) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n return { status: 'error', error: 'Node is not of type HTMLElement' };\n const element = node;\n if (!element.isConnected)\n return { status: 'notconnected' };\n if (!this.isVisible(element))\n return { status: 'error', error: 'Element is not visible' };\n if (element.nodeName.toLowerCase() === 'input') {\n const input = element;\n const type = (input.getAttribute('type') || '').toLowerCase();\n const kDateTypes = new Set(['date', 'time', 'datetime', 'datetime-local']);\n const kTextInputTypes = new Set(['', 'email', 'number', 'password', 'search', 'tel', 'text', 'url']);\n if (!kTextInputTypes.has(type) && !kDateTypes.has(type))\n return { status: 'error', error: 'Cannot fill input of type \"' + type + '\".' };\n if (type === 'number') {\n value = value.trim();\n if (!value || isNaN(Number(value)))\n return { status: 'error', error: 'Cannot type text into input[type=number].' };\n }\n if (input.disabled)\n return { status: 'error', error: 'Cannot fill a disabled input.' };\n if (input.readOnly)\n return { status: 'error', error: 'Cannot fill a readonly input.' };\n if (kDateTypes.has(type)) {\n value = value.trim();\n input.focus();\n input.value = value;\n if (input.value !== value)\n return { status: 'error', error: `Malformed ${type} \"${value}\"` };\n element.dispatchEvent(new Event('input', { 'bubbles': true }));\n element.dispatchEvent(new Event('change', { 'bubbles': true }));\n return { status: 'success', value: false }; // We have already changed the value, no need to input it.\n }\n }\n else if (element.nodeName.toLowerCase() === 'textarea') {\n const textarea = element;\n if (textarea.disabled)\n return { status: 'error', error: 'Cannot fill a disabled textarea.' };\n if (textarea.readOnly)\n return { status: 'error', error: 'Cannot fill a readonly textarea.' };\n }\n else if (!element.isContentEditable) {\n return { status: 'error', error: 'Element is not an <input>, <textarea> or [contenteditable] element.' };\n }\n const result = this.selectText(node);\n if (result.status === 'success')\n return { status: 'success', value: true }; // Still need to input the value.\n return result;\n }\n selectText(node) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n return { status: 'error', error: 'Node is not of type HTMLElement' };\n if (!node.isConnected)\n return { status: 'notconnected' };\n const element = node;\n if (!this.isVisible(element))\n return { status: 'error', error: 'Element is not visible' };\n if (element.nodeName.toLowerCase() === 'input') {\n const input = element;\n input.select();\n input.focus();\n return { status: 'success' };\n }\n if (element.nodeName.toLowerCase() === 'textarea') {\n const textarea = element;\n textarea.selectionStart = 0;\n textarea.selectionEnd = textarea.value.length;\n textarea.focus();\n return { status: 'success' };\n }\n const range = element.ownerDocument.createRange();\n range.selectNodeContents(element);\n const selection = element.ownerDocument.defaultView.getSelection();\n if (!selection)\n return { status: 'error', error: 'Element belongs to invisible iframe.' };\n selection.removeAllRanges();\n selection.addRange(range);\n element.focus();\n return { status: 'success' };\n }\n focusNode(node) {\n if (!node.isConnected)\n return { status: 'notconnected' };\n if (!node['focus'])\n return { status: 'error', error: 'Node is not an HTML or SVG element.' };\n node.focus();\n return { status: 'success' };\n }\n isCheckboxChecked(node) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n throw new Error('Not a checkbox or radio button');\n let element = node;\n if (element.getAttribute('role') === 'checkbox')\n return element.getAttribute('aria-checked') === 'true';\n if (element.nodeName === 'LABEL') {\n const forId = element.getAttribute('for');\n if (forId && element.ownerDocument)\n element = element.ownerDocument.querySelector(`input[id=\"${forId}\"]`) || undefined;\n else\n element = element.querySelector('input[type=checkbox],input[type=radio]') || undefined;\n }\n if (element && element.nodeName === 'INPUT') {\n const type = element.getAttribute('type');\n if (type && (type.toLowerCase() === 'checkbox' || type.toLowerCase() === 'radio'))\n return element.checked;\n }\n throw new Error('Not a checkbox');\n }\n async setInputFiles(node, payloads) {\n if (node.nodeType !== Node.ELEMENT_NODE)\n return 'Node is not of type HTMLElement';\n const element = node;\n if (element.nodeName !== 'INPUT')\n return 'Not an <input> element';\n const input = element;\n const type = (input.getAttribute('type') || '').toLowerCase();\n if (type !== 'file')\n return 'Not an input[type=file] element';\n const files = await Promise.all(payloads.map(async (file) => {\n const result = await fetch(`data:${file.type};base64,${file.data}`);\n return new File([await result.blob()], file.name, { type: file.type });\n }));\n const dt = new DataTransfer();\n for (const file of files)\n dt.items.add(file);\n input.files = dt.files;\n input.dispatchEvent(new Event('input', { 'bubbles': true }));\n input.dispatchEvent(new Event('change', { 'bubbles': true }));\n }\n async waitForDisplayedAtStablePosition(node, timeout) {\n if (!node.isConnected)\n return { status: 'notconnected' };\n const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\n if (!element)\n return { status: 'notconnected' };\n let lastRect;\n let counter = 0;\n const result = await this.poll('raf', timeout, () => {\n // First raf happens in the same animation frame as evaluation, so it does not produce\n // any client rect difference compared to synchronous call. We skip the synchronous call\n // and only force layout during actual rafs as a small optimisation.\n if (++counter === 1)\n return false;\n if (!node.isConnected)\n return 'notconnected';\n const clientRect = element.getBoundingClientRect();\n const rect = { x: clientRect.top, y: clientRect.left, width: clientRect.width, height: clientRect.height };\n const isDisplayedAndStable = lastRect && rect.x === lastRect.x && rect.y === lastRect.y && rect.width === lastRect.width && rect.height === lastRect.height && rect.width > 0 && rect.height > 0;\n lastRect = rect;\n return !!isDisplayedAndStable;\n });\n return { status: result === 'notconnected' ? 'notconnected' : (result ? 'success' : 'timeout') };\n }\n async waitForHitTargetAt(node, timeout, point) {\n const targetElement = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;\n let element = targetElement;\n while (element && window.getComputedStyle(element).pointerEvents === 'none')\n element = element.parentElement;\n if (!element)\n return { status: 'notconnected' };\n const result = await this.poll('raf', timeout, () => {\n if (!element.isConnected)\n return 'notconnected';\n const clientRect = targetElement.getBoundingClientRect();\n if (clientRect.left > point.x || clientRect.left + clientRect.width < point.x ||\n clientRect.top > point.y || clientRect.top + clientRect.height < point.y)\n return 'moved';\n let hitElement = this._deepElementFromPoint(document, point.x, point.y);\n while (hitElement && hitElement !== element)\n hitElement = this._parentElementOrShadowHost(hitElement);\n return hitElement === element;\n });\n if (result === 'notconnected')\n return { status: 'notconnected' };\n if (result === 'moved')\n return { status: 'error', error: 'Element has moved during the action' };\n return { status: result ? 'success' : 'timeout' };\n }\n _parentElementOrShadowHost(element) {\n if (element.parentElement)\n return element.parentElement;\n if (!element.parentNode)\n return;\n if (element.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE && element.parentNode.host)\n return element.parentNode.host;\n }\n _deepElementFromPoint(document, x, y) {\n let container = document;\n let element;\n while (container) {\n const innerElement = container.elementFromPoint(x, y);\n if (!innerElement || element === innerElement)\n break;\n element = innerElement;\n container = element.shadowRoot;\n }\n return element;\n }\n}\nexports.Injected = Injected;\n\n\n/***/ }),\n\n/***/ \"./src/injected/selectorEvaluator.ts\":\n/*!*******************************************!*\\\n !*** ./src/injected/selectorEvaluator.ts ***!\n \\*******************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst attributeSelectorEngine_1 = __webpack_require__(/*! ./attributeSelectorEngine */ \"./src/injected/attributeSelectorEngine.ts\");\nconst cssSelectorEngine_1 = __webpack_require__(/*! ./cssSelectorEngine */ \"./src/injected/cssSelectorEngine.ts\");\nconst injected_1 = __webpack_require__(/*! ./injected */ \"./src/injected/injected.ts\");\nconst textSelectorEngine_1 = __webpack_require__(/*! ./textSelectorEngine */ \"./src/injected/textSelectorEngine.ts\");\nconst xpathSelectorEngine_1 = __webpack_require__(/*! ./xpathSelectorEngine */ \"./src/injected/xpathSelectorEngine.ts\");\nclass SelectorEvaluator {\n constructor(customEngines) {\n this.injected = new injected_1.Injected();\n this.engines = new Map();\n // Note: keep predefined names in sync with Selectors class.\n this.engines.set('css', cssSelectorEngine_1.createCSSEngine(true));\n this.engines.set('css:light', cssSelectorEngine_1.createCSSEngine(false));\n this.engines.set('xpath', xpathSelectorEngine_1.XPathEngine);\n this.engines.set('xpath:light', xpathSelectorEngine_1.XPathEngine);\n this.engines.set('text', textSelectorEngine_1.createTextSelector(true));\n this.engines.set('text:light', textSelectorEngine_1.createTextSelector(false));\n this.engines.set('id', attributeSelectorEngine_1.createAttributeEngine('id', true));\n this.engines.set('id:light', attributeSelectorEngine_1.createAttributeEngine('id', false));\n this.engines.set('data-testid', attributeSelectorEngine_1.createAttributeEngine('data-testid', true));\n this.engines.set('data-testid:light', attributeSelectorEngine_1.createAttributeEngine('data-testid', false));\n this.engines.set('data-test-id', attributeSelectorEngine_1.createAttributeEngine('data-test-id', true));\n this.engines.set('data-test-id:light', attributeSelectorEngine_1.createAttributeEngine('data-test-id', false));\n this.engines.set('data-test', attributeSelectorEngine_1.createAttributeEngine('data-test', true));\n this.engines.set('data-test:light', attributeSelectorEngine_1.createAttributeEngine('data-test', false));\n for (const { name, engine } of customEngines)\n this.engines.set(name, engine);\n }\n querySelector(selector, root) {\n if (!root['querySelector'])\n throw new Error('Node is not queryable.');\n return this._querySelectorRecursively(root, selector, 0);\n }\n _querySelectorRecursively(root, selector, index) {\n const current = selector[index];\n if (index === selector.length - 1)\n return this.engines.get(current.name).query(root, current.body);\n const all = this.engines.get(current.name).queryAll(root, current.body);\n for (const next of all) {\n const result = this._querySelectorRecursively(next, selector, index + 1);\n if (result)\n return result;\n }\n }\n querySelectorAll(selector, root) {\n if (!root['querySelectorAll'])\n throw new Error('Node is not queryable.');\n let set = new Set([root]);\n for (const { name, body } of selector) {\n const newSet = new Set();\n for (const prev of set) {\n for (const next of this.engines.get(name).queryAll(prev, body)) {\n if (newSet.has(next))\n continue;\n newSet.add(next);\n }\n }\n set = newSet;\n }\n return Array.from(set);\n }\n}\nexports.default = SelectorEvaluator;\n\n\n/***/ }),\n\n/***/ \"./src/injected/textSelectorEngine.ts\":\n/*!********************************************!*\\\n !*** ./src/injected/textSelectorEngine.ts ***!\n \\********************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nfunction createTextSelector(shadow) {\n const engine = {\n create(root, targetElement, type) {\n const document = root instanceof Document ? root : root.ownerDocument;\n if (!document)\n return;\n for (let child = targetElement.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === 3 /* Node.TEXT_NODE */) {\n const text = child.nodeValue;\n if (!text)\n continue;\n if (text.match(/^\\s*[a-zA-Z0-9]+\\s*$/) && engine.query(root, text.trim()) === targetElement)\n return text.trim();\n if (queryInternal(root, createMatcher(JSON.stringify(text)), shadow) === targetElement)\n return JSON.stringify(text);\n }\n }\n },\n query(root, selector) {\n return queryInternal(root, createMatcher(selector), shadow);\n },\n queryAll(root, selector) {\n const result = [];\n queryAllInternal(root, createMatcher(selector), shadow, result);\n return result;\n }\n };\n return engine;\n}\nexports.createTextSelector = createTextSelector;\nfunction createMatcher(selector) {\n if (selector[0] === '\"' && selector[selector.length - 1] === '\"') {\n const parsed = JSON.parse(selector);\n return text => text === parsed;\n }\n if (selector[0] === '/' && selector.lastIndexOf('/') > 0) {\n const lastSlash = selector.lastIndexOf('/');\n const re = new RegExp(selector.substring(1, lastSlash), selector.substring(lastSlash + 1));\n return text => re.test(text);\n }\n selector = selector.trim().toLowerCase();\n return text => text.toLowerCase().includes(selector);\n}\nfunction queryInternal(root, matcher, shadow) {\n const document = root instanceof Document ? root : root.ownerDocument;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT);\n const shadowRoots = [];\n if (shadow && root.shadowRoot)\n shadowRoots.push(root.shadowRoot);\n while (walker.nextNode()) {\n const node = walker.currentNode;\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node;\n if ((element instanceof HTMLInputElement) && (element.type === 'submit' || element.type === 'button') && matcher(element.value))\n return element;\n if (shadow && element.shadowRoot)\n shadowRoots.push(element.shadowRoot);\n }\n else {\n const element = node.parentElement;\n const text = node.nodeValue;\n if (element && element.nodeName !== 'SCRIPT' && element.nodeName !== 'STYLE' && text && matcher(text))\n return element;\n }\n }\n for (const shadowRoot of shadowRoots) {\n const element = queryInternal(shadowRoot, matcher, shadow);\n if (element)\n return element;\n }\n}\nfunction queryAllInternal(root, matcher, shadow, result) {\n const document = root instanceof Document ? root : root.ownerDocument;\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT);\n const shadowRoots = [];\n if (shadow && root.shadowRoot)\n shadowRoots.push(root.shadowRoot);\n while (walker.nextNode()) {\n const node = walker.currentNode;\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node;\n if ((element instanceof HTMLInputElement) && (element.type === 'submit' || element.type === 'button') && matcher(element.value))\n result.push(element);\n if (shadow && element.shadowRoot)\n shadowRoots.push(element.shadowRoot);\n }\n else {\n const element = node.parentElement;\n const text = node.nodeValue;\n if (element && element.nodeName !== 'SCRIPT' && element.nodeName !== 'STYLE' && text && matcher(text))\n result.push(element);\n }\n }\n for (const shadowRoot of shadowRoots)\n queryAllInternal(shadowRoot, matcher, shadow, result);\n}\n\n\n/***/ }),\n\n/***/ \"./src/injected/xpathSelectorEngine.ts\":\n/*!*********************************************!*\\\n !*** ./src/injected/xpathSelectorEngine.ts ***!\n \\*********************************************/\n/*! no static exports found */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst maxTextLength = 80;\nconst minMeaningfulSelectorLegth = 100;\nexports.XPathEngine = {\n create(root, targetElement, type) {\n const maybeDocument = root instanceof Document ? root : root.ownerDocument;\n if (!maybeDocument)\n return;\n const document = maybeDocument;\n const xpathCache = new Map();\n if (type === 'notext')\n return createNoText(root, targetElement);\n const tokens = [];\n function evaluateXPath(expression) {\n let nodes = xpathCache.get(expression);\n if (!nodes) {\n nodes = [];\n try {\n const result = document.evaluate(expression, root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE);\n for (let node = result.iterateNext(); node; node = result.iterateNext()) {\n if (node.nodeType === Node.ELEMENT_NODE)\n nodes.push(node);\n }\n }\n catch (e) {\n }\n xpathCache.set(expression, nodes);\n }\n return nodes;\n }\n function uniqueXPathSelector(prefix) {\n const path = tokens.slice();\n if (prefix)\n path.unshift(prefix);\n let selector = '//' + path.join('/');\n while (selector.includes('///'))\n selector = selector.replace('///', '//');\n if (selector.endsWith('/'))\n selector = selector.substring(0, selector.length - 1);\n const nodes = evaluateXPath(selector);\n if (nodes[nodes.length - 1] === targetElement)\n return selector;\n // If we are looking at a small set of elements with long selector, fall back to ordinal.\n if (nodes.length < 5 && selector.length > minMeaningfulSelectorLegth) {\n const index = nodes.indexOf(targetElement);\n if (index !== -1)\n return `(${selector})[${index + 1}]`;\n }\n return undefined;\n }\n function escapeAndCap(text) {\n text = text.substring(0, maxTextLength);\n // XPath 1.0 does not support quote escaping.\n // 1. If there are no single quotes - use them.\n if (text.indexOf(`'`) === -1)\n return `'${text}'`;\n // 2. If there are no double quotes - use them to enclose text.\n if (text.indexOf(`\"`) === -1)\n return `\"${text}\"`;\n // 3. Otherwise, use popular |concat| trick.\n const Q = `'`;\n return `concat(${text.split(Q).map(token => Q + token + Q).join(`, \"'\", `)})`;\n }\n const defaultAttributes = new Set(['title', 'aria-label', 'disabled', 'role']);\n const importantAttributes = new Map([\n ['form', ['action']],\n ['img', ['alt']],\n ['input', ['placeholder', 'type', 'name', 'value']],\n ]);\n let usedTextConditions = false;\n for (let element = targetElement; element && element !== root; element = element.parentElement) {\n const nodeName = element.nodeName.toLowerCase();\n const tag = nodeName === 'svg' ? '*' : nodeName;\n const tagConditions = [];\n if (nodeName === 'svg')\n tagConditions.push('local-name()=\"svg\"');\n const attrConditions = [];\n const importantAttrs = [...defaultAttributes, ...(importantAttributes.get(tag) || [])];\n for (const attr of importantAttrs) {\n const value = element.getAttribute(attr);\n if (value && value.length < maxTextLength)\n attrConditions.push(`normalize-space(@${attr})=${escapeAndCap(value)}`);\n else if (value)\n attrConditions.push(`starts-with(normalize-space(@${attr}), ${escapeAndCap(value)})`);\n }\n const text = document.evaluate('normalize-space(.)', element).stringValue;\n const textConditions = [];\n if (tag !== 'select' && text.length && !usedTextConditions) {\n if (text.length < maxTextLength)\n textConditions.push(`normalize-space(.)=${escapeAndCap(text)}`);\n else\n textConditions.push(`starts-with(normalize-space(.), ${escapeAndCap(text)})`);\n usedTextConditions = true;\n }\n // Always retain the last tag.\n const conditions = [...tagConditions, ...textConditions, ...attrConditions];\n const token = conditions.length ? `${tag}[${conditions.join(' and ')}]` : (tokens.length ? '' : tag);\n const selector = uniqueXPathSelector(token);\n if (selector)\n return selector;\n // Ordinal is the weakest signal.\n const parent = element.parentElement;\n let tagWithOrdinal = tag;\n if (parent) {\n const siblings = Array.from(parent.children);\n const sameTagSiblings = siblings.filter(sibling => (sibling).nodeName.toLowerCase() === nodeName);\n if (sameTagSiblings.length > 1)\n tagWithOrdinal += `[${1 + siblings.indexOf(element)}]`;\n }\n // Do not include text into this token, only tag / attributes.\n // Topmost node will get all the text.\n const nonTextConditions = [...tagConditions, ...attrConditions];\n const levelToken = nonTextConditions.length ? `${tagWithOrdinal}[${nonTextConditions.join(' and ')}]` : tokens.length ? '' : tagWithOrdinal;\n tokens.unshift(levelToken);\n }\n return uniqueXPathSelector();\n },\n query(root, selector) {\n const document = root instanceof Document ? root : root.ownerDocument;\n if (!document)\n return;\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 return node;\n }\n },\n queryAll(root, selector) {\n const result = [];\n const document = root instanceof Document ? root : root.ownerDocument;\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};\nfunction createNoText(root, targetElement) {\n const steps = [];\n for (let element = targetElement; element && element !== root; element = element.parentElement) {\n if (element.getAttribute('id')) {\n steps.unshift(`//*[@id=\"${element.getAttribute('id')}\"]`);\n return steps.join('/');\n }\n const siblings = element.parentElement ? Array.from(element.parentElement.children) : [];\n const similarElements = siblings.filter(sibling => element.nodeName === sibling.nodeName);\n const index = similarElements.length === 1 ? 0 : similarElements.indexOf(element) + 1;\n steps.unshift(index ? `${element.nodeName}[${index}]` : element.nodeName);\n }\n return '/' + steps.join('/');\n}\n\n\n/***/ })\n\n/******/ })).default";
//# sourceMappingURL=selectorEvaluatorSource.js.map
{
"name": "playwright-core",
"version": "0.14.0-next.1587678100542",
"version": "0.14.0-next.1587678340966",
"description": "A high-level API to automate web browsers",

@@ -5,0 +5,0 @@ "repository": "github:Microsoft/playwright",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc